Claude Code 源码深读:51 万行 TypeScript 被一个 source map 曝光
- 一、代码全景:1900 文件的目录地图
- 二、引擎核心:QueryEngine.ts 的流式工具循环
- 三、工具系统:40 个 Tool 的注册与权限沙箱
- 四、上下文管理:从 CLAUDE.md 到 Prompt Cache
- 五、认证与安全:OAuth 2.0 + 卧底模式 + 反蒸馏
- 六、多 Agent 编排:Coordinator 与 AgentTool
- 七、技能与插件:可扩展架构
- 八、功能标志:Bun 编译时消除与 44 个隐藏功能
- 九、代码质量观察:亮点与屎山
- 十、给开发者的启示
- 结语
本文首发地址 https://h89.cn/archives/566.html
2026 年 3 月 31 日,Chaofan Shou (@Fried_rice) 在 Twitter 上扔了一颗炸弹:Claude Code 的 npm 包中暴露了.map文件,引用了托管在 Anthropic R2 存储桶上的未混淆 TypeScript 源码。51.2 万行代码,1900 个文件,一个source map的蝴蝶效应,让 Anthropic 最核心的 CLI 工具架构赤裸裸地摊在了阳光下。
这不是一篇架构概述。这是拿着放大镜逐行读代码后的发现——从 QueryEngine.ts 的流式工具循环,到 ToolPermission 的三层权限沙箱,再到 Coordinator 的多 Agent 编排。如果你是写代码的人,这些细节比任何官方文档都值得看。

一、代码全景:1900 文件的目录地图

先看全貌。src/ 下的目录结构揭示了 Claude Code 的野心——它不只是一个终端聊天工具,而是一个完整的 AI 开发环境操作系统:
src/
├── main.tsx # 入口(Commander.js CLI + React/Ink 渲染)
├── QueryEngine.ts # LLM 查询引擎(~46K 行)—— 整个系统的心脏
├── Tool.ts # 工具类型定义(~29K 行)—— 40 个工具的契约层
├── commands.ts # 命令注册表(~25K 行)
├── tools.ts # 工具注册表
├── context.ts # 系统/用户上下文收集
├── cost-tracker.ts # Token 费用追踪
│
├── tools/ # 40 个工具实现
├── commands/ # ~50 个斜杠命令
├── components/ # ~140 个 Ink UI 组件
├── hooks/ # React Hooks(含 toolPermission 权限系统)
├── services/ # 外部服务(API, MCP, OAuth, LSP, analytics)
├── bridge/ # IDE 桥接(VS Code, JetBrains)
├── coordinator/ # 多智能体协调器
├── skills/ # 技能系统
├── plugins/ # 插件系统
├── buddy/ # 伴侣精灵
├── voice/ # 语音输入
├── memdir/ # 持久化内存目录
├── schemas/ # Zod v4 配置模式
├── vim/ # Vim 模式
├── remote/ # 远程会话
├── server/ # 服务器模式
└── ...
几个值得注意的数字:
- 46K 行的
QueryEngine.ts——一个文件撑起了整个 LLM 交互引擎 - 140 个 UI 组件——终端界面比你想象的复杂得多
- 40 个工具 + 50 个命令——功能密度极高
- coordinator/ + buddy/ + skills/ + plugins/——多 Agent 和可扩展架构从第一天就在设计里
二、引擎核心:QueryEngine.ts 的流式工具循环
QueryEngine.ts 是整个系统的心脏。46,000 行代码,单文件。这在任何项目中都是"怪兽级"的存在。它的核心职责是:驱动 LLM 的流式工具调用循环。
2.1 核心循环:消息 → 工具 → 消息
Claude Code 的交互不是简单的"发一条收一条"。它是一个 tool-use loop:
用户输入
→ QueryEngine 发送 messages + tools 给 API
→ API 流式返回(可能包含 tool_use 块)
→ 如果有 tool_use → 执行工具 → 将工具结果追加到 messages
→ 再次调用 API(带着工具结果)
→ 重复直到 API 不再请求工具
→ 最终文本输出给用户
这个循环的关键在于 流式处理。QueryEngine 不会等工具执行完再显示内容——它在流式接收 API 响应的同时,就开始渲染中间结果。这意味着用户在 Claude "思考"的过程中就能看到它在做什么。
2.2 思考模式(Thinking)
源码中 thinkingConfig 贯穿整个引擎:
export type ToolUseContext = {
options: {
thinkingConfig: ThinkingConfig
// ...
}
// ...
}
ThinkingConfig 控制着 Claude 的"内心独白"——扩展思考(extended thinking)模式下,Claude 会先输出一段不可见的思考链,再给出最终回答。这对代码生成等需要深度推理的场景至关重要。源码中思考模式的 token 预算控制、截断策略和缓存复用都做得很精细。
2.3 重试与错误处理
46K 行的另一个原因是重试逻辑极其复杂。API 调用可能因为速率限制、网络错误、内容过滤等多种原因失败,每种情况的重试策略不同:
- 速率限制 → 指数退避重试
- 网络错误 → 短间隔重试
- 内容过滤 → 换一种方式重新提问
- 工具执行失败 → 将错误信息注入 messages,让模型自行决定下一步
这个设计哲学值得学习:不要替模型做错误恢复的决策,把错误信息交给模型,让它自己决定怎么办。
2.4 Token 计数与费用追踪
cost-tracker.ts 是独立于引擎的计费模块。它实时追踪每次 API 调用的 input/output token 数,计算费用,并在 UI 中展示。关键设计:
- 输入/输出 token 分开计费(Anthropic 的定价模型中,输出 token 贵 3-5 倍)
- 缓存命中 token 单独统计——Prompt Cache 命中的 token 按折扣价计算
- 多 Agent 场景下的费用聚合——子 Agent 的费用归到父会话
三、工具系统:40 个 Tool 的注册与权限沙箱

