Claude Code源码暗藏意外礼物秘密
目录
- 系统全貌:它到底是什么?
- 入口:一切从 main.tsx 开始
- 核心引擎:query.ts 的 Agent 循环
- 上下文管理:五层过滤的精妙设计
- 工具系统:Claude 的"手"
- 容错机制:为生产环境而生的防御
- 多智能体:协调器与子 Agent
- 工程洞察:值得学习的设计决策
- 结语
1. 系统全貌:它到底是什么?
Claude Code 是 Anthropic 官方推出的终端 AI 编程助手 CLI。它不是什么简单的代码补全工具。它是一个真正的智能体系统,能干的事儿可多了:

- 读写文件、搜索代码库、执行 Shell 命令
- 管理 Git、创建 PR、审查代码
- 通过 MCP(Model Context Protocol)连接外部服务
- 协调多个子 Agent 并行完成复杂任务
技术栈一览:
| 层次 | 技术选型 |
|---|---|
| 运行时 | Bun(取代 Node.js,启动更快) |
| 语言 | TypeScript(严格类型,全覆盖) |
| 终端 UI | React + Ink(React 渲染到 terminal) |
| AI SDK | @anthropic-ai/sdk(流式 API) |
| 协议层 | MCP SDK(工具/资源的统一接入) |
| Schema | Zod(运行时类型校验) |
| 功能开关 | GrowthBook + Bun bundle feature flags |
这代码的规模和复杂程度,跟一般人印象里"一个 CLI 工具"比起来,差距可不是一星半点。
2. 入口:一切从 main.tsx 开始
src/main.tsx 的前 20 行就明明白白告诉你,这个团队对启动性能的执着到了什么程度:
// 必须在所有 import 之前执行的副作用:import { profileCheckpoint } from './utils/startupProfiler.js'profileCheckpoint('main_tsx_entry')// ← 第一行就开始计时import { startMdmRawRead } from './utils/settings/mdm/rawRead.js'startMdmRawRead()// ← 并行启动 MDM subprocess(plutil/reg query)import { startKeychainPrefetch } from './utils/secureStorage/keychainPrefetch.js'startKeychainPrefetch()// ← 并行预取 Keychain(OAuth + API Key)
三件事并行触发,注释里专门说明了原因:keychain 预取能节省约 65ms 的启动时间。这种对毫秒级延迟的计较,在整个代码库里一以贯之。
启动阶段的主要工作:
- 身份认证:OAuth 令牌校验、Bedrock/Vertex 凭证预取
- 信任检查:
checkHasTrustDialogAccepted()确保用户同意条款 - 配置加载:MDM 托管配置、远程策略限制、Feature Flag 初始化
- 工具注册:
getTools()按 feature flag 动态组装工具集 - MCP 初始化:预取官方 MCP Server 列表
- REPL 启动:
launchRepl()进入交互主循环
3. 核心引擎:query.ts 的 Agent 循环
这是整个系统最精华的部分——src/query.ts,约 1,750 行。
它的核心是一个 while(true) 无限循环,每次迭代代表一个"轮次(turn)"。用 ASCII 图描述:
用户输入 │ ▼┌─────────────────────────────────────────────────┐│while(true) 主循环 ││ ││① 上下文预处理(5层压缩/过滤)││ │ ││② 调用 Claude API(流式) ││ │ ││③ 实时处理流消息││ │ ││ needsFollowUp?││ ├─ NO → ④ 错误恢复 / Stop Hooks / 结束││ └─ YES → ⑤ 执行工具 │││││ ⑥ 构建下一轮消息 → 继续循环│└─────────────────────────────────────────────────┘
3.1 状态机设计
循环的状态通过一个不可变的 State 对象在迭代间传递:
type State = {messages: Message[]// 完整对话历史toolUseContext: ToolUseContext// 工具执行上下文turnCount: number// 轮次计数maxOutputTokensRecoveryCount: number// 截断恢复次数hasAttemptedReactiveCompact: boolean// 防止 compact 死循环transition: Continue | undefined// 调试:上一次为何 continue// ...}
transition 字段尤其值得关注——它记录了每次 continue 的原因,如 'next_turn'、'max_output_tokens_recovery'、'reactive_compact_retry' 等。这使得测试可以断言具体的恢复路径触发了,而不必检查消息内容。
3.2 流式处理与消息收集
API 以 async generator 形式流式返回消息,循环实时处理每一块:
for await (const message of deps.callModel({ messages, systemPrompt, ... })) {// 1. 处理 fallback(模型降级)// 2. 将 tool_use 的 input 字段 backfill 给 SDK 消费者// 3. 判断是否要缓留(withheld)这条消息// 4. yield 或暂存// 5. 提取 tool_use blocks,设置 needsFollowUp = true}
"缓留"机制是一个精妙的设计:三类可恢复的错误消息(Prompt-too-long、Media 超限、Max-output-tokens)在流式阶段被暂不传递给调用方,等待恢复逻辑判断,成功则悄无声息地重试,失败才将错误暴露出去。这避免了 SDK 消费者(如 desktop 客户端)在看到 error 字段时立即终止会话。
4. 上下文管理:五层过滤的精妙设计
LLM 的致命弱点是有限的上下文窗口。Claude Code 用五层递进的机制来管理这个问题,每层都在 API 调用前依次执行:
原始消息列表 │ ▼ 层1: Tool Result 大小限制 │applyToolResultBudget() — 截断超大工具返回值 │持久化替换记录,/resume 时可恢复 │ ▼ 层2: Snip 压缩 [HISTORY_SNIP feature] │snipCompactIfNeeded() — 按策略删除旧消息 │snipTokensFreed 传递给下层,避免误判 │ ▼ 层3: Microcompact │微型压缩 — 合并重复工具调用/结果 │CACHED_MICROCOMPACT: 延迟 boundary 消息 │以获取真实 cache_deleted_input_tokens │ ▼ 层4: Context Collapse [CONTEXT_COLLAPSE feature] │折叠历史 — Read-time projection │折叠记录存 store,不修改 REPL 数组 │保证 /resume 后折叠状态持久 │ ▼ 层5: Auto Compact 触发阈值时 fork 子 Claude 对历史做摘要 成功: 用摘要替换历史,继续当前 turn 失败: 记录 consecutiveFailures,断路器保护 ↓ 发送给 API 的消息
层次顺序的设计意图:
- Collapse 在 AutoCompact 之前:如果 collapse 把 token 数降到阈值以下,autocompact 就无需触发,保留细粒度历史
- Snip 在 Microcompact 之前:snip 释放的 token 数必须传给 autocompact,否则基于旧 usage 数据会误触发
- Tool Result 限制最先执行:microcompact 只认
tool_use_id,不检查内容,两者相互独立
task_budget 的跨 compact 追踪
这是一个极度细节的设计。Anthropic API 支持 task_budget(任务预算),服务端通过计数 context window 来追踪消耗。但 compact 之后,服务端只看到摘要,会低估历史消耗。
解决方案:在每次 compact 触发前,客户端快照当前的 finalContextTokensFromLastResponse,累加到 taskBudgetRemaining,下次请求时通过 remaining 字段告知服务端正确的剩余预算。
5. 工具系统:Claude 的"手"
工具系统是 Claude Code 能力边界的直接体现。所有工具实现 Tool 接口,通过 Zod schema 声明输入类型。
5.1 工具全景
核心文件操作├── FileReadTool— 读文件,支持行范围├── FileEditTool— 精确字符串替换(必须唯一匹配)├── FileWriteTool — 全覆盖写入└── GlobTool— 模式匹配文件搜索代码搜索├── GrepTool— 正则文本搜索└── LSPTool — 基于 LSP 的语义搜索/跳转Shell 执行├── BashTool— Unix Shell 命令└── PowerShellTool— Windows PowerShell智能体工具├── AgentTool — 启动子 Agent(多 Agent 协作)├── SkillTool — 执行预定义工作流 Skill└── TodoWriteTool — 进度追踪与任务管理Web 能力├── WebFetchTool— HTTP 请求/页面抓取└── WebSearchTool — 搜索引擎查询MCP 集成├── MCPTool — 调用任意 MCP Server 工具├── ListMcpResourcesTool└── ReadMcpResourceTool任务调度(feature-gated)├── ScheduleCronTool— 定时任务(AGENT_TRIGGERS)├── SleepTool — 等待/延迟(PROACTIVE/KAIROS)└── MonitorTool — 后台监控(MONITOR_TOOL)
5.2 StreamingToolExecutor:并发工具执行
传统 Agent Loop 是串行的:模型流结束 → 执行所有工具 → 下一轮。Claude Code 实现了 StreamingToolExecutor,在模型仍在流式输出时就开始执行已确认的工具调用:
模型流式输出:[text...] [tool_use: BashTool] [text...] [tool_use: GlobTool]││StreamingToolExecutor:addTool() 立即开始执行 addTool() 立即开始执行││流结束后:getRemainingResults() 收割所有完成的结果
这将"等待工具执行"的时间隐藏在了"等待模型输出"的时间里,显著降低延迟。
5.3 工具的权限模型
工具执行前必须通过 canUseTool() 检查。权限层级:
plan模式:只读工具,不允许写操作或命令执行default模式:需要用户确认危险操作auto模式(bypassPermissions):自动批准,适合 CI/CD 场景
权限系统还内置了 DenialTrackingState——记录用户拒绝了哪些操作,避免重复询问。
6. 容错机制:为生产环境而生的防御
生产级系统的标志是当事情出错时的表现。Claude Code 有完善的错误恢复链:
6.1 模型降级(Fallback)
当主模型因高负载返回 FallbackTriggeredError 时:
if (innerError instanceof FallbackTriggeredError && fallbackModel) {currentModel = fallbackModelattemptWithFallback = true// 1. Tombstone 孤立的 assistant 消息(thinking block 有签名,不能跨模型复用)for (const msg of assistantMessages) {yield { type: 'tombstone', message: msg }}// 2. 清空状态,创建新的 StreamingToolExecutor// 3. 剥离 signature blocks(thinking block 是模型绑定的)// 4. 告知用户:已切换到 ${fallbackModel}(warning 级别)// 5. 重试}
Tombstone 消息是一个有趣的设计:UI 层看到 tombstone 后,会从界面和 transcript 中移除对应消息,保证视觉一致性。
6.2 max_output_tokens 恢复(三层递进)
Claude 有时会在任务未完成时达到输出 token 上限。系统按顺序尝试三种恢复:
第1层:Token 升级
// 如果用户没有显式设置上限,先尝试用 64k 重试同一请求if (capEnabled && maxOutputTokensOverride === undefined) {state = { ..., maxOutputTokensOverride: ESCALATED_MAX_TOKENS }continue// 重试,不告知用户}
第2层:截断续写(最多 3 次)
const recoveryMessage = createUserMessage({content: `Output token limit hit. Resume directly — no apology, no recap. ` + `Pick up mid-thought if that is where the cut happened.`,isMeta: true,// 隐藏消息,不显示给用户})state = { messages: [..., recoveryMessage], maxOutputTokensRecoveryCount: count + 1 }continue
第3层:放弃,暴露错误
"no apology, no recap" 这句续写提示写得极妙——精确地抑制了模型在续写时的常见病:长篇大论地解释"刚才发生了什么"。
6.3 Prompt-too-long 恢复(三层递进)
当 context 过长导致 API 返回 413 时,也有分层恢复:
- Context Collapse Drain:提交暂存的折叠,便宜操作,先试
- Reactive Compact:被动触发全量摘要(
hasAttemptedReactiveCompact防止死循环) - 暴露错误,调用
executeStopFailureHooks
关键细节:这两种错误消息在流式阶段都被缓留(withheld),恢复后悄悄重试。只有恢复失败才向调用方暴露错误。这意味着用户在大多数情况下看不到中间态的错误——系统静默地解决了问题。
7. 多智能体:协调器与子 Agent
Claude Code 支持多 Agent 协作模式,架构设计颇为精妙。
7.1 AgentTool:递归的 Agent
AgentTool 允许 Claude 启动一个完整的子 Agent,子 Agent 又可以继续调用工具甚至再启动孙 Agent:
主 Agent (query.ts)└─ AgentTool → 子 Agent (独立 query loop)└─ AgentTool → 孙 Agent
每个子 Agent 有独立的 agentId、独立的 abort 控制器、独立的工具使用上下文。消息队列通过 agentId 作用域隔离:
- 主线程 drain
agentId === undefined的消息 - 子 Agent drain 自己
agentId的消息 - 用户 prompt 只流向主线程
7.2 Team 模式(实验性)
从工具列表可以看到 TeamCreateTool 和 TeamDeleteTool,结合 coordinatorMode.ts,这是一个多 Agent 并行执行的协调器模式:
- Coordinator 负责任务分解和调度
- 多个 Worker Agent 并行执行子任务
- 结果汇总回 Coordinator
这是一个仍在 feature flag 保护下的实验性功能,但架构雏形已经清晰可见。
7.3 Buddy 系统(有趣的彩蛋)
src/buddy/ 目录里有一个 CompanionSprite.tsx 和 sprites.ts——这是 Claude Code 的"宠物"功能,一个可以在终端中显示的像素风格伙伴角色,会在某些操作时显示动画。这个功能完全不影响核心功能,却体现了团队对产品体验的用心。
8. 工程洞察:值得学习的设计决策
通读源码后,有几个设计决策值得单独拎出来讨论。
8.1 AsyncGenerator 作为核心抽象
整个 query 函数是一个 async function*(async generator):
export async function* query(params: QueryParams):AsyncGenerator<StreamEvent | Message | ..., Terminal>
这个选择非常巧妙:
- 自然流式传输:每个
yield立即推送给调用方,无需额外缓冲 - 背压(Backpressure):调用方消费速度控制生产速度
- 资源清理:
using pendingMemoryPrefetch = ...,无论正常退出、throw 还是.return()都能触发 dispose - 组合性:
yield*自然委托给子 generator,如queryLoop
返回类型 Terminal 提供了丰富的退出原因枚举:completed、aborted_streaming、max_turns、blocking_limit、prompt_too_long、stop_hook_prevented 等,调用方可以精确分支处理。
8.2 Feature Flag 的双轨制
代码里同时使用两套 feature flag 系统:
// 运行时 A/B 测试(GrowthBook)const value = getFeatureValue_CACHED_MAY_BE_STALE('tengu_otk_slot_v1', false)// 构建时消除(Bun bundle)if (feature('CONTEXT_COLLAPSE')) {// 此块在 feature 关闭的 build 中被完全删除}
_CACHED_MAY_BE_STALE 后缀是一个强制的命名约定——提醒开发者这个值在流式处理的 5-30 秒内可能翻转,如果用在"缓留"和"恢复"两处必须保证一致性。mediaRecoveryEnabled 在循环入口处快照一次,正是基于这个考虑。
8.3 "不可变参数 + 可变 State" 的循环设计
// 一次性解构,循环内永不重赋值const { systemPrompt, maxTurns, querySource } = params// 可变 State,每次 continue 整体替换let state: State = { ... }while (true) {const { messages, turnCount, ... } = state// ...state = { ...next }// 整体替换,7 个 continue 点一致}
这种设计的优点:
- 意图清晰:看到
const就知道这个值绝不会变 - 避免竟态:每次迭代都是从
state全量读取,不存在"某个字段没更新"的 bug - 易于 debug:
transition字段记录了每次continue的原因,测试可验证恢复路径
8.4 工具使用摘要的延迟消费
// 工具执行完毕,异步启动摘要生成(Haiku,~1s)const nextPendingToolUseSummary = generateToolUseSummary(...)// 在下一轮 ——— 流结束后 ——— 才消费(流 5-30s,摘要 1s)if (pendingToolUseSummary) {const summary = await pendingToolUseSummary// 此时几乎已完成,无需等待yield summary}
这是经典的"异步计算隐藏延迟"技巧:把慢操作(即使只有 1s)藏在另一个慢操作(5-30s 的模型流)背后,用户几乎感知不到额外等待。
8.5 Memory Prefetch 的 using 析构
using pendingMemoryPrefetch = startRelevantMemoryPrefetch(state.messages,state.toolUseContext,)
using 关键字(TC39 显式资源管理提案,TypeScript 5.2 起支持)确保 pendingMemoryPrefetch[Symbol.dispose]() 在所有退出路径(正常返回、throw、generator .return())上都会被调用,即使忘记 try-finally 也没问题。
9. 结语
通读这份源码,最深刻的感受不是"Claude Code 好厉害",而是:一个真实的、面向生产的 AI Agent 系统,需要解决多少工程问题。
- 上下文窗口管理不是一个算法,而是 5 层递进的工程系统
- 错误恢复不是 try-catch,而是精心设计的状态机迁移
- 流式处理不是
await response.text(),而是涉及背压、缓留、并发执行的复杂管道 - 工具系统不是函数数组,而是带权限模型、并发执行、结果预算的完整框架
Anthropic 在 Claude Code 上的实践,代表了当前 AI Agent 工程的最高水平线之一。无论你是在构建自己的 Agent 系统,还是只是想理解这类系统的设计边界,这份意外暴露的源码都是难得的一手学习材料。
本文基于 2026-03-31 公开曝光的 Claude Code 源码快照(npm 包 source map 泄露)进行分析,仅用于技术学习与架构研究。文中所有代码引用均来自该公开快照。
如果你对某个具体模块有更深入的问题,欢迎在评论区讨论。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
阿里云OpenClaw官方镜像六大场景3分钟开箱即用指南
先聊聊OpenClaw到底是什么,以及它为什么值得关注。作为阿里云推出的智能助理平台,OpenClaw基于通义千问大模型深度定制,目标很明确:为开发者、创作者、运营者提供一站式的AI赋能解决方案。下面直接切入正题,看看它的六大核心场景。 OpenClaw 智能助理:六大核心场景赋能开发者高效成长 O
Moltbot Clawdbot与飞书机器人接入实践
简单认识一下 Clawdbot 最近 AI 圈被一款名为 Clawdbot 的产品刷屏了。不管是在国内技术社区,还是刷 TG、X 的时候,几乎都能看到有人在讨论它。 看了一下官方文档,Clawdbot 本质上就是一个偏“个人智能助手”的东西。不过它并不是单独开一个网页给我们用,而是可以直接接入我们平
SpringAI与ONNX打造免费离线向量引擎
前段时间尝试了一个很有意思的项目——原本只是想在 Spring AI 项目中顺手集成 ONNX 模型,结果一上手就停不下来,直接调试到凌晨两点,边调边感慨:整个过程也太丝滑流畅了。 今天就来深入聊聊这件事:如何在 Spring AI 中使用 ONNX 向量模型,实现本地化的文本嵌入能力。 如果你之前
AI智能体技能完全指南:让你的AI助手拥有超能力
引言:AI Agent 的能力边界在哪里?你的AI编程助手可以编写代码,但它是否真正理解你公司的独特工作流程?能否自动处理你的CI CD流水线?又是否熟悉你日常使用的那些特定工具与API接口?AI Agent Skills正是为解决这一痛点而诞生的——它们作为可复用的能力模块,能够将通用型AI助手转
AI编程神器狂揽34k星与Claude Code和Codex绝配
CC Switch:一站式AI编程工具管理神器 今天要介绍的这款实用小工具,名字叫作CC Switch。它是一款跨平台的桌面“All-in-One”助手,专门用于管理主流的AI编程开发工具。目前该项目在GitHub上已经获得了34k+ star,关注度非常高。它的核心卖点很直接:提供一个可视化操作界
- 日榜
- 周榜
- 月榜
相关攻略
2026-06-06 18:43
2026-06-06 18:40
2026-06-06 18:40
2026-06-06 18:39
2026-06-06 18:39
2026-06-06 18:39
2026-06-06 18:39
2026-06-06 18:39
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

