Kimi CLI 技術深掘
この記事は、Moonshot AIのオープンソースプロジェクト Kimi CLI のアーキテクチャ設計、コア実装、革新的な機能を総合的に分析し、開発者がこの強力なAIコマンドラインツールの内部構造を深く理解するのに役立ちます。
目次
- 導入 - Kimi CLIとは?
- アーキテクチャ概要 - 4つのコアシステム
- エージェントシステム - 柔軟な設定とロード
- KimiSoulエンジン - スマート実行の中枢
- ツールシステム - 拡張可能な機能ハブ
- ACPプロトコル - IDE統合の架け橋
- コア設計原則
導入 - Kimi CLIとは?
Kimi CLIは、Moonshot AIが開発したAI駆動型のコマンドラインインテリジェントアシスタントです。これは単なるコマンドラインのラッパーツールではなく、完全な AIネイティブ開発ツールエコシステム です。開発者を支援します:
- ターミナルからファイル操作、コード解析、Web検索などの複雑なタスクを実行
- 自然言語での対話でソフトウェア開発ワークフローを完了
- 複数のLLMプロバイダーをサポート(Moonshot AI、OpenAI、Claude、Gemini)
- 主流のIDE(Zedなど)と深く統合
従来のコマンドラインツールとは異なり、Kimi CLIの最も大きな特徴はその エージェンティックAIアーキテクチャ です。これはAIモデル、ツールシステム、実行エンジンを有機的に結合し、自律的に計画、実行、検証できる完全なインテリジェントエージェントを形成します。
バージョン:0.58 Technical Preview 技術スタック:Python 3.13+、非同期アーキテクチャ、モジュラーデザイン
アーキテクチャ概要 - 4つのコアシステム
詳細に入る前に、まずマクロレベルでKimi CLIの全体アーキテクチャを理解しましょう。
高レベルアーキテクチャ
graph TB
A[CLIエントリ: cli.py] --> B[アプリケーション層: KimiCLI];
B --> C[エージェントシステム];
B --> D[KimiSoul実行エンジン];
D --> E[ツールシステム];
B --> F[UI層];
subgraph "UI層(4つのモード)"
F --> G[Shellモード: インタラクティブCLI];
F --> H[Printモード: バッチ処理];
F --> I[ACPモード: IDE統合];
F --> J[Wireモード: 実験的プロトコル];
end
subgraph "エージェントシステム"
C --> K[エージェント設定をロード];
C --> L[システムプロンプト管理];
C --> M[ツール登録];
C --> N[サブエージェント管理];
end
subgraph "KimiSoulエンジン"
D --> O[実行ループ];
D --> P[コンテキスト管理];
D --> Q[エラーハンドリング];
D --> R[チェックポイント機構];
end
subgraph "ツールシステム"
E --> S[ファイル操作];
E --> T[シェルコマンド];
E --> U[Web検索];
E --> V[MCP統合];
E --> W[集約システム];
endコアデータフロー
flowchart LR
A[ユーザー入力] --> B[解析とルーティング];
B --> C{実行モードを選択};
C -->|Shell/Print| D[直接実行];
C -->|ACP| E[ACPサーバーを起動];
D --> F[セッション作成];
E --> F;
F --> G[エージェントをロード];
G --> H[ランタイムを初期化];
H --> I[依存性を注入];
I --> J[KimiSoulを作成];
J --> K[メイン実行ループ];
K --> L{ツール呼び出しが必要?};
L -->|はい| M[ツールを実行];
M --> N[結果を取得];
N --> O[コンテキストを更新];
O --> P{完了?};
L -->|いいえ| P;
P -->|いいえ| K;
P -->|はい| Q[結果を返却];
M --> R[並行処理];
R --> M;このアーキテクチャのコア思想は レイヤー化と分離 です:
- エージェントシステム が設定と初期化を担当
- KimiSoul は純粋な実行エンジン
- ツールシステム がプラガブルな機能を提供
- UI層 はビジネスロジックから完全に分離
この設計により、Kimi CLIは単純なコマンドライン対話から複雑なIDE統合まで、複数の使用シナリオをサポートしながらコードの明確さと保守性を維持できます。
エージェントシステム - 柔軟な設定とロード
エージェントシステムとは?
Kimi CLIでは、エージェント は完全なインテリジェントエージェント設定を意味します:
- システムプロンプト
- 利用可能なツールリスト
- サブエージェント定義
- ランタイムパラメーター
エージェントを設定可能にすることで、Kimi CLIは柔軟に異なる「AIパーソナリティ」を切り替えることができます:
- Coderエージェント:コード作成とリファクタリングに特化
- Debugエージェント:バグトリアージと修正に特化
- カスタムエージェント:ユーザー定義エージェント
設定ファイル構造
# agents/default/agent.yaml
version: 1
agent:
name: "Kimi CLI" # エージェント名
system_prompt_path: ./system.md # システムプロンプトファイル
system_prompt_args: # プロンプト引数
ROLE_ADDITIONAL: ""
tools: # 利用可能なツール
- "kimi_cli.tools.multiagent:Task"
- "kimi_cli.tools.todo:SetTodoList"
- "kimi_cli.tools.shell:Shell"
- "kimi_cli.tools.file:ReadFile"
- "kimi_cli.tools.file:WriteFile"
- "kimi_cli.tools.web:SearchWeb"
- "kimi_cli.tools.web:FetchURL"
subagents: # サブエージェント
coder:
path: ./sub.yaml
description: "一般的なソフトウェアエンジニアリングタスクに特化"エージェントロードフロー(シーケンスダイアグラム)
sequenceDiagram
participant CLI as KimiCLI
participant Loader as load_agent()
participant Spec as load_agent_spec()
participant SubLoader as サブエージェントロード
participant ToolLoader as ツールロード
participant MCP as MCPツール
CLI->>Loader: agent_file, runtime, mcp_configs
Loader->>Spec: YAML設定をパース
Spec-->>Loader: ResolvedAgentSpec
Note over Loader: システムプロンプトをロード
Loader->>Loader: _load_system_prompt()
Note over Loader: サブエージェントを再帰的にロード(固定サブエージェント)
loop 各サブエージェントごと
Loader->>SubLoader: load_agent(subagent.path)
SubLoader->>Loader: エージェントインスタンス
Loader->>Runtime.labor_market: add_fixed_subagent()
end
Note over Loader: ツールをロード(依存性注入)
Loader->>ToolLoader: tool_paths, dependencies
loop 各ツールごと
ToolLoader->>ToolLoader: importlib.import_module()
ToolLoader->>ToolLoader: リフレクションでインスタンス作成
ToolLoader->>ToolLoader: 自動的に依存性注入
ToolLoader->>ToolLoader: toolset.add(tool)
end
opt MCP設定がある場合
Loader->>MCP: MCPサーバーに接続
MCP->>Loader: ツールリストを取得
Loader->>Loader: toolsetに追加
end
Loader-->>CLI: エージェントインスタンス(全ツールを含む)依存性注入機構
Kimi CLIのツールシステムは 自動依存性注入 を採用しており、これはエージェントシステムの最もエレガントな側面の1つです:
def _load_tool(tool_path: str, dependencies: dict) -> ToolType | None:
"""ツールをロードし、依存性を自動注入"""
module_name, class_name = tool_path.rsplit(":", 1)
module = importlib.import_module(module_name)
cls = getattr(module, class_name)
args = []
for param in inspect.signature(cls).parameters.values():
# 全ポジションパラメータを依存性として扱う
if param.annotation in dependencies:
args.append(dependencies[param.annotation])
return cls(*args) # 自動依存性注入依存性コンテナが含むもの:
Runtime: ランタイムコンテキストConfig: 設定情報Approval: 承認システムSession: セッションデータDenwaRenji: DメールシステムLaborMarket: サブエージェント管理
ツール定義例:
class Shell(CallableTool2[Params]):
def __init__(self, approval: Approval, **kwargs):
# approvalパラメータはRuntimeから自動注入される
self._approval = approval
async def __call__(self, params: Params) -> ToolReturnType:
# 承認を使用してユーザー確認を要求
if not await self._approval.request(...):
return ToolRejectedError()LaborMarket: サブエージェント「労働市場」
LaborMarket は、利用可能な全サブエージェントを管理する革新的な設計です:
graph TB
A[ユーザーがTaskツールを呼び出す] --> B[Task実行];
B --> C{サブエージェントを検索};
C -->|見つかった| D[固定サブエージェントを取得];
C -->|見つからない| E[動的サブエージェントを作成];
D --> F[サブエージェントをロード];
F --> G[独立コンテキストを作成];
G --> H[run_soul() 実行];
subgraph "サブエージェントタイプ"
I[固定サブエージェント] --> J[共有設定];
I --> K[独立DenwaRenji];
K --> L[独立LaborMarket];
E --> M[動的サブエージェント];
M --> N[ランタイムを複製];
N --> O[メインLaborMarketを共有];
endなぜサブエージェントが必要か?
- タスク分解: 複雑なタスクを専門エージェントに委任できる
- コンテキスト分離: サブエージェントは独立した履歴を持ち、メインコンテキストの中断を避ける
- 単一責任: 各エージェントは特定のドメインに集中
KimiSoulエンジン - スマート実行の中枢
KimiSoulはシステム全体で最も重要なコンポーネントです。これはAIエージェントの「心臓部」であり、すべての推論、ツール呼び出し、コンテキスト管理を担当します。
コア責任
class KimiSoul(Soul):
"""The soul of Kimi CLI."""
# 1. 実行ループを管理
async def run(self, user_input: str):
await self._checkpoint()
await self._context.append_message(user_message)
await self._agent_loop() # メインループ
# 2. 各推論ステップを処理
async def _step(self) -> bool:
result = await kosong.step(
self._runtime.llm.chat_provider,
self._agent.system_prompt,
self._agent.toolset,
self._context.history
)
# ツール呼び出し、結果、コンテキスト更新を処理
# 3. コンテキストライフサイクルを管理
async def _grow_context(self, result, tool_results):
await self._context.append_message(result.message)
await self._context.append_message(tool_messages)
# 4. コンテキストを圧縮
async def compact_context(self):
# コンテキストが長すぎる場合に圧縮実行ループ詳細(シーケンスダイアグラム)
sequenceDiagram
participant User as ユーザー
participant Soul as KimiSoul
participant LLM as LLMプロバイダー
participant Context as コンテキストストレージ
participant Tools as ツールコレクション
participant Wire as イベントバス
User->>Soul: 入力 "カレントディレクトリのファイルを一覧表示"
Soul->>Context: checkpoint() チェックポイント作成
Soul->>Context: append_message(user_message)
loop エージェントループ(ステップ 1..N)
Soul->>Soul: _step()
opt コンテキストが長すぎる
Soul->>Wire: CompactionBegin
Soul->>Soul: compact_context()
Soul->>Wire: CompactionEnd
end
Soul->>Context: checkpoint()
Soul->>Wire: StepBegin(n=step_no)
Soul->>LLM: kosong.step() 呼び出し
LLM-->>Soul: StepResult
loop ツール呼び出し並行実行
Soul->>Tools: handle(tool_call)
Tools-->>Soul: ToolResult
Soul->>Wire: ToolResultイベントを送信
end
Soul->>Soul: _grow_context()
Soul->>Context: append_message(result)
Soul->>Context: append_message(tool_results)
opt DenwaRenjiにDメールがある
Soul->>Soul: BackToTheFutureをスロー
Soul->>Context: revert_to(checkpoint_id)
Soul->>Context: append_message(dmail)
end
opt ツールが拒否された
Soul->>Wire: 拒否イベントを送信
Soul->>Soul: return True (ループ終了)
end
opt ツール呼び出しがない
Soul->>Soul: return True (完了)
end
end
Soul-->>User: 最終回答を返却チェックポイントと「タイムトラベル」機構
KimiSoulの最も革新的な設計の1つは チェックポイント機構 であり、システムが「過去に戻る」ことを可能にします。
仕組み:
# 1. チェックポイント作成
async def checkpoint(self, add_user_message: bool):
"""各ステップ前にチェックポイントを作成"""
checkpoint_id = self._next_checkpoint_id
self._next_checkpoint_id += 1
# ディスクに書き込み
await f.write(json.dumps({"role": "_checkpoint", "id": checkpoint_id}) + "\n")
if add_user_message:
await self.append_message(
Message(role="user", content=[system(f"CHECKPOINT {checkpoint_id}")])
)ユースケース:Dメール
graph LR
A[SendDMailツール] --> B[過去にDメール送信];
B --> C[checkpoint_id指定];
C --> D[KimiSoulがキャッチ];
D --> E[BackToTheFutureをスロー];
E --> F[revert_to(checkpoint_id)];
F --> G[後続コンテンツを削除];
G --> H[再実行];想像シナリオ:
- ユーザーが尋ねる:「この関数をリファクタリングして」
- AIが実行開始、ステップ3で気づく:「待てよ、まずファイルをバックアップしないと」
- AIがチェックポイント1にDメールを送信
- システムがチェックポイント1に戻り、今度はリファクタリングの前にバックアップ
これはSFアニメ「Steins;Gate」のDメールのように、AIが過去の自分にメッセージを送れるんです!
エラーハンドリングとリトライ
KimiSoulは堅牢なエラーハンドリングを備えています:
@tenacity.retry(
retry=retry_if_exception(_is_retryable_error),
wait=wait_exponential_jitter(initial=0.3, max=5, jitter=0.5),
stop=stop_after_attempt(max_retries),
reraise=True
)
async def _kosong_step_with_retry() -> StepResult:
"""LLM呼び出しを自動リトライ"""
return await kosong.step(...)リトライ可能なエラー:
- API接続エラー
- タイムアウトエラー
- 503サービス不可
- レート制限(429)
リトライ不可能なエラー:
- 無効なAPIキー
- サポートされていないモデル
- コンテキストオーバーフロー
ツールシステム - 拡張可能な機能ハブ
ツールシステムアーキテクチャ
ツールシステムの理念は: 全てがツール、そして全てのツールはプラガブル です。
graph TB
A[ツールベースクラス] --> B[CallableTool];
A --> C[CallableTool2[Params]];
B --> D[Shell];
B --> E[ReadFile];
C --> F[Task];
C --> G[SearchWeb];
subgraph "ツールレジストリ"
H[KimiToolset] --> I[_inner: SimpleToolset];
I --> J[add(tool)];
end
subgraph "依存性注入"
K[Runtime] --> L[ツール依存性];
M[Approval] --> L;
N[BuiltinSystemPromptArgs] --> L;
end
subgraph "MCP統合"
O[MCPクライアント] --> P[MCPTool];
P --> H;
end
style A fill:#f96
style H fill:#bbf
style L fill:#bfbツールカテゴリ
1. ファイル操作
# ファイル読み取り
ReadFile(path="/absolute/path/to/file.py", line_offset=1, n_lines=100)
# ファイル書き込み
WriteFile(path="/absolute/path", file_text="content", line_count_hint=1)
# ファイル検索
Glob(pattern="src/**/*.py")
# 内容検索
Grep(pattern="TODO|FIXME", path="/workspace", -n=true)
# 文字列置換
StrReplaceFile(path="/absolute/path", old_str="", new_str="")セキュリティ機能:
- 絶対パスを指定する必要あり(パストラバーサル防止)
- ファイルサイズ制限(100KB)
- 行数制限(1000行)
- 行の長さ制限(2000文字)
2. シェルコマンド
Shell(command="git status", timeout=60)セキュリティ機能:
- ユーザー承認が必要(yoloモードを除く)
- タイムアウト制御(1-300秒)
- ストリーミング出力(リアルタイムstdout/stderr)
- 最大タイムアウト:5分
3. Webツール
# Web検索
SearchWeb(query="Python 3.13 の新機能")
# URLコンテンツ取得
FetchURL(url="https://github.com/MoonshotAI/kimi-cli")4. タスク管理
# ToDoリスト設定
SetTodoList(todos=[
{"content": "コード構造の分析", "status": "completed"},
{"content": "ユニットテストの作成", "status": "in_progress"}
])5. サブエージェントツール
# タスクをサブエージェントに委任
Task(
description="コードベース構造を分析", # 簡潔な説明
subagent_name="coder", # サブエージェント名
prompt="src/ディレクトリ構造を詳細に分析し、各モジュールの責務を要約"
)ツール呼び出しフロー(Shell例)
sequenceDiagram
participant Soul as KimiSoul
participant ToolSet as KimiToolset
participant Shell as Shellツール
participant Approval as 承認システム
participant Process as サブプロセス
participant Wire as イベントバス
Soul->>ToolSet: toolset.handle(tool_call)
ToolSet->>Shell: current_tool_call.set()
Shell->>Shell: ToolResultBuilder()
Shell->>Approval: request("Shell", "シェルコマンド実行", description)
opt YOLOモード
Approval-->>Shell: True (自動承認)
else 通常モード
Approval->>Wire: ApprovalRequest
Wire-->>Approval: ApprovalResponse
Approval-->>Shell: True/False
end
alt 拒否された
Shell-->>ToolSet: ToolRejectedError()
else 承認された
Shell->>Process: asyncio.create_subprocess_shell()
par ストリーム読み取り
Process-->>Shell: stdout (行ごと)
Shell->>Shell: builder.write(line)
Shell->>Wire: 出力を送信
Process-->>Shell: stderr (行ごと)
Shell->>Shell: builder.write(line)
Shell->>Wire: 出力を送信
end
Process-->>Shell: exitcode
opt exitcode == 0
Shell-->>ToolSet: builder.ok("成功")
else exitcode != 0
Shell-->>ToolSet: builder.error(f"失敗: {exitcode}")
end
end
ToolSet->>ToolSet: current_tool_call.reset()
ToolSet-->>Soul: HandleResult
Soul->>Wire: ToolResultを送信MCP (Model Context Protocol) 統合
MCPはAnthropicのオープンプロトコルで、AIモデルとツールの接続を標準化します。
# MCPサーバー設定
{
"mcpServers": {
"context7": {
"url": "https://mcp.context7.com/mcp",
"headers": {
"CONTEXT7_API_KEY": "YOUR_API_KEY"
}
},
"chrome-devtools": {
"command": "npx",
"args": ["-y", "chrome-devtools-mcp@latest"]
}
}
}
# 起動時にロード
kimi --mcp-config-file /path/to/mcp.jsonMCP統合フロー:
graph TB
A[MCPサーバー設定] --> B[MCP設定ロード];
B --> C[MCPクライアント接続];
C --> D[利用可能なツール取得];
D --> E[MCPToolラッパー作成];
E --> F[toolsetに追加];
subgraph "拡張機能"
F --> G[Chrome DevTools];
F --> H[Context7ドキュメント];
F --> I[GitHub API];
F --> J[データベース接続];
end
A -- "統一ツールインターフェース" --> K[全ツールを均質化];
style A fill:#f96
style K fill:#bbfMCP統合により、Kimi CLIの能力は無限に拡張可能になります。MCPプロトコルに準拠する任意のツールをシームレスに統合できます。含まれるもの:
- データベースクエリツール
- API呼び出しツール
- ブラウザ自動化ツール
- ドキュメント検索ツール
ACPプロトコル - IDE統合の架け橋
Agent Client Protocol (ACP) は、Kimi CLIの最重要な革新の1つです。LSP (Language Server Protocol) がエディタと言語サーバーの通信を標準化するように、ACPはエディタとAIエージェントの通信を標準化します。
ACPの位置づけ: エディタ ↔ エージェントのLSP
graph TB
subgraph "LSPアナロジー"
A[エディタ] -->|LSP| B[言語サーバー];
B --> A;
end
subgraph "ACP定義"
C[エディタ/IDE] -->|ACP| D[AIエージェント];
D --> C;
end
style A fill:#f9f
style C fill:#bbfACPコア機能:
- JSON-RPC 2.0: JSON-RPC 2.0プロトコルに基づく
- StdIO転送: 標準入出力経由での通信
- ストリーミングイベント: リアルタイムストリーミング応答をサポート
- ツール統合: 標準化されたツール呼び出し表示
- 承認制御: ユーザー確認メカニズム
- セッション管理: ステートフルな対話
ACPプロトコルスタック
graph TB
subgraph "アプリケーション層"
A[Zedエディタ] --> B[ユーザーインタラクション];
end
subgraph "プロトコル層 (ACP v1)"
C[初期化] --> D[セッション管理];
D --> E[プロンプト実行];
E --> F[ストリーミング更新];
F --> G[ツール呼び出し];
G --> H[承認リクエスト];
end
subgraph "転送層 (JSON-RPC)"
I[リクエスト] --> J[レスポンス];
I --> K[通知];
end
subgraph "物理層"
L[Stdin] --> M[Stdout];
end
subgraph "Kimi CLI"
N[ACPServer] --> O[ACPAgent];
O --> P[イベント変換];
P --> Q[KimiSoul];
end
style A fill:#f96
style N fill:#bbf
style Q fill:#bfbZed統合例
設定:
// ~/.config/zed/settings.json
{
"agent_servers": {
"Kimi CLI": {
"command": "kimi",
"args": ["--acp"],
"env": {}
}
}
}ワークフロー:
sequenceDiagram
participant User as ユーザー
participant Zed as Zedエディタ
participant ACP as ACPクライアント
participant Kimi as Kimi CLI
participant Soul as KimiSoul
participant LLM as Moonshot AI
User->>Zed: エージェントパネルを開く
Zed->>ACP: kimi --acpプロセスを起動
ACP->>Kimi: initialize() リクエスト
Kimi-->>ACP: InitializeResponse
ACP->>Kimi: session/new リクエスト
Kimi-->>ACP: NewSessionResponse(sessionId)
User->>Zed: 質問入力 "このコードロジックを説明して"
Zed->>ACP: session/prompt リクエスト
ACP->>Kimi: メッセージを転送
Kimi->>Soul: run_soul(prompt)
Soul->>LLM: リクエスト送信
LLM-->>Soul: ストリーミング応答
loop リアルタイムストリーミング出力
Soul-->>Kimi: TextPart/ThinkPart
Kimi-->>ACP: AgentMessageChunk/AgentThoughtChunk
ACP->>Zed: テキストを表示
end
opt ツール呼び出しが必要
Soul-->>Kimi: ToolCall
Kimi-->>ACP: ToolCallStart
ACP->>Zed: ツール呼び出しを表示
Soul->>Kimi: ツール実行
Soul-->>Kimi: ToolResult
Kimi-->>ACP: ToolCallUpdate
ACP->>Zed: 結果を表示
end
Soul-->>Kimi: 完了
Kimi-->>ACP: PromptResponse
ACP->>Zed: 最終回答を表示ACPイベント変換詳細
ACPの最も複雑な部分は、Kimi CLIの内部イベントをACP標準イベントに変換することです。
内部Wireイベント → ACPプロトコルイベント:
| 内部イベント | ACPイベント | 説明 |
|---|---|---|
TextPart | AgentMessageChunk | AI出力テキスト |
ThinkPart | AgentThoughtChunk | AI思考プロセス |
ToolCall | ToolCallStart | ツール呼び出し開始 |
ToolCallPart | ToolCallProgress | パラメータストリーミング更新 |
ToolResult | ToolCallUpdate | ツール呼び出し完了 |
ApprovalRequest | RequestPermissionRequest | ユーザー承認が必要 |
# 主要な変換ロジック例
async def _send_tool_call(self, tool_call: ToolCall):
# ツール呼び出し状態を作成
state = _ToolCallState(tool_call)
self.run_state.tool_calls[tool_call.id] = state
# ACPクライアントに送信
await self.connection.sessionUpdate(
acp.SessionNotification(
sessionId=self.session_id,
update=acp.schema.ToolCallStart(
toolCallId=state.acp_tool_call_id, # UUID
title=state.get_title(), # "Shell: ls -la"
status="in_progress",
content=[...]
)
)
)_ToolCallState: インテリジェントな状態管理
class _ToolCallState:
def __init__(self, tool_call: ToolCall):
# 一意のACPツール呼び出しIDを生成
self.acp_tool_call_id = str(uuid.uuid4())
# ツール呼び出し引数を解析
self.tool_call = tool_call
self.args = tool_call.function.arguments or ""
self.lexer = streamingjson.Lexer()
def get_title(self) -> str:
"""タイトルを動的に生成"""
tool_name = self.tool_call.function.name
subtitle = extract_key_argument(self.lexer, tool_name)
# 例: "Shell: git status" または "ReadFile: src/main.py"
return f"{tool_name}: {subtitle}"ACP承認フロー
sequenceDiagram
participant Soul as KimiSoul
participant Tool as Shellツール
participant Approval as 承認システム
participant Wire as Wire
participant ACP as ACPAgent
participant ACPClient as ACPクライアント
participant Editor as IDE
Soul->>Tool: __call__()
Tool->>Approval: request("Shell", "シェルコマンド実行", "ls -la")
Approval->>Wire: ApprovalRequest
Wire-->>ACP: wire.receive()
ACP->>ACPClient: requestPermission({
toolCallId: "uuid",
options: [
{optionId: "approve", name: "一度承認", kind: "allow_once"},
{optionId: "approve_for_session", name: "このセッションで承認", kind: "allow_always"},
{optionId: "reject", name: "拒否", kind: "reject"}
]
})
ACPClient->>Editor: 承認ダイアログを表示
Editor-->>ACPClient: ユーザー選択
ACPClient-->>ACP: RequestPermissionResponse
alt ユーザーが承認
ACP->>Wire: ApprovalResponse.APPROVE
Wire-->>Approval: True
Approval-->>Tool: True
Tool->>Tool: コマンドを実行
else ユーザーが拒否
ACP->>Wire: ApprovalResponse.REJECT
Wire-->>Approval: False
Approval-->>Tool: False
Tool-->>Tool: ToolRejectedError()
endこの承認メカニズムは細粒度の制御を提供し、AIがユーザー認可のない危険な操作を実行しないことを保証します。
コア設計原則
Kimi CLIのソースコードを徹底的に分析した結果、以下のコア設計原則をまとめました:
1. レイヤー化と分離
graph TB
A[CLIエントリ] --> B[KimiCLIアプリ層];
B --> C[エージェントシステム];
B --> D[KimiSoulエンジン];
D --> E[ツールシステム];
B --> F[UI層];
subgraph "完全に分離"
C
D
E
F
end
style A fill:#f96
style F fill:#bbf
style E fill:#bfbレイヤー化の利点:
- テスタビリティ: 各層を個別にテスト可能
- 拡張性: UIモードの追加/削除がコアロジックに影響しない
- 保守性: 明確な責任範囲
2. 依存性注入と自動配線
# ツールはタイプアノテーションで依存性を宣言
class ReadFile(CallableTool2[Params]):
def __init__(self, builtin_args: BuiltinSystemPromptArgs):
self._work_dir = builtin_args.KIMI_WORK_DIR
# エージェントシステムが依存性を自動的に発見・注入
def _load_tool(tool_path: str, dependencies: dict):
for param in inspect.signature(cls).parameters.values():
if param.annotation in dependencies:
args.append(dependencies[param.annotation])
return cls(*args)利点:
- ボイラープレートコード削減
- テスタビリティ向上(モックしやすい)
- 柔軟なツール構成
3. タイムトラベル(チェックポイント)
# 各ステップ前にチェックポイント作成
await self._checkpoint() # checkpoint_id: 0
# ... 実行 ...
await self._checkpoint() # checkpoint_id: 1
# ... 問題を発見 ...
# 過去にDメール
await self._context.revert_to(1)革新性:
- セーフティネットを提供
- 「元に戻す」を実現
- サブエージェントタスク管理をサポート
4. Wire通信抽象化
def wire_send(msg: WireMessage) -> None:
"""SoulとUIを分離"""
wire = get_wire_or_none()
wire.soul_side.send(msg)
# Shell UIが直接処理
msg = await wire.ui_side.receive()
# ACP UIが変換後にエディタに送信
await connection.sessionUpdate(convert_to_acp(msg))利点:
- SoulはUIタイプを気にしない
- 複数のUI実装をサポート
- イベント駆動アーキテクチャ
5. ACP: AI時代のLSP
ACPはエディタ-AI通信を標準化します。LSPがエディタ-言語サーバー通信を標準化したのと同様です。
コアバリュー:
- エコシステム相互運用性: どのACPエディタでもKimi CLIを使用可能
- ストリーミング体験: AI思考プロセスのリアルタイム表示
- セキュリティ制御: ユーザー承認メカニズム
- ツールビジュアライゼーション: 構造化されたツール呼び出し表示
6. LLMプロバイダー抽象化
複数のLLMプロバイダーをサポート:
def create_llm(provider, model):
match provider.type:
case "kimi":
return Kimi(model, base_url, api_key)
case "openai_responses":
return OpenAIResponses(model, base_url, api_key)
case "anthropic":
return Anthropic(model, base_url, api_key)
case "google_genai":
return GoogleGenAI(model, base_url, api_key)利点:
- ベンダーロックインを避ける
- 柔軟なモデル切り替え
- セルフホストモデルをサポート
ユースケース分析
最も適している:
ターミナル開発ワークフロー
bashkimi > このエラーログを分析し、根本原因を特定して > テストを実行し、失敗したケースを修正 > このコードのパフォーマンスを最適化IDEインテリジェントアシスタント
json// Zed設定後 { "agent_servers": { "Kimi CLI": { "command": "kimi", "args": ["--acp"] } } }バッチ自動化
bashkimi --print -c "全Pythonファイルをレビューし、PEP8違反を修正"マルチツール協調: AIは複数のツール(ファイル操作、Shell、検索、承認、取り消し)を持ち、複雑なタスクを自動計画
あまり適していない:
- 単純なQ&A: 直接ChatGPT Webインターフェースの方が便利
- 非対話型: 単純なgrep/lsコマンドは従来のツールの方が速い
- 超高性能: Python非同期にオーバーヘッドがある
セキュリティ設計
パス制限
- ファイル操作は絶対パスを使用する必要あり
- パストラバーサル攻撃を防ぐ
承認メカニズム
- Shellコマンドには承認が必要
- ファイル変更には承認が必要
- yoloモードをサポート(スクリプトシナリオ用)
タイムアウト制御
- Shellコマンド最大5分タイムアウト
- 長時間ハングを防ぐ
コンテキスト制限
- コンテキスト上限に近づくと自動圧縮
- トークン浪費を防ぐ
結論
Kimi CLIは、Moonshot AIの優れたツール以上の存在です。これはアーキテクチャがエレガントで、設計が革新的なAIネイティブアプリケーションの優れた例です。
Kimi CLIを学ぶことで、以下が理解できます:
- AIアプリケーションはレイヤー化すべき: 設定層、実行層、ツール層、UI層を明確に分離
- 依存性注入は柔軟性の鍵: 自動配線ツールは容易に拡張可能
- チェックポイントはタイムトラベルの魔術: 安全網を提供し、複雑なタスクをサポート
- 標準化プロトコルはエコシステムの基盤: ACPがエディタ-AI通信を可能に
リソース:
Kimi CLIは、次世代開発ツールの未来を表しています:単なるツールではなく、理解し、計画し、実行できるインテリジェントなパートナーです。
著者: Claude Code + Kimi K2 Thinking