这是源码中最有设计感的部分。40 个工具,每个都是独立的模块,但它们共享同一套类型系统、权限模型和注册机制。
3.1 Tool 类型定义——所有工具的契约
Tool.ts(29K 行)定义了工具的核心类型:
export type Tool<
Input extends AnyObject = AnyObject,
Output = unknown,
P extends ToolProgressData = ToolProgressData,
> = {
aliases?: string[] // 工具别名,向后兼容
searchHint?: string // ToolSearch 关键词,3-10 词
call(args, context, canUseTool, parentMessage, onProgress?): Promise<ToolResult<Output>>
description(input, options): Promise<string>
readonly inputSchema: Input // Zod schema
readonly inputJSONSchema?: ToolInputJSONSchema // MCP 直接 JSON Schema
outputSchema?: z.ZodType<unknown>
// ...
}
几个精妙的设计点:
1. 泛型三参数 <Input, Output, P>
Input 是 Zod schema 类型,Output 是工具返回值类型,P 是进度回调数据类型。三层泛型让每个工具都有完整的类型安全——从输入验证到输出处理到进度展示,全链路类型推断。
2. searchHint——延迟工具发现
这个字段用于 ToolSearchTool。Claude Code 有 40+ 个工具,但不可能每次调用 API 都把所有工具描述发给模型(token 成本太高)。searchHint 是 3-10 个关键词,用于在工具注册表中做模糊匹配,只在需要时才将具体工具的完整描述注入 prompt。
3. 双 Schema 设计
inputSchema(Zod)用于内部验证,inputJSONSchema 用于 MCP 协议的直接 JSON Schema 输出。一套类型,两种消费方式。
3.2 ToolUseContext——工具执行的上下文宇宙
export type ToolUseContext = {
options: {
commands: Command[]
tools: Tools
thinkingConfig: ThinkingConfig
mcpClients: MCPServerConnection[]
mcpResources: Record<string, ServerResource[]>
isNonInteractiveSession: boolean
agentDefinitions: AgentDefinitionsResult
maxBudgetUsd?: number
customSystemPrompt?: string
appendSystemPrompt?: string
refreshTools?: () => Tools // 动态刷新工具列表
}
messages: Message[]
readFileState: FileStateCache
toolDecisions?: Map<string, { source: string; decision: 'accept'|'reject'; timestamp: number }>
contentReplacementState?: ContentReplacementState
renderedSystemPrompt?: SystemPrompt // 父 agent 冻结的 prompt 用于缓存共享
// ...
}
注意几个关键字段:
refreshTools:动态刷新工具列表。MCP 服务器可能在运行时动态注册新工具,这个回调让引擎能实时更新可用工具集。toolDecisions:记录用户对每个工具调用的审批历史(接受/拒绝),避免重复弹窗。renderedSystemPrompt:父 Agent 冻结的 prompt。在多 Agent 场景下,子 Agent 可以复用父 Agent 的静态 prompt 部分,避免重复构建和重复计费。contentReplacementState:工具结果预算替换。当工具输出太长时,用压缩版本替换原始结果,控制 token 预算。
3.3 权限沙箱——三层规则 + 四种模式
export type ToolPermissionContext = DeepImmutable<{
mode: PermissionMode // 'default' | 'plan' | 'bypassPermissions' | 'auto'
additionalWorkingDirectories: Map<string, AdditionalWorkingDirectory>
alwaysAllowRules: ToolPermissionRulesBySource
alwaysDenyRules: ToolPermissionRulesBySource
alwaysAskRules: ToolPermissionRulesBySource
isBypassPermissionsModeAvailable: boolean
shouldAvoidPermissionPrompts?: boolean // 后台 agent 不弹 UI
awaitAutomatedChecksBeforeDialog?: boolean // coordinator workers
prePlanMode?: PermissionMode
}>
这个权限模型的设计非常考究:
三种规则来源:
alwaysAllowRules:白名单规则。匹配的工具调用自动放行,不打扰用户。alwaysDenyRules:黑名单规则。匹配的工具调用直接拒绝。alwaysAskRules:灰名单规则。匹配的工具调用必须询问用户。
规则可以按工具名、文件路径模式、命令模式等多种维度匹配。
四种权限模式:
| 模式 | 行为 |
|---|---|
default |
未在白/黑名单中的工具都需要用户确认 |
plan |
只允许只读工具(FileRead, Grep, Glob),禁止写入操作 |
bypassPermissions |
跳过所有权限检查(CI/CD 场景) |
auto |
自动决策,尽量减少用户交互 |
两种特殊标志:
shouldAvoidPermissionPrompts:后台 Agent 不会弹 UI,所以不能打断等用户确认。这种情况下,未明确允许的工具会被静默拒绝。awaitAutomatedChecksBeforeDialog:Coordinator 的 worker Agent 在弹出权限对话框前,先等待自动化检查完成。这避免了多个 worker 同时弹窗的混乱。
DeepImmutable 的妙用:权限上下文被标记为深度不可变。这意味着工具实现不能篡改权限规则——安全边界在类型系统层面就被锁死了。
3.4 工具注册表
40 个工具在 tools.ts 中注册,每个工具的实现都在 tools/ 目录下。完整列表:
| 工具 | 说明 | 危险级别 |
|---|---|---|
BashTool |
Shell 命令执行 | 🔴 高 |
FileReadTool |
文件读取(含图片、PDF、笔记本) | 🟢 低 |
FileWriteTool |
文件创建/覆盖 | 🔴 高 |
FileEditTool |
文件局部修改(字符串替换) | 🟡 中 |
GlobTool |
文件模式匹配搜索 | 🟢 低 |
GrepTool |
基于 ripgrep 的内容搜索 | 🟢 低 |
WebFetchTool |
获取 URL 内容 | 🟡 中 |
WebSearchTool |
网络搜索 | 🟢 低 |
AgentTool |
子智能体生成 | 🔴 高 |
SkillTool |
技能执行 | 🟡 中 |
MCPTool |
MCP 服务器工具调用 | 🟡 中 |
LSPTool |
语言服务器协议集成 | 🟢 低 |
NotebookEditTool |
Jupyter 笔记本编辑 | 🔴 高 |
TaskCreateTool / TaskUpdateTool |
任务创建与管理 | 🟢 低 |
SendMessageTool |
智能体间消息传递 | 🟡 中 |
TeamCreateTool / TeamDeleteTool |
团队智能体管理 | 🔴 高 |
EnterPlanModeTool / ExitPlanModeTool |
计划模式切换 | 🟢 低 |
EnterWorktreeTool / ExitWorktreeTool |
Git 工作树隔离 | 🟡 中 |
ToolSearchTool |
延迟工具发现 | 🟢 低 |
CronCreateTool |
定时触发器创建 | 🟡 中 |
RemoteTriggerTool |
远程触发 | 🟡 中 |
SleepTool |
主动模式等待 | 🟢 低 |
SyntheticOutputTool |
结构化输出生成 | 🟢 低 |
几个值得关注的工具:
AgentTool——子 Agent 生成。这是多 Agent 编排的基础设施。调用它时,会创建一个新的 Agent 实例,拥有自己的消息历史和工具集,但在同一个进程内运行。
ToolSearchTool——延迟工具发现。不是把 40 个工具的描述全部塞进 prompt,而是让模型先搜索相关工具,再按需加载完整描述。这是 token 经济学的关键设计。
EnterWorktreeTool——Git 工作树隔离。在多 Agent 并行工作时,每个 Agent 可以在独立的 git worktree 中操作,避免文件冲突。这是真正的"沙箱隔离"。
四、上下文管理:从 CLAUDE.md 到 Prompt Cache

