1. 项目概述:为什么我们要拆解 Claude Code 的 50 万行源码?

如果你是一名开发者,最近半年大概率用过或者至少听说过 Claude Code。它可能是目前市面上最“好用”的 AI 编程助手,那种感觉就像身边多了一个不知疲倦、知识渊博的结对编程伙伴。它能理解你整个项目的上下文,自主执行多步任务,从修复 Bug 到重构代码,甚至帮你运行 git 命令和 npm 脚本。但好用背后,是 Anthropic 开源出来的、超过 50 万行的 TypeScript 源码。面对如此庞大的代码库,绝大多数人的第一反应是望而却步:这从哪开始看起?

这正是我们启动 “how-claude-code-works” 这个项目的初衷。我们不是要做一个简单的 API 文档翻译,而是想扮演一个“引路人”的角色,带着你一起钻进这 50 万行代码的迷宫,把那些精妙的设计、踩过的坑、以及支撑起日活百万级产品的工程智慧,一点一点挖出来,用你能听懂的话讲明白。我们发现,市面上大多数关于 AI Agent 的讨论都停留在概念和 Demo 层面,而 Claude Code 是一个活生生的、正在被数百万开发者使用的生产系统。它遇到的每一个问题——比如对话太长怎么办、工具太多怎么管、如何防止 AI 执行 rm -rf / ——其解决方案都经过了真实场景的严酷考验。读懂它,你学到的不是纸上谈兵的理论,而是价值千万美元的实战经验。

2. 核心架构总览:一个生产级 AI Agent 的骨架

在深入细节之前,我们需要先建立起对 Claude Code 整体架构的宏观认知。这能帮助我们在后续阅读具体模块时,知道每一块“积木”应该放在哪个位置,以及它为何被设计成现在的形状。

2.1 核心数据流:从用户输入到 AI 响应的完整旅程

Claude Code 的核心是一个持续运行的 Agent 循环 。这个循环的起点是用户的自然语言指令,终点是 AI 完成用户期望的任务。整个过程可以被抽象为以下几个关键阶段:

  1. 会话管理与输入处理 :用户的指令首先被 QueryEngine 接收。它负责管理整个对话会话(Session),维护历史消息,并将新的用户查询包装成符合 Claude API 要求的格式。这里的一个关键设计是, QueryEngine 并非简单转发,它会根据当前对话状态、Git 仓库状态以及项目根目录下的 CLAUDE.md 文件,动态地构建和优化最终发送给模型的“系统提示词”和“上下文”。

  2. 模型推理与流式响应 :构建好的提示词被发送给 Claude 模型。Claude Code 的一个显著体验优势是“快”,这很大程度上得益于其 全链路流式处理 。模型生成的不是一个完整的、打包好的响应,而是一个个 token(可以理解为词或字)。系统在收到第一个 token 时就开始向终端渲染,让用户感觉响应是“实时”出来的,而不是等待几十秒后一次性弹出大段文字。

  3. 工具调用解析与预执行 :模型的响应除了纯文本,还可能包含“工具调用”的指令,比如 read_file run_shell 。这是最精妙的部分之一: 工具预执行 。系统不会傻等模型把一整段话说完(比如“我想先读一下 src/index.ts ,然后修改第 10 行…”),而是在模型输出工具调用指令的 同时 ,就开始解析并尝试执行这个工具。这意味着,当模型还在“思考”后续步骤时,文件可能已经读完了,结果已经准备好并注回上下文了。这巧妙地隐藏了网络 I/O 和工具执行的延迟。

  4. 上下文压缩与记忆管理 :随着对话轮次增加,上下文会越来越长。Claude Code 采用了一套 4 级渐进式压缩流水线 来应对。它不是等到超出窗口限制才报错,而是持续监控 token 使用量,在接近上限时自动触发压缩。这四级从轻到重依次是:裁剪旧内容、去重、折叠不活跃段落、最终手段是启动一个子 Agent 进行摘要。压缩后,系统还会自动恢复最近编辑的 5 个文件内容,确保 AI 不会“失忆”,忘记刚刚在改什么。

  5. 安全沙箱与权限控制 :允许 AI 在用户电脑上执行任意 Shell 命令,这是最危险也最强大的功能。Claude Code 为此构建了 5 层纵深防御体系 。从高层的权限模式(如“受限制模式”),到基于规则的模式匹配,再到最硬核的 Bash 命令的抽象语法树(AST)分析 ,系统会拆解命令的每一个部分,检查是否有危险操作(如尝试删除根目录、读取敏感环境变量)。任何一层拦截,命令都不会被执行。

