背景
🚨 刚刚,Claude Code 源码被全网公开了。
不是黑客攻击,是一次典型的发布失误——source map 没剥离干净。
Anthropic 发布的 @anthropic-ai/claude-code 2.1.88 版本里,带了一个 60MB 的 source map 文件,直接指向内部 R2 存储的完整源码。装个包,顺手就能拉下来。
1900+ 个文件,51 万+ 行 TypeScript 代码,就这样摊在了所有人面前——CLI 核心、工具系统、多 Agent 协调、IDE Bridge、权限控制、插件系统,一个不落。
更值得注意的:一些尚未发布的功能也跟着曝光了——Agent 新特性、语音模式、远程协作、持久记忆……
官方目前暂无公告,但 npm 上的 map 文件已被紧急移除。
但是对开发者来说,这是一次绝佳的学习机会。这次我们先关注整体流程,后续我也会继续出专栏来逐步拆解每个细节,关注我不迷路 💗
基于 @anthropic-ai/claude-code@2.1.88 版本的源代码分析
Claude Code 源码分析
基于 @anthropic-ai/claude-code@2.1.88 源码
项目结构
restored-src/
├── src/
│ ├── main.tsx # 入口文件
│ ├── replLauncher.tsx # REPL 启动
│ ├── components/ # React 组件
│ ├── screens/ # 界面(主要是REPL)
│ ├── coordinator/ # 协调器模式
│ ├── state/ # 状态管理
│ ├── tasks/ # 任务系统
│ ├── tools/ # 工具集
│ ├── services/ # API/MCP/Analytics等
│ ├── bridge/ # 远程桥接
│ ├── commands/ # 命令系统
│ ├── skills/ # 技能
│ ├── plugins/ # 插件
│ └── ...
启动流程
main.tsx 是入口。先跑一堆预检:
enableConfigs()启用配置系统applySafeConfigEnvironmentVariables()应用安全的环境变量- 并行启动 MDM 读取、Keychain 预取等耗时操作
- 初始化遥测、检测 Git 仓库
- 等待策略限制加载完成
launchRepl()启动 REPL,渲染 React 组件树
启动阶段的设计思路是把能并行的都并行化,减少等待时间。
flowchart TD
A[main.tsx 入口] --> B[enableConfigs 配置系统]
B --> C[applySafeConfigEnvironmentVariables]
C --> D[并行启动预加载任务]
D --> E[startMdmRawRead]
D --> F[startKeychainPrefetch]
D --> G[profileCheckpoint]
E --> H[初始化遥测]
F --> H
G --> H
H --> I[检测环境和仓库]
I --> J[等待策略限制加载]
J --> K[launchRepl]
K --> L[渲染 App 组件]
L --> M[REPL 主循环]
REPL 主循环
用户输入后分两路:
- Slash 命令:直接执行对应的命令模块
- 普通文本:进
handlePromptSubmit→query()处理
query 是核心。它构建消息上下文、调用 Claude API、处理流式响应。API 返回的事件类型主要有三种:tool_use(需要执行工具)、content_block(文本内容)、message_delta(完成标记)。
工具执行走 runTools,内部会根据工具类型决定并发还是串行:读文件、glob、grep 这些可以并行;写文件、agent 调用得串行来。
工具结果返回给 API,继续下一轮对话,直到 API 返回完成。
flowchart TD
A[REPL 渲染] --> B[等待用户输入]
B --> C{输入类型}
C -->|Slash命令| D[执行命令]
C -->|普通文本| E[handlePromptSubmit]
E --> F[query 处理]
F --> G[构建消息上下文]
G --> H[调用 Claude API]
H --> I{流式事件}
I -->|tool_use| J[runTools 执行工具]
I -->|content_block| K[收集文本]
I -->|message_delta| L[完成标记]
J --> M{工具类型}
M -->|读文件/grep| N[并发执行]
M -->|写文件/agent| O[串行执行]
N --> P[结果返回API]
O --> P
P --> H
K --> Q[后处理]
L --> Q
Q --> R[autoCompact 检查]
R --> S[保存会话]
状态管理
AppStateStore 是核心状态仓库,用 React Context 的方式提供。AppState 里装的东西挺杂的:
settings:用户配置tasks:正在跑的所有任务mcp:MCP 客户端、工具、资源plugins:插件状态toolPermissionContext:权限上下文mainLoopModel:当前用的模型
classDiagram
class AppStateStore {
+getState()
+setState(updater)
+subscribe(listener)
}
class AppState {
+settings
+tasks
+mcp
+plugins
+toolPermissionContext
+mainLoopModel
}
class AppStateProvider {
+children
+initialState
+onChangeAppState
}
AppStateStore --> AppState
AppStateProvider --> AppStateStore
任务有六种类型:local_bash、local_agent、remote_agent、in_process_teammate、local_workflow、monitor_mcp。
stateDiagram-v2
[*] --> pending
pending --> running
running --> completed
running --> failed
running --> killed
completed --> [*]
failed --> [*]
killed --> [*]
工具系统
tools.ts 是入口,定义了所有内置工具。分类挺清晰的:
- 文件操作:Read、Edit、Write、Glob、Grep、NotebookEdit
- 终端操作:Bash、LSP
- 网络操作:WebFetch、WebSearch
- 任务管理:Create、Stop、List、Get、Update
- Agent 系统:Agent(启动子agent)、SendMessage(给 agent 发消息)、TeamCreate、TeamDelete
- 其他:AskUserQuestion、Config、ExitPlanMode、SkillTool 等
flowchart TB
subgraph 文件操作
A1[Read]
A2[Edit]
A3[Write]
A4[Glob]
A5[Grep]
A6[NotebookEdit]
end
subgraph 终端操作
B1[Bash]
B2[LSP]
end
subgraph 网络操作
C1[WebFetch]
C2[WebSearch]
end
subgraph 任务管理
D1[Create]
D2[Stop]
D3[List]
D4[Get]
D5[Update]
end
subgraph Agent系统
E1[Agent]
E2[SendMessage]
E3[TeamCreate]
E4[TeamDelete]
end
subgraph 其他
F1[AskUserQuestion]
F2[Config]
F3[ExitPlanMode]
F4[SkillTool]
end
工具编排的核心在 services/tools/toolOrchestration.ts 的 runTools 函数。它先把工具调用分区,然后并发执行只读工具,串行执行可能产生副作用的工具。
sequenceDiagram
participant Query
participant Tools
participant Bash as Bash/Glob/Grep
participant Write as FileWrite/Agent
Query->>Tools: runTools(toolUseBlocks)
Tools->>Tools: partitionToolCalls
alt 只读工具
Tools->>Bash: 并行执行
Bash-->>Tools: results
else 有副作用的工具
Tools->>Write: 串行执行
Write-->>Tools: result
end
Tools-->>Query: MessageUpdate
查询引擎
query.ts 是查询引擎的入口。主要步骤:
- 消息预处理,包括上下文拼装
microcompact压缩历史消息- 调用
queryModelWithStreaming - 处理流事件:工具调用、文本内容,完成标记
- 工具执行完后把结果发回 API
- 自动 compact 检查,决定是否压缩上下文
- 增量保存会话状态
flowchart TD
A[用户输入] --> B[query]
B --> C[消息预处理]
C --> D[microcompact 压缩]
D --> E[queryModelWithStreaming]
E --> F{流式事件}
F -->|tool_use| G[runTools]
F -->|content_block| H[收集文本]
F -->|message_delta| I[完成标记]
G --> J{还有待执行工具?}
J -->|是| E
J -->|否| K[后处理]
H --> K
I --> K
K --> L[autoCompact 检查]
L --> M[保存会话]
M --> N[返回结果]
API 调用在 services/api/claude.ts,用的是 Anthropic 的流式 API。
sequenceDiagram
participant Query
participant API as Claude API
participant Auth
Query->>API: queryModelWithStreaming
API->>Auth: 获取 API Key
Auth-->>API: API Key
API->>API: 构建请求
API->>API: 发送流式请求
API-->>Query: Stream Events
MCP 系统
MCP (Model Context Protocol) 在 services/mcp/ 下实现了一套完整的东西:
- 传输层:SDK Control Transport(连接外部 MCP 服务器)、InProcess Transport(进程内通信)
- 认证:OAuth 支持
- 功能:工具发现、资源管理、提示词模板、授权处理
flowchart TD
subgraph MCPClient
A[MCP Client]
end
subgraph 传输层
B[SDK Control Transport]
C[InProcess Transport]
end
subgraph 功能
D[工具发现]
E[资源管理]
F[提示词模板]
G[授权处理]
end
subgraph 认证
H[OAuth]
end
A --> B
A --> C
A --> H
A --> D
A --> E
A --> F
A --> G
MCP 客户端负责管理多个服务器连接,发现工具和资源供模型使用。
命令系统
commands.ts 注册了所有命令,类型分四种:
prompt:提示词类型,展开后发给模型local:本地执行,返回文本结果local-jsx:渲染 React 组件info:信息展示
flowchart TD
A[commands.ts 加载] --> B[静态命令列表]
B --> C[加载 skills 目录]
C --> D[加载插件命令]
D --> E[加载工作流]
E --> F[加载 bundle 技能]
F --> G[按可用性过滤]
G --> H[去重合并]
H --> I[getCommands 返回]
命令来源有多个:内置命令、skills 目录下的技能、插件提供的命令,工作流脚本、bundle 技能。加载顺序是:先聚合所有来源,再按可用性过滤,最后去重。
协调器模式
启用 COORDINATOR_MODE 后,Claude Code 变成协调者,指挥 worker agent 干活。Coordinator 接收用户任务,分派给多个 worker 并行研究/实现,最后汇总结果。
flowchart TD
A[Coordinator Mode] --> B[接收用户任务]
B --> C{任务类型}
C -->|研究| D[spawn Worker]
C -->|实现| E[spawn Worker]
C -->|直接回答| F[响应用户]
D --> G[并行执行]
E --> G
G --> H{Worker 通知}
H -->|completed| I[汇总结果]
H -->|failed| J[重试]
H -->|需要继续| K[SendMessage]
I --> L[报告用户]
J --> G
K --> G
Worker 有两种模式:
- 简单模式:只有 Bash、Read、Edit
- 完整模式:所有工具 + MCP + Skills
Coordinator 的 prompt 里写了很清楚的工作模式,不抢功、只汇总。
桥接系统
Bridge 实现了两件事:远程控制(手机/网页操控桌面 Claude)和远程会话(桌面 Claude 在网页上跑)。
flowchart TD
subgraph Bridge架构
A[本地 Claude Code]
B[Bridge API Client]
C[Session Spawner]
D[Claude.ai 远程]
end
A <-.->|WebSocket| B
B --> C
C -->|子进程| D
A -->|--remote| D
连接状态有四种:connecting、connected、reconnecting、disconnected。断线会自动重连,有指数退避。
stateDiagram-v2
[*] --> connecting
connecting --> connected
connecting --> reconnecting
connected --> reconnecting
reconnecting --> connected
reconnecting --> disconnected
disconnected --> [*]
权限系统
权限模式有四种:default、auto、manual、bypass。
flowchart TD
subgraph 权限模式
A[default]
B[auto]
C[manual]
D[bypass]
end
A --> E{canUseTool}
B --> E
C --> E
D --> E
E --> F{permissionCheck}
F -->|允许| G{alwaysAllow?}
F -->|拒绝| H{alwaysDeny?}
G -->|是| I[执行工具]
G -->|否| J[弹窗确认]
H -->|是| K[拒绝]
H -->|否| J
检查流程:先 canUseTool,再 permissionCheck,然后查 alwaysAllow/alwaysDeny 规则。auto 模式下低风险操作自动放行,高风险操作弹窗确认。
会话管理
会话以 sessionId 标识,消息增量保存到磁盘。会话成本(token 消耗)独立统计。
flowchart LR
A[会话开始] --> B[创建 sessionId]
B --> C[初始化历史]
C --> D[处理输入]
D --> E[调用 API]
E --> F[保存消息]
F --> D
D -->|结束| G[保存成本]
G --> H[更新会话列表]
恢复会话时从磁盘读取历史消息,重建对话上下文。
插件系统
插件分三类:Marketplace 下载的、本地目录的、内置的。
flowchart LR
subgraph 插件来源
A[Marketplace]
B[本地目录]
C[内置插件]
end
A --> D[PluginInstallationManager]
B --> E[loadPluginCommands]
C --> F[initBundledPlugins]
D --> G[命令注册]
E --> G
F --> G
G --> H[getCommands 聚合]
加载流程:扫描目录 → 读取清单 → 注册命令 → 聚合到命令列表。插件卸载或更新后需要 /reload-plugins 生效。
技能系统
技能放在 skills/ 目录下,每个技能是一个独立模块。模型通过 SkillTool 调用技能。
flowchart TD
A[技能加载] --> B[skills 目录]
A --> C[bundle 技能]
A --> D[插件技能]
B --> E[聚合列表]
C --> E
D --> E
E --> F[过滤可用性]
F --> G[SkillTool 调用]
技能来源:技能目录、bundle 技能(内置)、插件技能。动态技能会在命令执行过程中被发现并加载。
组件层次
React 组件树:
flowchart TD
A[App] --> B[FpsMetricsProvider]
B --> C[StatsProvider]
C --> D[AppStateProvider]
D --> E[MailboxProvider]
E --> F[VoiceProvider]
F --> G[REPL Screen]
G --> H[Messages]
G --> I[PromptInput]
G --> J[TaskListV2]
I --> K[工具调用]
H --> L[消息渲染]
特性开关
用 bun:bundle 的 feature() 函数控制功能编译。开启哪些特性由环境变量决定,比如 COORDINATOR_MODE、KAIROS、VOICE_MODE 等。
flowchart TD
subgraph 特性开关
A[COORDINATOR_MODE]
B[KAIROS]
C[VOICE_MODE]
D[WORKFLOW_SCRIPTS]
E[PROACTIVE]
F[WEB_BROWSER_TOOL]
end
A --> G[feature 函数]
B --> G
C --> G
D --> G
E --> G
F --> G
G --> H[条件编译]
H -->|包含| I[功能代码]
H -->|排除| J[Dead Code Elimination]
好处是发行版可以裁剪掉不需要的代码,减少体积。
关键文件
| 文件 | 作用 |
|---|---|
main.tsx | 入口 |
replLauncher.tsx | 启动 REPL |
components/App.tsx | 根组件 |
screens/REPL.tsx | REPL 界面 |
state/AppStateStore.ts | 状态定义 |
query.ts | 查询引擎 |
services/api/claude.ts | API 调用 |
services/tools/toolOrchestration.ts | 工具执行 |
tools.ts | 工具注册 |
commands.ts | 命令注册 |
bridge/bridgeMain.ts | 远程桥接 |
coordinator/coordinatorMode.ts | 协调器 |
总结
整体是个分层架构:入口 → 状态 → REPL → 查询引擎 → 工具/API。状态管理用 React Context,工具系统可扩展,命令来自多个源(内置/技能/插件/工作流)。
设计上比较务实,该并行并行、该串行串行,会话状态持久化到磁盘而不是全放内存。特性开关的实现也值得参考,可以有效控制不同发行版的功能差异。