上下文管理是 AI 编码工具的隐形战场。Claude Code 的上下文系统分三层:系统上下文、用户上下文和记忆系统。
4.1 系统上下文:5 个 git 命令并行执行
context.ts 中的 getSystemContext() 是这样收集项目信息的:
// 伪代码还原
async function getSystemContext() {
// 并行执行 5 个 git 命令
const [branch, mainBranch, status, log, userName] = await Promise.all([
git('branch --show-current'),
git('remote show origin'), // 提取默认分支
git('status'),
git('log --oneline -20'),
git('config user.name'),
])
// ...
}
并行化是关键。5 个 git 命令同时执行,而不是串行等待。在大型仓库中,git 命令可能需要几百毫秒,串行执行会让启动延迟累加到 1-2 秒。
截断逻辑也很有讲究:
const MAX_STATUS_CHARS = 2000
// git status 输出超过 2000 字符时,截断并添加提示
大型 monorepo 的 git status 可能有几万行输出。2000 字符的限制确保上下文不会膨胀失控,同时保留足够信息让模型理解项目状态。
BREAK_CACHE_COMMAND 注入:源码中有一个特殊的环境变量 BREAK_CACHE_COMMAND,可以注入额外的上下文。这是开发调试用的——注入一个独特的字符串,强制打破 Prompt Cache,确保拿到最新的 API 行为。
4.2 用户上下文:CLAUDE.md 的自动发现
getUserContext() 收集 CLAUDE.md 的内容。关键设计:
- 多层 CLAUDE.md:项目根目录、用户主目录、当前工作目录都可以有
CLAUDE.md,按优先级合并。 --bare模式:跳过自动发现,只使用显式指定的 CLAUDE.md。这在 CI/CD 场景中很有用——你不希望 CI 环境中的意外 CLAUDE.md 影响行为。memoize缓存:上下文收集结果会被缓存,避免每次对话循环都重新执行 git 命令和读取文件。
4.3 三层记忆架构
MEMORY.md ← 精选长期记忆(惜字如金,手动维护)
↑ 沉淀
memory/topic/ ← 主题文件(按主题组织,定期提炼)
↑ 整理
memory/daily/ ← 原始记录(每日笔记,不加工)
这个架构的设计哲学是"原始记录不丢,定稿精炼留存":
- 原始层:
memory/daily/YYYY-MM-DD.md是每日工作流水账,什么都记,不做过滤。信息不丢比格式漂亮更重要。 - 主题层:当某个话题在日记中出现 3 次以上,提炼到
memory/topic/下独立文件。跨天的信息在这里汇聚。 - 精选层:
MEMORY.md只保留最重要的长期记忆——用户偏好、关键决策、经验教训。定期回顾,过时的删掉。
这和人类记忆的工作方式惊人地相似:短期记忆(原始记录)→ 工作记忆(主题整理)→ 长期记忆(精选定稿)。
4.4 Prompt Cache:静态/动态分割
这是成本控制的核心设计。Anthropic API 支持 Prompt Cache——相同的 prompt 前缀可以缓存,后续请求只计算新增 token 的费用(折扣可达 90%)。
源码中通过一个特殊标记实现分割:
const DYNAMIC_BOUNDARY = '__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__'
- 静态部分(Boundary 之前):系统指令、工具描述、项目上下文等很少变化的内容。这部分可以被缓存,多次请求复用。
- 动态部分(Boundary 之后):对话历史、当前任务描述等每次都变化的内容。这部分每次都需要重新计算。
在多 Agent 场景下,renderedSystemPrompt(父 Agent 冻结的 prompt)允许子 Agent 直接复用父 Agent 的静态部分,进一步降低缓存成本。
4.5 四层上下文压缩
当对话历史超过 token 预算时,Claude Code 有四层递进的压缩策略:
- 主动摘要:在 token 使用量达到阈值时,主动调用 API 对历史消息做摘要,替换原始消息。
- 错误重试压缩:API 返回 token 超限错误时,触发紧急压缩,丢弃最旧的消息。
- 流式裁剪:在流式接收响应的过程中,如果发现 token 即将超限,实时裁剪上下文。
- 全量折叠:最后的手段——将所有历史消息折叠为一条摘要消息,只保留最近几轮对话。
这个设计体现了"优雅降级"的思想:先尝试最不损失信息的压缩方式,只有在必要时才动用破坏性更强的策略。
五、认证与安全:OAuth 2.0 + 卧底模式 + 反蒸馏
5.1 认证流程
Claude Code 的认证系统基于 OAuth 2.0 + JWT,本地凭证存储在 macOS 钥匙串中:
用户输入 /login
→ 打开浏览器跳转 Anthropic OAuth 授权页
→ 用户授权后,回调到本地 HTTP 服务器
→ 本地服务器获取 authorization code
→ 用 code 换取 access_token + refresh_token
→ 将 token 存入 macOS 钥匙串(Keychain)
→ 后续 API 调用使用 access_token
→ token 过期时用 refresh_token 自动刷新
源码中的 startKeychainPrefetch() 在启动时就并行预取钥匙串中的凭证,避免在用户首次交互时出现延迟。
5.2 Undercover Mode(卧底模式)
这是源码中最引人注目的未发布功能之一。卧底模式的设计目的是隐藏 AI 的存在痕迹:
- 在 git commit 中不添加 AI 辅助标记
- 在代码注释中不提及 Claude
- 在生成的文件中不留下 Anthropic 的指纹
- 工具调用的输出经过"去 AI 化"处理
从代码注释来看,这个功能是为企业客户设计的——有些组织不希望外界知道他们在使用 AI 辅助编码。
5.3 Anti-Distillation(反蒸馏)
这是一个防御性安全特性,目的是防止模型输出被用于训练竞品模型:
- 注入假工具定义:在工具列表中混入不存在的工具,如果 API 请求尝试调用这些工具,就说明有人在使用爬取的数据做推理。
- 在某些输出中嵌入不可见的水印标记。
- 对高敏感度的内部实现细节(如 system prompt 构建逻辑)做特殊处理,避免完整暴露。
这种"蜜罐"设计在安全领域很常见,但用在 AI 产品中还是首次见到完整实现。
六、多 Agent 编排:Coordinator 与 AgentTool