2.2 关键子系统与设计哲学

除了主线流程,几个关键的子系统共同支撑起了 Claude Code 的复杂能力:

  • 工具系统 :统一管理着 66 个以上的内置和外部工具(通过 MCP - Model Context Protocol 集成)。所有工具遵循同一套接口,享受同样的安全检查和并发控制(读操作并行,写操作串行)。
  • 多 Agent 协作系统 :支持主从、协调器、集群(Swarm)多种模式。为了防止多个 Agent 同时修改文件产生冲突,它创新性地使用了 Git Worktree ,为每个 Agent 创建独立的代码副本。
  • 技能系统 :AI 的能力不是固定的。技能系统允许 Claude Code 动态加载和执行一些预定义的复杂操作流程(比如“运行测试套件并分析结果”),这些技能可以来自内置库、项目本地配置或远程仓库。
  • Hook 系统 :提供了极高的可扩展性。开发者可以通过 Hook 在关键生命周期节点(如工具调用前、模型响应后)插入自定义逻辑,甚至可以动态修改工具参数或拦截危险操作。

这个架构的核心设计哲学是 “故障静默恢复” “用户体验优先” 。许多在其他系统中会导致错误弹窗的异常(如上下文超限、临时网络问题),在 Claude Code 内部都被设计成了可自动恢复的流程,用户感知到的就是一个稳定、连贯的助手。

3. 深入 Agent 主循环:驱动一切的核心引擎

Agent 循环是 Claude Code 的“心脏”。理解它,就理解了整个系统是如何“思考”和“行动”的。

3.1 双层循环结构与“Continue Sites”

源码中,Agent 循环并非一个简单的 while 循环。它被设计成一个 双层状态机

外层循环管理着整个“任务”的生命周期,比如处理一次用户查询。内层循环则处理单次与模型的交互:发送提示词、接收响应、执行工具、处理结果。

最值得称道的是其 7 种“Continue Sites” 设计。你可以把它理解为 7 种不同的“故障恢复点”或“重试策略”。当循环中发生错误(如网络超时、上下文超限、模型输出格式错误)时,系统不会直接崩溃或向用户报错,而是根据错误类型,跳转到预设的某个“Continue Site”,从那里尝试恢复并继续。

例如:

  • CONTINUE_ON_STREAM_ERROR : 流式输出中断,尝试重新建立连接。
  • CONTINUE_ON_CONTEXT_WINDOW_EXCEEDED : 上下文超限,触发压缩流水线,压缩后重试。
  • CONTINUE_ON_INVALID_TOOL_CALL : 模型返回了无法解析的工具调用,丢弃该调用并请求模型重新思考。

这种设计使得整个系统异常健壮,用户遇到的“报错”情况被降到最低,因为大部分错误都在内部被消化和修复了。

3.2 工具预执行与流式工具执行器

“工具预执行”是提升感知速度的关键魔法。其实现核心是一个叫 StreamingToolExecutor 的组件。

当模型开始流式输出响应时,一个独立的解析器会并行工作,实时扫描输出的 token 流。一旦它识别出一个完整的工具调用 JSON 结构(可能模型还没输出完后面的文本), StreamingToolExecutor 就会立刻接管。

  1. 解析与验证 :首先验证工具调用格式是否正确,参数是否合法。
  2. 安全检查 :将工具调用送入权限与安全模块进行多层校验。
  3. 预执行 :对于“安全”且“可预测”的工具(如 read_file ),执行器会立即开始执行。对于写操作或危险命令,则会等待用户确认或更严格的安全检查。
  4. 结果回注 :工具执行的结果(如文件内容)会被格式化,并作为一个特殊的“工具响应”消息,插入到即将发送给模型的下一轮对话上下文中。这一切发生在模型生成后续内容的间隙。

这样,当模型“想”到下一步需要某个文件的内容时,这个内容可能已经准备好了,极大地减少了用户等待的“空窗期”。

