乐于分享
好东西不私藏

深度拆解:Claude Code 源码揭秘!它为什么是目前最强的 AI 程序员?

本文最后更新于2026-03-31,某些文章具有时效性,若有错误或已失效,请在下方留言或联系老夜

深度拆解:Claude Code 源码揭秘!它为什么是目前最强的 AI 程序员?

【特别声明】本研究报告基于公开 npm 发布包与 source map 分析还原。所有分析内容仅供技术研究与学习使用,请勿用于非法用途。

最近,Claude Code 意外泄露了 map 文件,导致其源码文件被完整还原。我下载了 npm 包里的 cli.js.map,从中提取出了 4756 个源码文件。沿着入口、提示词、工具、权限、Agent 调度、插件、Hook 一路拆解下去,我发现了一个令人震惊的事实:

大家津津乐道的 Claude Code 的 System Prompt,其实只是冰山露出水面的一小块。

这篇文章,我会把冰山下面的部分摊开给你看。你不需要是做 Agent 产品的硬核工程师,也能从里面看到一套顶级的系统设计思路。看完之后,你再去看市面上任何一个 AI Agent 产品,都会比之前多一层极其敏锐的判断力。

一、大多数人对 Claude Code 的理解,停在了表面

现在网上流传的关于 Claude Code 的分析,绝大部分只聚焦在两件事:它的 System Prompt 写了什么?它调了哪些工具?

这两件事确实重要,但它们只是这个系统的“皮肤”。如果你拿到同样的 Prompt,接上同样的工具,照猫画虎写一遍,出来的东西和 Claude Code 的实际体验差距依然会非常大。

差在哪?差在 Prompt 背后有一整套编排机制,工具背后有一整条治理流水线,Agent 背后有一套分工和调度系统,生态扩展背后有一套让模型“知道自己能干什么”的感知通道。

这些东西加在一起,才构成了你用 Claude Code 时感受到的那个“稳”。这个稳,不是来自某段神奇的文案,而是来自极其扎实的工程底座。

二、源码结构第一眼:这不是 CLI 工具,这是一个运行平台

从 src/ 目录的顶层看,Claude Code 至少包含了这些核心模块:

  • 入口层 (entrypoints)
  • 常量与提示词 (constants)
  • 工具定义 (tools)
  • 运行时服务 (services)
  • 命令系统 (commands)
  • 协调器 (coordinator)
  • 记忆系统 (memdir)
  • 插件与 Hook 系统 (plugins / hooks)
  • 任务系统 (tasks)

光看这个目录结构就能感觉到,这不是一个简单的“把大语言模型(LLM)接到终端里”的套壳项目。

入口层更能说明问题。它有四个入口:CLI、初始化流程、MCP 模式、SDK。这意味着同一个 Agent 运行时,可以服务四种不同的交互界面。这是典型的平台化设计标志。

命令系统也不是点缀。它注册了 /mcp/memory/permissions/plan/agents 等十几个系统级命令。而且,命令系统不只加载内建命令,还统一加载插件命令、技能命令。所以,命令系统本身就是整个生态的入口。

回头想想,大部分开源 Coding Agent 的目录长什么样?通常是一个 main 文件,一个 prompt 文件,几个 tool 文件,再加一个 utils。Claude Code 的目录结构跟它们完全不在一个量级,这个量级差异不是为了好看,是因为它要解决的工程问题本身就更多、更深。

三、Prompt 不是一段话,是一台“动态组装机器”

这可能是整个源码里最反直觉的部分。

大多数人以为 System Prompt 是一大段固定文本,启动时塞给模型就完了。Claude Code 完全不是这样。它的 System Prompt 是由一个叫 getSystemPrompt() 的函数动态拼装出来的。

这个函数做的事,更像一个编排器。它先拼一组静态模块,再根据当前会话状态拼一组动态模块

  • 静态部分(宪法):
    包括身份定位、系统规范、做任务的哲学、风险动作规范、工具使用规范、语气风格等。不管什么会话,这些底线规则都不变。
  • 动态部分(当期政策):
    根据你这次用的工具、连了哪些 MCP、用的什么语言、开没开 brief 模式,动态注入 session guidance、环境信息、token budget 等。

💡 核心亮点:Token 经济学与缓存边界

