Claude code 源码分析
源码分析
代码结构
五层结构
|
|
Claude Code 系统运行时架构
| 层级 | 核心模块/文件 | 技术栈/关键说明 |
|---|---|---|
| 入口层(Entrypoints) | main.tsx、bridge/、server/、remote/ | Bun + React/Ink(~140 组件) |
| 运行时层(Runtime) | services/、screens/、会话、认证、配置 | - |
| 引擎层(Engine) | QueryEngine.ts (46K行)、coordinator/、context.ts、cost-tracker.ts、三层压缩 | - |
| 工具与能力层(Tools & Capabilities) | Tool.ts (29K行)、tools/ (~40)、commands.ts、commands/ (~85, 25K行)、skills/、plugins/ | - |
| 基础设施层 | hooks/、types/、utils/、memdir/、tasks/、vendor/: ripgrep、tree-sitter、audio | 注:原图标注笔误,层级名应为 Infrastructure Layer |
QueryEngine
46,000 行 TypeScript。QueryEngine 是一个单例(singleton),
拥有一个 mutableMessages 数组——整个对话的唯一真相来源(single source of truth)。循环的核心实现用了 generator 模式:
|
|
Generator 模式 相比传统的 while 循环或状态机,有哪些好处呢?
- 天然的流式输出,yield 每产生一个事件就推给 UI
- 中断是干净的,用户按 Ctrl+C,generator 直接 return,无需清理状态机
- 预算控制是平凡的,在 yield 之间检查 Token 消耗,超预算直接 return。工具调用是递归的,子代理可以嵌套自己的 generator
40 个工具与 29K 行定义
Claude Code 工具分层表
| 类别 | 用户可见工具 | 内部隐藏工具 |
|---|---|---|
| 文件操作 | Read、Write、Edit | 文件监控、LSP 集成 |
| 搜索 | Grep、Glob | 语义搜索、AST 分析 |
| 执行 | Bash | 沙箱化执行器、进程管理 |
| 网络 | WebFetch、WebSearch | OAuth 流程、API 代理 |
| 编排 | Agent、TodoWrite、Skill | Swarm 编排、上下文分叉 |
| 系统 | — | 遥测上报、密钥检测、缓存管理 |
每个工具都是一个离散的、权限门控的插件。工具定义不是简单的函数签名——每个工具包含以下内容
- JSON Schema 的参数定义
- 权限需求声明(哪些权限级别可以调用)
- 风险等级标注(是否需要用户审批)
- 输出格式规范(返回给模型的数据结构)
- 错误处理逻辑(重试策略、降级方案)
上下文工程
Sebastian Raschka(《Build a Large Language Model From Scratch》作者)在泄露当天发表了一篇分析文章,标题直接点出了核心洞察:Claude Code’s Real Secret Sauce Isn’t the Model.
优化一:Git 上下文自动加载
- 每次提示构造时,Claude Code 自动注入当前 Git 分支名、主分支名、最近的 commit 记录和 diff
- 模型不需要你告诉它“你在哪个分支上”——Harness 已经替你说了。这就是为什么 Claude Code 能自然地执行
git checkout -b feature/xxx而 Web UI 做不到。
优化二:静态 / 动态内容分界标记
- 提示词中有一个 boundary marker,将静态内容(系统指令、工具定义、CLAUDE.md)和动态内容(对话历史)分开
- 静态部分走全局缓存——和 Codex CLI 的 Prompt Caching 策略异曲同工,但 Claude Code 在客户端就做了分界,而不是依赖 API 端推断。
优化三:文件读取去重
- 如果你在一次会话中多次读取同一个文件且文件未变,Claude Code 不会重复将内容塞入上下文
- 它在客户端做了内容哈希去重——只有文件内容发生变化时才重新加载。
优化四:大结果落盘
- 当工具返回结果超过一定大小(比如
grep搜出了几千行)时,Claude Code 不会把完整结果塞进上下文——它把完整结果写入临时文件 - 上下文中只保留一段摘要预览 + 文件引用路径。模型可以在需要时通过 Read 工具读取完整内容。
优化五:LSP 集成
- 源码中有一个 LSP(Language Server Protocol)工具
- LSP 让 Claude Code 能做语义级的代码理解:定义跳转、引用查找、调用层次分析
| 优化项 | 核心机制 | 核心价值 |
|---|---|---|
| Git 上下文自动加载 | 自动注入分支名、commit 记录、diff | 让模型天然理解 Git 工作流,支持分支操作等复杂场景 |
| 静态/动态内容分界 | 用 boundary marker 拆分静态/动态内容,静态内容全局缓存 | 大幅降低 Token 消耗,提升响应速度,客户端自主分界更灵活 |
| 文件读取去重 | 客户端内容哈希校验,仅在文件变更时重新加载 | 避免冗余上下文,减少 Token 浪费,提升会话效率 |
| 大结果落盘 | 超大工具结果写入临时文件,上下文仅保留摘要+路径 | 突破上下文长度限制,按需加载完整内容 |
| LSP 集成 | 接入语言服务器协议 | 实现语义级代码理解,支持定义跳转、引用查找等高级能力 |
Self-Healing Memory
三层结构
|
|
源码中有一条关键规则叫“Strict Write Discipline”——Agent 只有在成功写入文件之后,
才更新 MEMORY.md 索引。如果写入失败,索引不更新,这避免了“索引指向不存在的内容”的一致性问题。
这本质上是数据库中的 write-ahead logging(WAL) 的逆向——先写数据,再写索引,确保索引永远指向有效内容。
权限系统:44 个 Feature Flag
KAIROS 是一个守护进程模式
- 当前的 Claude Code 是“被动响应式”的——你输入命令,它执行
- KAIROS 让 Claude Code 变成一个始终在线的后台 Agent
- 它包含一个叫 autoDream 的进程:在用户空闲时,Agent 自动进行“记忆整合”——合并分散的观察、消除逻辑矛盾、将模糊的洞察转化为确定性事实
- 这意味着 Anthropic 正在构建一个从工具到助手到守护进程的进化路径。我们的课程停留在“工具”阶段,KAIROS 代表的是下一个阶段
反蒸馏机制
这是什么意思?如果有人在录制 Claude Code 的 API 流量(比如通过中间人代理截获请求和响应),用这些数据来训练竞品模型——那些虚假工具定义就会污染训练数据。竞品模型会学到不存在的工具,在推理时产生幻觉
|
|
这个功能受 GrowthBook feature flag(tengu_anti_distill_fake_tool_injection)控制,只在第一方 CLI 会话中激活
源码中还有第二层反蒸馏机制,betas.ts 中的“connector-text summarization”。开启后,API 会将 Claude 在工具调用之间的中间文本进行摘要化处理,并附上加密签名。即使有人截获了流量,拿到的也是摘要而非原始推理过程
挫败检测
源码中的 userPromptKeywords.ts
暴露了一个出人意料的功能:用户挫败感检测。具体实现是一条正则表达式:
|
|
这条正则匹配了英语中最常见的挫败和愤怒表达——从轻微的 damn it 到重度的 fuck you。匹配结果被记录到分析系统,标记为 tengu_input_prompt 事件的 is_negative 布尔值
同时还有一个 is_keep_going 布尔值——检测用户是否在失败后仍坚持继续(比如 try again、keep going)
两个信号组合,让 Anthropic 可以构建用户满意度仪表盘,分析哪些功能让用户“骂街”?哪些场景让用户在失败后仍然愿意继续尝试?
社区对此的讨论很有意思——为什么一家拥有世界上最好的语言模型的 AI 公司,用正则表达式来检测用户情绪?
答案很工程化,一条正则表达式的执行成本是纳秒级的,而调用一次 LLM 来做情感分析的成本是秒级 + Token 费用
对于每条用户输入都要跑的检测,正则是唯一合理的选择
Undercover Mode
功能说明
- 源码中有一个叫 Undercover Mode 的功能,用于 Anthropic 员工以“匿名身份”向公共开源项目贡献代码。系统提示词中包含一句话:
Do not blow your cover(不要暴露身份)。 - 更引人注目的是,代码中明确标注了 “没有永久禁用 Undercover Mode 的方法”。
- 从工程伦理的角度看,这引发了一个值得讨论的问题:AI 辅助的代码贡献,是否应该在开源社区中透明标注?如果一个 PR 是 Claude Code 在 Undercover Mode 下生成的,提交者应该披露吗?
这个功能本身可能是为了让 Anthropic 的工程师在使用 Claude Code 贡献开源时,避免引起不必要的关注(比如“Anthropic 在用自己的 AI 写代码”的舆论风险)。但它的存在确实触及了 AI 工程的一个前沿问题——AI 参与的透明度边界在哪里?
Undercover Mode 是 Headless 模式的一个极端延伸——不仅无人值守,而且刻意隐藏 AI 的参与。这提醒我们,自动化能力越强,工程伦理的考量就越重要
| 核心维度 | 关键信息 |
|---|---|
| 功能定位 | Anthropic 员工匿名向开源项目贡献代码的模式 |
| 核心提示词 | Do not blow your cover(不要暴露身份) |
| 代码特性 | 无永久禁用该模式的方法 |
| 伦理争议 | AI 辅助代码贡献是否需要在开源社区透明标注 |
| 模式延伸 | 是 Headless 无人值守模式的极端形态,隐藏 AI 参与 |
| 核心结论 | 自动化能力越强,工程伦理的考量越重要 |
对照表
| 内容 | 源码验证 | 发现 |
|---|---|---|
| Agentic Loop | 核心循环逻辑完全一致 | generator 模式实现;QueryEngine 46K 行单例 |
| 工具系统 | 五个原子操作分类正确 | 实际 ~40 个工具(含内部),29K 行定义;功能代码与安全代码比例 ≈ 1:3 |
| 上下文管理 | 压缩 + 重注入策略正确 | Git 上下文自动加载、静态/动态 boundary marker、文件读取去重、大结果落盘、LSP 语义理解 |
| 记忆系统 | 三级记忆体系正确 | Self-Healing Memory:MEMORY.md 是索引;topic files 按需加载;Strict Write Discipline |
| 权限系统 | deny→allow→ask 正确;四级层次正确 | 44 个 feature flag;KAIROS 守护进程;120+ 内部环境变量 |
| Hooks 事件驱动 | 事件驱动思维正确 | 挫败感检测用正则而非 LLM——“确定性代码处理确定性” |
| Headless 模式 | 无人值守架构正确 | Undercover Mode:Headless 的极端延伸 |
| 平台定位 | Harness 定位完全正确 | 5 层平台运行时;反蒸馏机制(假工具注入 + 密文摘要) |
| 安全工程 / Rules权限系统 | 这次事件本身的启示 | Source map 泄露向量;Bun 构建行为与文档不一致;CI/CD 是最薄弱环节 |
Claude Code 主要流程架构图
1. 启动流程 (Startup Flow)
flowchart TD
Start[用户启动 claude] --> P1[性能分析检查点<br/>profileCheckpoint]
P1 --> P2[并行启动阶段]
P2 --> P2a[MDM 读取<br/>startMdmRawRead]
P2 --> P2b[Keychain 预取<br/>startKeychainPrefetch]
P2 --> P2c[重模块评估<br/>模块导入]
P2a --> Init[初始化阶段]
P2b --> Init
P2c --> Init
Init --> I1[Commander.js<br/>CLI 解析]
Init --> I2[GrowthBook<br/>特性开关]
Init --> I3[加载配置]
Init --> I4[加载状态]
I1 --> App[应用启动]
I2 --> App
I3 --> App
I4 --> App
App --> Mode{模式判断}
Mode -->|交互模式 | REPL[REPL UI]
Mode -->|桥接模式 | Bridge[Bridge]
Mode -->|服务器模式 | Server[Server]
REPL --> Ready[就绪,等待输入]
Bridge --> Ready
Server --> Ready
2. 核心查询流程 (Core Query Flow)
flowchart TB
subgraph InputPhase [输入处理阶段]
Input[用户输入] --> Process[processUserInput]
Process --> Messages[消息数组]
Messages --> Record[记录到转录]
end
subgraph QueryPhase [查询阶段]
Record --> QE[QueryEngine.ask]
QE --> Setup[设置工具上下文]
Setup --> Query[query 函数]
Query --> SysPrompt[系统提示构建]
Query --> UserCtx[用户上下文]
Query --> SysCtx[系统上下文]
SysPrompt --> APIReq[构建 API 请求]
UserCtx --> APIReq
SysCtx --> APIReq
end
subgraph APIPhase [API 调用阶段]
APIReq --> API[调用 Anthropic API]
API --> Stream[流式响应处理]
end
subgraph StreamPhase [流式处理阶段]
Stream --> ContentBlock[content_block]
Stream --> MessageDelta[message_delta]
Stream --> MessageStop[message_stop]
ContentBlock --> ToolCheck{工具调用?}
MessageDelta --> ToolCheck
end
subgraph ToolPhase [工具执行阶段]
ToolCheck -->|是 | Permission[权限检查]
Permission --> Execute[执行工具]
Execute --> ToolResult[工具结果]
ToolResult --> ToolMsg[工具结果消息]
ToolMsg --> Query
end
subgraph CompletePhase [完成阶段]
ToolCheck -->|否 | StopReason{stop_reason}
MessageStop --> StopReason
StopReason -->|end_turn| Output[输出结果]
StopReason -->|tool_use| ToolPhase
Output --> Save[保存会话]
Save --> Done[完成]
end
3. 权限系统流程 (Permission System Flow)
graph TB
ToolCall[工具调用请求] --> Check1{权限模式}
Check1 -->|auto| AutoMode[自动模式]
Check1 -->|always| AlwaysMode[始终允许]
Check1 -->|never| NeverMode[始终拒绝]
Check1 -->|default| DefaultMode[默认模式]
Check1 -->|plan| PlanMode[计划模式]
AutoMode --> AutoCheck[自动分类检查]
AutoCheck --> AutoDecision{决策}
AutoDecision -->|safe| Execute[直接执行]
AutoDecision -->|unsafe| PromptUser[提示用户]
DefaultMode --> History{历史决策?}
History -->|是| UseHistory[使用历史决策]
History -->|否| PromptUser
PlanMode --> PlanCheck{计划模式激活?}
PlanCheck -->|是| PlanBlock[阻止执行]
PlanCheck -->|否| PromptUser
AlwaysMode --> Execute
NeverMode --> Deny[拒绝]
PromptUser --> UserChoice[用户选择]
UserChoice --> UC1{选择}
UC1 -->|Allow| Execute
UC1 -->|Deny| Deny
UC1 -->|Always Allow| Always[设置始终允许]
UC1 -->|Apply to All| Batch[批量应用]
Always --> SaveRule[保存规则]
SaveRule --> Execute
Batch --> SaveRule
Execute --> Success[执行成功]
Deny --> Failure[执行失败]
PlanBlock --> Wait[等待计划完成]
UseHistory --> Execute
4. 上下文压缩流程 (Context Compaction Flow)
graph TB
QueryStart[query 调用] --> TokenCheck{Token 检查}
TokenCheck -->|正常| API[调用 API]
TokenCheck -->|超限| Compact[触发压缩]
Compact --> C1[Microcompact]
Compact --> C2[History Snip]
Compact --> C3[Context Collapse]
Compact --> C4[Autocompact]
C1 --> BuildMessages[构建消息]
C2 --> BuildMessages
C3 --> BuildMessages
BuildMessages --> C4
C4 --> Summary[Llama 生成摘要]
Summary --> Boundary[创建 compact_boundary]
Boundary --> NewMessages[新消息数组]
NewMessages --> TokenCheck
API --> Stream[流式响应]
Stream --> Update[更新消息]
Update --> Done[完成]
5. 工具系统架构 (Tool System Architecture)
graph TB
ToolPool[工具池] --> GetTools[getTools]
GetTools --> GT1[内置工具]
GetTools --> GT2[权限过滤]
GetTools --> GT3[特性开关过滤]
GT1 --> Tools[可用工具列表]
GT2 --> Tools
GT3 --> Tools
Tools --> Assemble[assembleToolPool]
Assemble --> MCPTools[MCP 工具]
MCPTools --> FinalPool[最终工具池]
FinalPool --> Registration[工具注册]
Registration --> ToolDefinition{工具定义}
ToolDefinition --> T1[Schema 定义]
ToolDefinition --> T2[权限模型]
ToolDefinition --> T3[执行函数]
T1 --> ToolInstance[工具实例]
T2 --> ToolInstance
T3 --> ToolInstance
ToolInstance --> Orchestration[工具编排]
Orchestration --> Execution[执行引擎]
Execution --> Execute[runTools]
Execute --> StreamingTool[StreamingToolExecutor]
StreamingTool --> Progress[进度更新]
StreamingTool --> Result[结果处理]
Result --> Output[输出到消息流]
Progress --> Output
Output --> Next{更多工具?}
Next -->|是| Execution
Next -->|否| Complete[完成]
6. MCP 系统集成流程 (MCP Integration Flow)
graph TB
Startup[启动] --> MCPLoad[加载 MCP 配置]
MCPLoad --> Config{配置类型}
Config -->|内置| BuiltIn[内置 MCP 服务器]
Config -->|Claude AI| AI[Claude AI MCP]
Config -->|自定义| Custom[自定义 MCP]
Config -->|企业| Enterprise[企业 MCP]
BuiltIn --> Initialize[初始化 MCP 客户端]
AI --> Initialize
Custom --> Initialize
Enterprise --> Initialize
Initialize --> Connect[连接服务器]
Connect --> Success{成功?}
Success -->|是| Discover[发现工具和资源]
Success -->|否| ErrorLog[记录错误]
Discover --> Tools[MCP 工具]
Discover --> Resources[MCP 资源]
Tools --> RegisterTool[注册到工具池]
Resources --> RegisterResource[注册到资源管理器]
RegisterTool --> Pool[工具池]
RegisterResource --> ResourceMgr[资源管理器]
Pool --> Query[查询请求]
ResourceMgr --> Query
Query --> ToolCall{工具调用?}
ToolCall -->|是| MCPInvoke[调用 MCP 工具]
ToolCall -->|否| ReadResource{资源读取?}
MCPInvoke --> MCPExecute[MCP 执行]
MCPExecute --> MCPResult[返回结果]
ReadResource -->|是| MCPRead[读取 MCP 资源]
MCPRead --> MCPResult
ReadResource -->|否| NativeTool[原生工具]
MCPResult --> Convert[转换格式]
Convert --> Message[工具消息]
NativeTool --> Message
Message --> Output[输出]
7. 多 Agent 协调流程 (Multi-Agent Coordination Flow)
graph TB
User[用户任务] --> Coordinator[Agent 协调器]
Coordinator --> TaskAnalysis[任务分析]
TaskAnalysis --> Plan[生成执行计划]
Plan --> AgentSpawn[生成 Agent]
AgentSpawn --> A1[主 Agent]
AgentSpawn --> A2[工作 Agent 1]
AgentSpawn --> A3[工作 Agent 2]
AgentSpawn --> A4[...更多 Agent]
A1 --> AgentTool[AgentTool]
A2 --> AgentTool
A3 --> AgentTool
A4 --> AgentTool
AgentTool --> QueryEngine[QueryEngine]
QueryEngine --> ExecuteAgent[执行 Agent]
ExecuteAgent --> Task{任务类型}
Task -->|子任务| SubTask[创建子任务]
Task -->|并行| Parallel[并行执行]
Task -->|串行| Serial[串行执行]
Task -->|通信| Message[Agent 通信]
SubTask --> AgentSpawn
Parallel --> Coordinator
Serial --> Coordinator
Message --> Message
Message --> SendMessage[SendMessageTool]
SendMessage --> AgentTool
Coordinator --> Complete{所有完成?}
Complete -->|否| ExecuteAgent
Complete -->|是| Results[汇总结果]
Results --> Output[输出给用户]
8. 状态管理流程 (State Management Flow)
flowchart TD
Init[应用启动] --> CreateStore[创建 Store]
CreateStore --> AppState[AppState]
CreateStore --> SetState[setState]
CreateStore --> GetState[getState]
AppState --> DefaultState[默认状态]
DefaultState --> D1[消息历史]
DefaultState --> D2[工具权限]
DefaultState --> D3[MCP 状态]
DefaultState --> D4[Agent 状态]
DefaultState --> D5[配置状态]
SetState --> Update[状态更新]
Update --> Validation[验证]
Validation --> Persist[持久化]
Persist --> Storage{存储类型}
Storage -->|会话 | SessionStore[会话存储]
Storage -->|全局 | GlobalStore[全局存储]
Storage -->|内存 | MemoryStore[内存存储]
GetState --> Read[读取状态]
Read --> Return[返回值]
Subscribe[订阅变化] --> ReactComponent[React 组件]
ReactComponent --> Render[渲染更新]
QueryOperation[查询操作] --> Update
ToolOperation[工具操作] --> Update
ConfigOperation[配置操作] --> Update
关键数据流说明
1. 消息生命周期
- 创建:用户输入 →
createUserMessage→ 添加到mutableMessages - 处理:
processUserInput解析命令和附件 - 查询:
query()构建请求,调用 API - 流式:API 响应 → 分块处理 → 实时更新 UI
- 记录:
recordTranscript保存到会话存储 - 压缩:超限时触发自动压缩,生成摘要
2. 工具调用生命周期
- 发现:
getTools()+ MCP 工具发现 - 过滤:权限规则 + 特性开关
- 调用:LLM 决定 →
toolUseBlock - 检查:权限系统检查
- 执行:
runTools()+StreamingToolExecutor - 结果:
toolUseResult→ 添加到消息流
3. 会话持久化
- 实时保存:每个操作后异步写入
- 恢复:
--resume从转录加载 - 压缩:
compact_boundary标记压缩点 - 共享:
/share导出会话
性能优化关键点
- 并行启动:MDM、Keychain、模块评估并行执行
- 延迟加载:重模块动态 import()
- 死代码消除:特性开关移除未使用代码
- 上下文压缩:多层压缩策略(Microcompact、Snip、Autocompact)
- 缓存预取:Skills、Plugins、MCP 资源预取
- 流式处理:实时 UI 更新,不阻塞响应
- 提示缓存:系统提示缓存减少 Token
错误处理策略
- API 错误:自动重试(
withRetry) - 权限拒绝:记录到否认追踪(
DenialTracking) - 工具失败:错误消息 → LLM 重试
- 上下文超限:自动压缩或拒绝
- 连接失败:重连机制 + 用户通知