实操心得:并发控制的精妙之处 工具执行并非完全并行。源码中有一个精细的并发控制逻辑:所有“只读”工具(如 read_file , search_code )可以并行执行,以最大化利用 I/O 等待时间。而所有“写”操作(如 edit_file , run_shell 如果可能修改状态)则被强制串行化,并通过一个队列管理。这是为了防止多个写操作同时进行导致竞态条件和不可预知的状态混乱。在你自己设计 Agent 工具系统时,这个“读并行、写串行”的原则非常值得借鉴。

4. 上下文工程:如何与百万 Token 的“记忆”搏斗

对于需要处理整个代码库的编程 Agent 来说,上下文长度是永恒的挑战。Claude Code 的解决方案不是一味追求更大的模型窗口,而是一套组合拳。

4.1 4 级渐进式压缩流水线

这是源码中最具工程美感的部分之一。压缩不是粗暴的截断,而是一个有状态的、逐步升级的决策过程。

  1. Level 1: 裁剪 :首先瞄准历史消息中“体积庞大”但“可能已过时”的部分,主要是很久之前工具调用的完整输出(比如之前读取的一个 1000 行的大文件内容)。系统会将这些内容截断,只保留一个摘要或元信息。
  2. Level 2: 去重 :利用哈希或精确匹配,快速识别并移除上下文中完全重复的段落(有时模型或工具可能会意外生成重复内容)。这步成本极低,效果有时却很好。
  3. Level 3: 折叠 :将一段时间内不活跃的对话段落(例如用户和 AI 在 10 轮对话前讨论的一个无关话题)进行“折叠”。折叠并非删除,而是将其替换为一个简短的标题占位符(如“[关于项目设置的早期讨论]”)。在需要时,理论上可以“展开”恢复(虽然当前实现中更多是作为压缩策略)。
  4. Level 4: 摘要 :当前面三级都无法释放足够空间时,启动终极手段——调用一个专用的“摘要子 Agent”。这个子 Agent 的任务是对整个冗长的对话历史进行智能摘要,保留核心决策、当前状态和关键信息,丢弃细节。摘要结果将替代原有长历史。

每一级压缩后,系统都会重新计算 token 数量,如果已经低于安全阈值,则停止,不再进行更激进(且成本更高、信息损失更大)的压缩。这是一种成本与收益的精细权衡。

4.2 压缩后的“记忆恢复”机制

如果压缩只是丢弃信息,那么 AI 很快就会忘记自己在干什么。Claude Code 设计了一个巧妙的 “记忆恢复” 机制。

在每次压缩操作 之后 ,系统会执行一个恢复步骤:

  1. 它会自动扫描并重新将用户 最近编辑过的 5 个文件 的内容,以完整或高亮的形式插入到压缩后的上下文中。
  2. 它会重新激活当前任务相关的“技能”(Skill)描述。

这意味着,即使对话历史被大幅压缩,AI 对“当前正在修改哪些文件”和“当前在执行什么任务”的核心记忆依然得以保留。这种设计完美契合了编程任务的场景特性:开发者最关心的是手头正在改的这几行代码。

注意事项:压缩的副作用与调试 虽然压缩机制很强大,但在深度调试复杂问题时,它有时会成为“黑盒”。如果你发现 Claude Code 突然忘记了很久之前你告诉它的一条重要约束,很可能是因为那段历史在压缩中被折叠或摘要了。对于需要超长上下文连贯性的任务,一个实践技巧是:在 CLAUDE.md 或系统提示词中,以结构化的方式(如列表、摘要)重申最关键的要求和约束,这些内容在提示词中优先级较高,不易被压缩掉。

5. 工具系统与安全沙箱:赋予 AI 手脚,并为其戴上镣铐

工具系统是 AI 与真实世界交互的桥梁,也是最大的安全风险来源。Claude Code 的工具系统设计体现了“能力与安全并重”的哲学。

5.1 统一的工具抽象与 MCP 集成

所有工具,无论是内置的 read_file ,还是通过 Model Context Protocol 连接的外部工具(如数据库客户端、JIRA API),都实现了同一个 Tool 接口。这个接口定义了工具的名称、描述、参数模式(使用 Zod 进行模式验证)和执行函数。

这种统一性带来了巨大好处:

  • 安全一致性 :所有工具调用都走同一套安全检查流水线。
  • 并发管理 :系统可以统一调度,实现读操作并行。
  • 输出处理 :大体积的工具输出(如超过 100K 字符的日志文件)会被自动写入临时文件,模型中只收到一个文件路径和摘要,需要时再按需读取,避免撑爆上下文。