源码里有一个叫 SYSTEM_PROMPT_DYNAMIC_BOUNDARY 的标记,注释里写得很清楚:边界之前的内容尽量保持 Cache 友好,边界之后是用户和会话特定的内容,不能乱改,否则会破坏缓存。

这意味着 Anthropic 在管理 System Prompt 的时候,已经在算经济账了。边界之前的内容因为稳定,可以被 API 层缓存,不用每次都重新计算;边界之后的内容因为会变,所以放在后面,不影响前面的缓存命中。

大部分人写 Prompt,根本不会想到这一层。但当你的产品每天要处理海量请求,每个 Token 都有成本的时候,这种设计直接决定了产品的商业可行性。

四、行为规范:怎么训一个 AI 工程师“不乱来”

Claude Code 有一个叫 getSimpleDoingTasksSection() 的模块,这可能是整个系统里最不起眼但最有用的部分。它做的事很简单:告诉模型什么该做,什么不该做。而且列得极其具体:

  • 不要加用户没要求的功能。
  • 不要过度抽象,不要瞎重构。
  • 不要做不必要的错误处理和兜底逻辑。
  • 先读代码再改代码,不要轻易创建新文件。
  • 方法失败时先诊断原因再换策略。
  • 结果要如实汇报,不能假装自己测试过了。

如果你用过其他 Coding Agent,你一定遇到过这些崩溃瞬间:让它改个 Bug,它顺手给你重构了半个文件;让它加个功能,它给你加了三层抽象;让它测一下,它说“测试通过了”,但其实根本没跑代码。

这些问题的根源不是模型笨,是模型的行为没有被约束。Claude Code 解决这个问题的方式,不是靠更聪明的模型,是靠把行为规范写成制度。

风险动作规范也是同样的思路。系统定义了什么叫“需要确认的风险动作”(如破坏性操作、修改共享状态等),并强调:不要用破坏性操作当捷径,遇到陌生状态先调查。这种设计的思路是把 Blast Radius(爆炸半径)意识编进系统。你不能指望 AI 每次都自己想到操作的后果,但你可以在系统层面强制它停下来确认。

五、多 Agent 分工:为什么一个人做不好所有事

源码里确认了至少六个内建 Agent:General Purpose、Explore、Plan、Verification、Guide、Statusline Setup。

这个设计选择不是为了炫技,它背后有一个很清晰的判断:让一个 Agent 同时做研究、规划、实现、验证,最后每件事都会做成一锅粥。

  • Explore Agent(纯只读模式):
    不能创建、修改、删除文件,不能运行改变系统状态的命令。它只能用 Glob、Grep、FileRead 探索代码。为什么要这么做?因为探索阶段如果不小心改了代码,后面的实现阶段就会出 Bug。把探索和实现的权限彻底隔离,是一种极其有效的安全设计。
  • Plan Agent(架构师):
    也是只读。它的职责是理解需求、探索架构、输出逐步实现计划。规划和实现分开,保证了 AI 在写代码前能专心想清楚怎么做,而不是急于动手。

六、Verification Agent:整个系统里最值钱的设计

Verification Agent(验证 Agent)的 Prompt,在整个源码里可能是写得最“狠”的一个。

它的核心方向根本不是“确认实现看起来没问题”,它的方向是:Try to break it(想办法搞坏它)!

Prompt 开头就点出了 LLM 最容易犯的两类验证失败模式:

  1. Verification avoidance(逃避验证):
    只看代码不跑检查,写个 PASS 就走了。
  2. 被前 80% 迷惑:
    UI 看起来还行,测试也过了,就忽略剩下 20% 的深层问题。

为了反制这种惰性,Prompt 强制要求了一系列硬核验证动作:必须跑 build、跑测试套件、跑 linter;前端改动要跑浏览器自动化;后端改动要用 curl 实测响应;数据库迁移要测 up/down 和已有数据。更狠的是,它要求做 adversarial probes(对抗性探测),主动去找边界情况和破绽,最后必须给出明确的 VERDICT(结论)。

这个设计解决了 LLM 验证工作中最常见的问题:“差不多就算了”。写代码的 Agent 往往会觉得自己写得没问题(自我确认偏见),但独立的验证 Agent 没有这个偏见,它的 KPI 就是找茬。这种“实现者和验证者分离”的思路,在传统软件工程里是常识,但在 AI Agent 系统里,Claude Code 是少有的真正落地的产品。

