跳转至

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 万行代码的"骨架"。