MCP 的集成尤为出色。它支持多种传输方式(stdio、HTTP、SSE),内置了 OAuth 2.0 with PKCE 的认证流程,使得连接外部服务变得标准化且相对安全。

5.2 5 层纵深防御体系

安全不是单点,而是一个体系。Claude Code 构建了五道防线:

  1. 权限模式 :用户可以在“完全”、“受限”、“安全”等模式间切换。在受限模式下,许多写操作和 Shell 命令会被直接禁止。
  2. 规则匹配 :一套基于模式(正则表达式)的白名单和黑名单规则。例如,可以禁止所有包含 rm -rf 模式的命令,或只允许运行 npm run 开头的脚本。
  3. Bash AST 深度分析 :这是最核心、最硬核的一层。它不使用简单的字符串匹配,而是利用 tree-sitter 库对 Bash 命令进行 语法解析 ,生成抽象语法树。然后对这棵树进行遍历分析,检查多达 23 项安全规则,例如:
    • 命令中是否包含未转义的特殊字符( ; , | , && , > )可能用于注入?
    • 是否尝试访问敏感路径(如 /etc/passwd , ~/.ssh )?
    • 是否尝试修改环境变量或执行来自变量的命令?
    • 是否尝试进行网络访问(在某些模式下被禁止)? 这种基于 AST 的分析能有效防御许多基于字符串拼接的命令注入攻击。
  4. 用户确认 :对于高风险操作(如修改 package.json 、运行安装脚本),会弹出需要用户手动确认的对话框。这里还有一个细节:确认对话框有 200ms 的防抖 ,防止用户快速连击回车键导致误确认。
  5. Hook 校验 :最终防线。开发者或用户可以实现自定义的 Hook,在工具执行前进行最后一次校验,甚至可以动态修改参数(例如,自动给所有 rm 命令加上 --dry-run 参数先看看效果)。

只有当一个命令通过了这五层检查,它才会被真正执行。这种纵深防御确保了即使某一层被绕过,还有其他层提供保护。

6. 多 Agent 协作与技能系统:从单兵到团队作战

Claude Code 的强大不止于单个 AI。它的多 Agent 架构允许不同的 AI 实例协同工作,处理更复杂的任务。

6.1 三种协作模式

  1. 子 Agent :最常用的模式。主 Agent 可以将一个子任务(如“去查一下这个 API 的文档”)派发给一个子 Agent。子 Agent 在独立的上下文中运行,完成后将结果返回给主 Agent。主 Agent 会“等待”子 Agent 完成。
  2. 协调器 :一种特殊的 Agent,它 自身没有读写文件或执行代码的能力 。它的唯一职责是协调其他多个“工作者” Agent。你可以告诉协调器“重构这个模块”,它会将任务分解,指派给不同的工作者,并整合结果。这种强制性的权责分离有助于构建更可控的多智能体工作流。
  3. Swarm :多个对等的、有名字的 Agent 组成一个集群。它们之间可以通过“信箱”进行点对点的异步通信。每个 Agent 独立运行,拥有自己的目标和状态,适合模拟一些分布式问题解决场景。

6.2 Git Worktree:解决并发写入冲突的妙招

当多个 Agent 同时操作同一个代码库时,最大的挑战是写冲突。Claude Code 的解决方案非常工程化:它利用 Git Worktree

当启动一个新的协作 Agent(如子 Agent)时,系统不会让它直接操作主工作目录,而是使用 git worktree add 命令,从当前分支创建一个新的、关联的 Worktree(工作树)到另一个临时目录。这个新 Worktree 拥有独立的文件系统视图,但共享同一个 Git 对象数据库。

这样,每个 Agent 都在自己的沙盒目录中工作,修改是物理隔离的。当子 Agent 完成任务后,主 Agent 可以通过 Git 操作(如 merge、cherry-pick)将有价值的变更合并回主工作区。这从根本上避免了文件锁和并发写入的难题。

6.3 技能系统:AI 的“武器库”

技能是一组预定义的、可复用的操作序列或提示模板。例如,“运行单元测试并报告覆盖率”可以封装成一个技能。技能可以来自:

  • 内置技能库
  • 项目根目录下的 .claude/skills 文件夹
  • 远程技能仓库