七、Agent 调度链:14 步 Pipeline 绝不是过度设计

一个子 Agent 从被触发到执行完成,在 Claude Code 里要经过一条长达 14 步的完整流水线:

  • 主模型决定调用 Agent 工具
  • AgentTool.call() 解析输入并判断类型
  • 选择 Agent 定义并构造 Prompt messages
  • 构造或继承 System Prompt
  • 组装工具池并创建专属 ToolUseContext
  • 注册 Hooks、Skills、MCP servers
  • 调用 runAgent() 内部调用 query() 进入主循环
  • 产出消息流,记录 transcript,处理生命周期,清理资源…

这看起来繁琐,但每一步都在解决具体问题。比如 Fork 路径与 Normal 路径的区分:当你 fork 一个子任务时,它会继承主线程的 System Prompt 和完整对话上下文。为什么?为了让 API 请求的前缀保持字节级一致,从而完美复用主线程的 Prompt Cache。

普通人做子 Agent 调度,想的是“子任务能跑起来就行”;Claude Code 想的是“子任务能跑起来,而且要尽量复用主线程的缓存,绝不白烧用户的 Token”。

八、工具执行:不是一步到位,是一条治理流水线

当模型决定调用一个工具时,Claude Code 绝不是简单粗暴地直接执行对应的函数。它的实际链路是:

解析 Metadata -> Zod schema 输入校验 -> 跑 validateInput -> 风险预判 (speculative check) -> 运行 PreToolUse Hooks -> 权限决策 -> 真正执行 -> 记录追踪 -> 运行 PostToolUse Hooks

这里面最精妙的是 Hook 系统。Hook 不只能记日志,它能改写输入,能直接放行或拒绝,能补充上下文信息。但 Hook 的权力是受控的:Hook 说 allow,不一定能绕过系统设置里的 deny 规则;如果工具要求用户交互,Hook 没提供替代输入,依然要乖乖走权限流程。

整条链路的设计哲学非常清晰:默认假设事情会出问题。模型可能乱传参数(所以有校验),操作可能有风险(所以有权限),执行可能失败(所以有失败 Hook)。提前把“可能出问题”的地方都堵住,系统才会抗打。

九、生态扩展:关键是让模型“知道”

Claude Code 有三套扩展机制:Skill(工作流包)、Plugin(行为扩展单元)、MCP(模型上下文协议)。

很多平台也有插件系统,但最大的问题是:模型本身不知道这些东西存在。就像你给一个人配了一整套顶级工具箱,但他根本不知道箱子里有什么。

Claude Code 的做法是,通过各种通道(如动态注入 System Prompt),把工具箱的清单和使用说明都放到模型看得见的地方。让模型感知到自己当前有哪些扩展能力、什么时候该用、怎么用。这才是生态真正能发挥作用的前提。

十、产品化的最后一公里:生命周期管理

在 runAgent() 的源码里,有大量不起眼但极其重要的代码:recordSidechainTranscript()cleanupAgentTracking()killShellTasksForAgent()

后台 Agent 有独立的控制器,支持异步完成和通知;前台 Agent 可以转后台。这说明 Anthropic 把日志记录、性能追踪、资源清理、会话恢复、前后台切换,都当成了运行时生命周期的正式组成部分。

大部分开源 Agent 系统只管“跑起来”,但任务中断了怎么续?脏状态怎么清?这些问题不解决,产品永远只能是个 Demo。Claude Code 跨越了这道鸿沟,完成了产品化的最后一公里。

💡 总结:你能从中学到什么?

拆解完这 4756 个源码文件,我们可以把 Claude Code 强大的秘密提炼为 5 条核心设计原则。这不仅适用于 Coding Agent,也适用于几乎所有需要 LLM 做复杂任务的系统:

  1. 不要信任模型的自觉性:
    好行为要写成制度(Prompt),坏行为要用 Runtime(运行时)去硬限制。
  2. 把角色拆开:
    至少把“做事的人”和“验收的人”分开,用对抗性验证打破 LLM 的自我确认偏见。
  3. 工具调用要有治理:
    从输入校验到风险预判,再到事后处理,必须形成完整的流水线,而不是裸调函数。
  4. 上下文就是预算:
    每个 Token 都有成本,要精打细算,善用动态边界和缓存复用。
  5. 生态的关键是模型感知:
    必须让模型明确知道自己有什么能力、什么时候该用。