这是 Claude Code 架构中最前沿的部分。当单个 Agent 无法高效处理复杂任务时,Coordinator 会将任务分解给多个 Agent 并行执行。
6.1 Coordinator 模式
Coordinator(主 Agent)
├── 分解任务为子任务
├── 为每个子任务分配 Worker Agent
│ ├── Worker 1: 搜索相关代码
│ ├── Worker 2: 编写测试用例
│ └── Worker 3: 更新文档
├── 收集所有 Worker 的结果
└── 合并为最终输出
Coordinator 的核心能力:
- 任务分解:分析用户请求,确定哪些子任务可以并行执行。
- 资源分配:为每个 Worker Agent 分配独立的工具集和权限。
- 冲突解决:当多个 Worker 修改同一文件时,通过 git worktree 隔离,最终合并。
- 结果聚合:收集所有 Worker 的输出,去重,排序,生成最终回复。
6.2 AgentTool——子 Agent 的生命周期
AgentTool 是创建子 Agent 的工具。当一个 Agent 调用 AgentTool 时:
- 创建新的
ToolUseContext,继承父 Agent 的权限配置和 MCP 连接。 - 分配独立的消息历史(不继承父 Agent 的对话历史,只接收任务描述)。
- 子 Agent 在独立的执行上下文中运行工具调用循环。
- 子 Agent 的结果作为
ToolResult返回给父 Agent。 - 子 Agent 的 token 消费归入父会话的
cost-tracker。
6.3 KAIROS——始终在线的守护进程
源码中被引用 150+ 次的 KAIROS 是一个始终在线的后台守护进程。它不是按需启动的 Agent,而是一个持续运行的监控器:
- 监控文件系统变化,自动响应
- 在后台执行周期性检查
- 支持事件驱动的自动化工作流
- 与
CronCreateTool和RemoteTriggerTool协同工作
KAIROS 的存在意味着 Claude Code 的愿景不仅仅是"被动的编码助手",而是一个"主动的开发伙伴"。
6.4 ULTRAPLAN——30 分钟远程规划
另一个未发布功能 ULTRAPLAN 允许 Claude Code 花费长达 30 分钟进行远程规划,然后返回详细的执行计划。这与 Plan Mode 不同:
- Plan Mode 是交互式的,用户可以看到规划过程
- ULTRAPLAN 是非交互式的,在后台完成规划,结果一次性返回
- ULTRAPLAN 的规划深度更高,可以处理跨文件、跨模块的复杂重构
七、技能与插件:可扩展架构
7.1 技能系统(Skills)
技能是可复用的工作流定义,存储在 skills/ 目录下。每个技能包含:
- 触发条件:什么情况下激活这个技能
- 步骤定义:按什么顺序调用哪些工具
- 输入/输出模式:Zod schema 定义
- 上下文模板:技能执行时的 prompt 模板
用户可以通过 SkillTool 执行技能,也可以通过 /skills 命令管理技能。
7.2 插件系统(Plugins)
插件比技能更重量级,可以:
- 注册新的工具和命令
- 拦截和修改工具调用
- 添加自定义的 UI 组件
- 接入第三方服务
插件的加载通过 services/plugins/ 子系统完成,支持动态加载和卸载。
7.3 MCP(模型上下文协议)集成
MCP 是 Anthropic 推出的标准化协议,让 AI 工具可以与外部服务交互。Claude Code 的 MCP 实现包含:
- MCP 客户端管理:连接多个 MCP 服务器,每个服务器提供一组工具和资源。
- 动态工具注册:MCP 服务器注册的工具自动出现在 Claude Code 的工具列表中。
- 工具调用代理:
MCPTool将调用转发给对应的 MCP 服务器,处理结果转换。
// ToolUseContext 中的 MCP 字段
mcpClients: MCPServerConnection[]
mcpResources: Record<string, ServerResource[]>
八、功能标志:Bun 编译时消除与 44 个隐藏功能
8.1 Bun Feature Flag 机制
Claude Code 使用 Bun 的 bun:bundle 实现编译时死代码消除:
import { feature } from 'bun:bundle'
// 非活跃代码在构建时被完全剥离
const voiceCommand = feature('VOICE_MODE')
? require('./commands/voice/index.js').default
: null
这意味着 feature('VOICE_MODE') 为 false 时,整个 voice/ 目录的代码都不会出现在最终构建中——不是注释掉,不是条件跳过,而是物理上不存在。
8.2 已知的功能标志
| 标志 | 说明 |
|---|---|
PROACTIVE |
主动模式,AI 主动发起操作 |
KAIROS |
始终在线守护进程 |
BRIDGE_MODE |
IDE 桥接模式 |
DAEMON |
后台守护进程模式 |
VOICE_MODE |
语音输入模式 |
AGENT_TRIGGERS |
Agent 事件触发器 |
MONITOR_TOOL |
监控工具 |
这些标志控制着约 44 个隐藏功能,其中大部分在当前版本中处于关闭状态。这意味着 Claude Code 的已发布功能只是冰山一角。
九、代码质量观察:亮点与屎山
9.1 亮点
1. 类型安全到极致
Zod v4 + TypeScript 严格模式的组合,让整个代码库从输入验证到运行时类型检查都有完整保障。DeepImmutable 这样的工具类型在权限系统中发挥了关键作用。
2. 并行化思维
从启动时的 Promise.all 预取,到工具调用的并行执行,到多 Agent 的并行工作流,并行化思维贯穿整个代码库。这不是事后优化,是第一设计原则。
3. 优雅降级
四层上下文压缩、权限模式切换、缓存回退——每个可能失败的地方都有降级方案。系统不会因为某个组件的失败而整体崩溃。
4. Token 经济学
searchHint 延迟加载、Prompt Cache 静态/动态分割、工具结果预算替换——每一步都在精打细算 token 预算。这不是小气,是对成本的工程级敬畏。
9.2 屎山
1. 46K 行的 QueryEngine.ts
这是不可辩驳的屎山。46,000 行在一个文件里,即使是核心引擎也不该这么写。函数嵌套深度、圈复杂度、可维护性都是灾难。这反映了早期快速迭代的技术债——功能不断往里加,没有人敢重构。
2. 29K 行的 Tool.ts
同样的问题。类型定义和工具逻辑混在一起,29K 行的文件让 IDE 的类型推断都变得迟缓。
3. 缺失的模块边界
services/ 目录下混杂了 API 客户端、MCP、OAuth、LSP、分析等完全不同的关注点,缺乏清晰的模块边界。tools/ 目录下 40 个工具的实现也没有统一的结构规范。
4. 条件编译散落各处
feature() 调用散落在代码的各个角落,没有集中的功能标志管理。这导致很难追踪某个标志影响了哪些代码路径。
十、给开发者的启示
1. Source Map 是供应链安全的盲区
Claude Code 的泄露不是被黑客攻击,而是构建产物中包含了 source map 文件。每个发布 npm 包的开发者都应该检查 .map 文件是否被排除在生产构建之外。一个 .npmignore 或构建配置的疏忽,就可能暴露整个源码。
2. 工具型 AI 应用的核心是工具调用循环
Claude Code 的架构本质是一个"工具调用循环"——消息 → 工具 → 消息 → 工具……这个模式适用于所有需要 AI 与外部系统交互的场景。如果你在设计类似系统,QueryEngine 的模式值得参考。
3. 权限模型必须在类型系统层面锁死
Claude Code 的 DeepImmutable<ToolPermissionContext> 是一个优雅的设计。权限规则一旦创建就不可修改,工具实现不能通过篡改权限上下文来绕过安全检查。这种"不信任实现者"的设计哲学,在 AI 工具这种高风险场景中尤为重要。
4. Token 成本是需要工程级管理的
从 Prompt Cache 到延迟工具发现,从上下文压缩到预算替换——Claude Code 的每一个设计决策都在权衡 token 成本。如果你的 AI 应用不考虑 token 经济学,要么功能受限,要么成本失控。
5. 多 Agent 是下一波架构浪潮
Coordinator 模式、AgentTool、TeamCreateTool、git worktree 隔离——这些设计预示着一个趋势:AI 应用正在从"单体智能"走向"多 Agent 协作"。未来的 AI 编码工具不是更强的一个 Agent,而是多个专注 Agent 的团队。
结语
51.2 万行代码,一个 source map 的意外,让我们得以一窥 Anthropic 在 AI 编码工具领域的完整技术布局。从代码级细节来看,Claude Code 不是"聊天机器人套了个终端壳"——它是一个精心设计的 AI 开发环境操作系统,有完整的工具体系、权限沙箱、上下文管理和多 Agent 编排。
当然,46K 行的 QueryEngine.ts 也提醒我们:即使是最前沿的 AI 公司,也在和快速迭代的技术债搏斗。代码的优雅和系统的优雅,有时候是两件事。
源码仓库:https://gitee.com/chenjim/claude-code
本文基于 2026 年 3 月 31 日泄露的 Claude Code v2.1.88 源码快照分析,仅供技术研究和学习讨论。原始代码版权归 Anthropic 所有。
本文链接:Claude Code 源码深读:51 万行 TypeScript 被一个 source map 曝光 - https://h89.cn/archives/566.html
版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。