Data | 架构图(Mermaid)¶
目的:用 mermaid 图直观展示 Claude Code 的架构。 使用:在支持 mermaid 的 Markdown 渲染器(GitHub、VSCode、Obsidian)里直接看。
1. 整体分层架构¶
graph TB
User[用户输入] --> CLI[CLI argv<br/>src/entrypoints/cli.tsx]
CLI -->|fast-path| Exit[直接退出<br/>--version等]
CLI -->|主路径| Main[main.tsx<br/>4683行]
Main -->|prefetches| Startup[启动期 prefetch<br/>startMdmRawRead<br/>startKeychainPrefetch]
Main --> Init[init.ts<br/>telemetry/config/MCP]
Init --> Repl[replLauncher.tsx]
Repl --> REPL[screens/REPL.tsx<br/>5005行]
subgraph 核心层
REPL --> State[state/<br/>store.ts + AppStateStore.ts]
REPL --> Hooks[hooks/<br/>85 个自定义 hook]
REPL --> Keybindings[keybindings/<br/>3 层键位系统]
REPL --> Components[components/<br/>150+ 业务组件]
end
subgraph 业务引擎
Query[query.ts<br/>1729行 async generator*]
QE[QueryEngine.ts<br/>1295行 class]
Tools[tools/<br/>43 个工具]
Tasks[tasks/<br/>多 agent 任务]
end
REPL --> Query
Query --> Tools
Query --> Tasks
Tools --> APIs[services/api/<br/>Anthropic SDK]
subgraph 扩展层
MCP[services/mcp/<br/>23 文件 MCP]
Bridge[bridge/<br/>IDE 集成]
Plugins[plugins/<br/>用户扩展]
Skills[skills/<br/>任务 prompt]
end
Tools --> MCP
REPL --> Bridge
State --> Plugins
State --> Skills
subgraph 平台层
Ink[ink/<br/>50+ 文件 TUI 框架]
Native[native-ts/<br/>3 N-API 模块]
Vendor[vendor/<br/>4 N-API 模块]
end
Components --> Ink
Bridge --> Native
Bridge --> Vendor
APIs --> Anthropic[Anthropic API]
MCP --> MCPext[外部 MCP server]
Bridge --> IDE[VSCode/JetBrains]
2. 模块依赖图¶
graph LR
Main[main.tsx] --> Init[entrypoints/init.ts]
Main --> Tools[tools.ts]
Main --> Repl[replLauncher.tsx]
Init --> State[state/]
Init --> MCP[services/mcp/]
Repl --> REPL[screens/REPL.tsx]
REPL --> PromptInput[components/PromptInput/]
REPL --> Messages[components/messages/]
REPL --> Keybindings[keybindings/]
REPL --> Hooks[hooks/]
REPL --> Query[query.ts]
REPL --> Cost[cost-tracker]
Query --> QE[QueryEngine.ts]
Query --> Tools2[Tool.ts]
Query --> API[services/api/claude.ts]
Query --> Compact[services/compact/]
Tools2 --> ToolsReg[tools.ts]
ToolsReg --> ToolImpls[tools/<ToolName>/]
ToolImpls --> API
State --> Store[store.ts]
State --> AppStateStore[AppStateStore.ts]
State --> AppState[AppState.tsx]
State --> Selectors[selectors.ts]
MCP --> MCPClient[MCPConnectionManager]
MCPClient --> MCPClientImpl[client.ts]
MCPClient --> Auth[auth.ts]
MCPClient --> Transport[InProcess/SdkControl]
REPL --> Bridge[bridge/]
Bridge --> BridgeMain[bridgeMain.ts]
Bridge --> ReplBridge[replBridge.ts]
Bridge --> Server[server/]
Bridge --> Remote[remote/]
3. 启动序列时序图¶
sequenceDiagram
participant U as User
participant Bun as Bun Runtime
participant CLI as cli.tsx
participant Main as main.tsx
participant Init as init.ts
participant Repl as replLauncher
participant REPL as REPL.tsx
participant Store as state/store
U->>Bun: bun run claude
Bun->>CLI: 加载 cli.tsx
CLI->>CLI: 解析 argv
alt fast-path (--version等)
CLI->>U: 输出版本号
else 主路径
CLI->>Main: 动态 import main.tsx
Main->>Main: profileCheckpoint('main_tsx_entry')
Main->>Main: startMdmRawRead() 并行
Main->>Main: startKeychainPrefetch() 并行
Main->>Init: init()
Init->>Init: 加载 ~/.claude/settings.json
Init->>Init: 加载 MCP 配置
Init->>Init: 初始化 telemetry
Init->>Init: 启动后台 housekeeping
Main->>Store: createStore(initialState)
Store-->>Main: store
Main->>Repl: launchRepl(store)
Repl->>REPL: <REPL /> mount
REPL->>Store: useAppState 订阅
REPL->>U: 渲染第一个画面
end
U->>REPL: 输入 prompt
REPL->>REPL: handleSubmit
REPL->>Query: query(messages, ...)
Query-->>REPL: 异步 stream events
REPL->>U: 流式渲染回复
4. 消息流时序图¶
sequenceDiagram
participant U as User
participant REPL as REPL
participant PI as PromptInput
participant Q as query()
participant QE as QueryEngine
participant T as Tool
participant API as Anthropic API
participant State as AppState
U->>PI: 输入 "列出当前目录文件"
PI->>REPL: onSubmit(text)
REPL->>State: setState({ messages: [...prev, userMsg] })
State->>State: onChange → 持久化
State-->>REPL: 通知 listeners
REPL->>Q: query(messages, systemPrompt, ctx, canUseTool)
loop 循环
Q->>API: POST /v1/messages (stream)
API-->>Q: content_block_delta (流式 token)
loop 每个 stream event
Q->>Q: 解析事件
Q-->>REPL: yield StreamEvent
REPL->>State: 更新 lastAssistantMessage
State-->>REPL: re-render
end
alt LLM 返回 tool_use
Q->>T: tool.call(input, ctx)
T->>T: validate(input)
T->>T: checkPermission
alt 需要用户批准
T-->>REPL: yield { type: 'permission_request' }
REPL->>U: 弹 PermissionRequest
U->>REPL: 批准
REPL-->>Q: 继续执行
end
T->>T: 执行工具
T-->>Q: yield { type: 'progress', ... }
Q-->>REPL: 透传
REPL->>U: 显示进度
T-->>Q: return ToolResult
Q->>State: 追加 tool_result 消息
Q->>Q: 继续下一轮
else LLM 完成
Q-->>REPL: 循环结束
end
end
5. MCP 通信时序图¶
sequenceDiagram
participant LLM
participant MCPTool as MCPTool
participant Mgr as MCPConnectionManager
participant T as InProcessTransport
participant Server as External MCP Server
LLM->>MCPTool: tool_use: mcp__github__create_issue
MCPTool->>MCPTool: 拆解 { server: 'github', tool: 'create_issue', input: {...} }
MCPTool->>Mgr: callTool('github', 'create_issue', input)
Mgr->>Mgr: 查 connections.get('github')
alt 已连接
Mgr->>T: request('tools/call', { name, arguments })
T->>Server: JSON-RPC over stdio/HTTP/InProcess
Server->>Server: 处理请求
Server-->>T: JSON-RPC response
T-->>Mgr: ToolResult
Mgr-->>MCPTool: ToolResult
else 未连接
Mgr->>Mgr: 触发重连
Mgr-->>MCPTool: 错误
end
MCPTool-->>LLM: return ToolResult
6. 状态机:会话状态¶
stateDiagram-v2
[*] --> Created: launchRepl
Created --> Loading: 加载 settings + MCP
Loading --> Ready: 初始化完成
Ready --> Thinking: 用户提交 prompt
Thinking --> Streaming: LLM 开始响应
Streaming --> Thinking: 完成一轮
Streaming --> ExecutingTool: LLM 返回 tool_use
Streaming --> Done: LLM 结束
ExecutingTool --> AwaitingPermission: 需要授权
AwaitingPermission --> ExecutingTool: 用户批准
AwaitingPermission --> ToolDenied: 用户拒绝
ToolDenied --> Thinking: 注入 denial 继续
ExecutingTool --> Thinking: 工具完成
ExecutingTool --> Running: 长跑任务(如 Bash)
Running --> ExecutingTool: 用户检查
Running --> Backgrounded: 用户后台化
Backgrounded --> Running: 用户恢复
Thinking --> Compressing: token 接近上限
Compressing --> Thinking: 压缩完成
Done --> Ready: 等下一轮
Ready --> Resumed: /resume
Resumed --> Ready: 历史加载完
Ready --> [*]: 用户退出
Ready --> [*]: 异常退出
7. 工具权限决策流¶
flowchart TD
Start[工具调用] --> Validate{validate(input)?}
Validate -->|失败| Reject[返回 is_error: true]
Validate -->|成功| PermCheck{检查权限规则}
PermCheck --> Allow[规则 allow]
PermCheck --> Deny[规则 deny]
PermCheck --> Ask[规则 ask 或无规则]
Allow --> Run[执行工具]
Deny --> DenialReturn[返回 denial ToolResult]
Ask --> UI[弹 PermissionRequest]
UI -->|用户批准| Run
UI -->|用户拒绝| DenialReturn
UI -->|用户更新规则| UpdateRule[更新 settings.json]
Run --> Progress{yield progress?}
Progress -->|是| YieldEvent[yield 给 REPL]
YieldEvent --> Progress
Progress -->|否| ToolResult[返回 ToolResult]
DenialReturn --> Inject[注入到 messages]
ToolResult --> Inject
Reject --> Inject
Inject --> Next[下一轮 LLM 调用]
8. 压缩触发时序图¶
sequenceDiagram
participant Query as query()
participant Compact as autoCompact
participant Group as grouping
participant LLM as LLM (small model)
participant State as AppState
Query->>Query: 累计 token 数
Query->>Compact: calculateTokenWarningState
Compact-->>Query: 'auto_compact'
Query->>Compact: runAutoCompact(messages)
Compact->>Group: groupMessagesForCompaction(messages)
Group-->>Compact: [{ messages, priority, tokens }]
Compact->>Compact: 选低优先级分组
Compact->>LLM: 小模型摘要(4K 输出)
LLM-->>Compact: summary
Compact->>Compact: buildPostCompactMessages(messages, summary)
Compact-->>Query: newMessages
Query->>State: setState({ messages: newMessages })
State->>State: postCompactCleanup
State->>State: 清 file cache + tool result cache
Query->>Query: 继续下一轮
9. 键位系统分层¶
graph TB
subgraph "L3: Ink useInput (兜底)"
L3[单字符键位: Esc, g, G, j, k]
end
subgraph "L2: Command Keybindings"
L2[命令模式快捷键<br/>在 / 后激活]
end
subgraph "L1: Global Keybindings"
L1[Ctrl+C 取消<br/>Ctrl+L 清屏<br/>Ctrl+O 全屏]
end
subgraph "L0: 组件级 useInput"
L0a[PromptInput 内部]
L0b[FuzzyPicker 内部]
L0c[Tabs 内部]
end
L3 --> L2
L2 --> L1
L1 --> L0a
L1 --> L0b
L1 --> L0c
L0a --> 实际触发[实际触发 action]
L0b --> 实际触发
L0c --> 实际触发
10. Bridge 双向通信¶
graph LR
subgraph Claude Code
REPL[REPL.tsx] --> Bridge[bridge/bridgeMain.ts]
ReplBridge[replBridge.ts] --> Bridge
end
subgraph "Transport Layer"
Bridge --> WS1[WebSocket / stdio / HTTP]
end
subgraph IDE
IDE[VSCode / JetBrains] --> WS2[WebSocket / stdio / HTTP]
end
WS1 <-->|JSON messages| WS2
Claude Code -->> IDE: tool_use, file diff
IDE -->> Claude Code: 用户选中, IDE 状态, 文件保存
11. 渲染管线¶
graph TB
A[React 组件树<br/>Box/Text/etc] --> B[React Reconciler<br/>src/ink/reconciler.ts]
B --> C[Virtual DOM<br/>src/ink/dom.ts]
C --> D[Layout 计算<br/>src/ink/layout/yoga.ts]
D --> E[Render Node to Output<br/>src/ink/render-node-to-output.ts]
E --> F[Y 缓冲<br/>ANSI 转义码]
F --> G[Diff with previous frame<br/>src/ink/renderer.ts]
G --> H[stdout<br/>终端显示]
12. 关键洞察¶
12.1 mermaid 的好处¶
- 纯文本(git diff 友好)
- GitHub / VSCode / Obsidian 直接渲染
- 易于修改(改一行就改图)
12.2 时序图 vs 流程图¶
- 时序图(sequenceDiagram)= 时间维度(谁先谁后)
- 流程图(flowchart/graph)= 控制流(分支、循环)
- 状态图(stateDiagram)= 状态机
12.3 复杂系统必看架构图¶
读 12 张图 = 读完 50 万行代码的"骨架"。