技能系统采用懒加载和 Token 预算管理。不是所有技能描述都一次性加载到上下文中,而是根据当前任务相关性动态加载。系统会为技能描述分配一个 Token 预算,防止技能信息过多挤占核心对话空间。

技能在上下文压缩后会被优先保留或重新激活,确保 AI 即使在长对话中也不会忘记可用的“大招”。

7. 从零构建的启示:最小必要组件与架构演进

阅读 50 万行源码是为了理解,但理解之后是为了创造。 how-claude-code-works 项目的一个宝贵衍生品是配套教程 Claude Code From Scratch 。它用约 3000 行 TypeScript,带你一步步实现一个 Claude Code 的核心功能。这个“最小实现”与“生产实现”的对比,极具启发性。

7.1 七个核心组件

最小实现剥离了所有优化、边缘 case 处理和企业级功能,聚焦于七个最核心的组件:

  1. 会话管理 :维护对话历史。
  2. 提示词构建器 :组装系统指令、上下文、用户消息。
  3. 模型客户端 :调用 Claude API 并处理流式响应。
  4. 工具调用解析器 :从模型响应中提取工具调用指令。
  5. 工具执行器 :执行简单的 read_file edit_file 工具。
  6. 安全校验器 :实现一个最基本的命令黑名单。
  7. 主循环 :将以上所有组件串联起来。

通过构建这个最小系统,你会立刻理解 Agent 循环最基本的数据流和控制逻辑。然后,再回头看 Claude Code 源码,你就会明白:

  • 那个复杂的 StreamingToolExecutor 是为了解决工具预执行和并发问题。
  • 那套 4 级压缩流水线是为了解决上下文限制问题。
  • 那 5 层安全防御是为了让系统敢在生产环境运行 shell 命令。
  • 那庞大的 Hook 系统是为了满足不同用户的定制化需求。

7.2 架构演进的思考

从 3000 行到 50 万行,增加的不仅仅是代码,更是对 生产环境复杂性 的应对。这其中包括:

  • 可观测性 :大量的日志、指标和追踪点,用于调试和监控。
  • 错误恢复 :前文提到的 7 种 Continue Sites。
  • 性能优化 :启动阶段的 9 阶段并行初始化,将冷启动时间压缩到 235 毫秒。
  • 用户体验细节 :防抖确认、进度指示、输出格式化等。
  • 可扩展性 :完整的插件化架构(Hook、MCP)。

这个过程告诉我们,构建一个可用的 AI Agent 原型可能不难,但要构建一个稳定、安全、高效、可扩展的生产级系统,需要大量的工程设计和细节打磨。Claude Code 的源码就是这份经验的集大成者。

8. 总结与个人实践建议

通读 how-claude-code-works 的文档和源码,给我的震撼不亚于阅读一个顶级开源项目(如 VS Code)的架构分析。它清晰地展示了一个前沿的 AI 应用如何从实验室原型走向成熟产品。其中体现出的工程思维——例如对故障的静默处理、对用户体验的极致追求、对安全性的层层设防——值得所有软件工程师,尤其是 AI 应用开发者深思。

如果你也想深入 AI Agent 开发,我的建议是:

  1. 先跑起来 :跟着 claude-code-from-scratch 教程,用 3000 行代码实现一个最小可用的 Agent,建立最直观的感受。
  2. 带着问题读源码 :不要试图一次性读懂 50 万行。先想清楚你想解决什么问题(比如“如何管理长上下文?”),然后去精读相关的模块(如上下文压缩流水线)。
  3. 关注设计模式,而非具体实现 :Claude Code 是用 TypeScript 写的,但它的架构思想是语言无关的。工具抽象、状态机、Hook 系统、纵深防御,这些模式你可以用任何语言实现。
  4. 安全第一 :如果你开发的 Agent 需要执行外部命令或访问系统资源,请务必、务必、务必重视安全。Claude Code 的 5 层防御是一个极好的参考起点,即使你不能实现 AST 分析,至少也要有规则过滤和用户确认。

AI 编程助手正在改变开发者的工作方式,而理解像 Claude Code 这样领先产品的内部机制,能让我们不仅成为使用者,更能成为未来的创造者。这片新大陆的规则,正藏在它的源代码之中。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