今天我就带你一起,透过泄露的代码,了解Anthropic藏在Claude Code里的工程智慧。注:本文分析版本为 @anthropic-ai/claude-code v2.1.88
Claude Code到底是什么?
市面上绝大多数所谓的“AI Agent”产品,本质是“套壳API”:在一个聊天界面外,裹一层简单的函数调用。
但Claude Code的源码展示了一个完全不一样的世界:
-
规模惊人:1884个TypeScript文件,43种核心工具,87个斜杠命令,104个CLI命令,39个核心服务模块。这是一个庞大而完整的软件系统。
-
定位严肃:代码中随处可见的是对安全性、并发隔离、成本控制和长期会话状态的深度考量,这完全是一个生产级、企业级软件的架构思路。
-
核心目标:它要解决的,是如何让大模型在安全、可控、高效且经济的前提下,成为用户终端里一个真正可靠、能独立完成复杂任务的“智能体”。
简单说,Claude Code是一个Agent操作系统,而不仅仅是一个应用。
全景架构:八层精密的职责分离
通过梳理源码,我发现Claude Code的架构可以清晰地分为八个层次,每一层职责单一,通过清晰的接口协作,构成了一个高效运转的流水线。
理解这个分层,是理解其设计精髓的关键。
-
入口层 (Entry Points):这是系统的边界,统一处理来自终端CLI、外部SDK、MCP(模型上下文协议)服务器、乃至IDE插件(如VSCode)的所有请求。它确保了无论从何处进入,都能被归一化处理。
-
命令与技能层 (Commands/Skills):用户输入的/compact、/plan等87个命令在这里被解析和执行。这是功能特性的直接体现层,也是用户意图的集散地。
-
查询引擎层 (Query Engine):系统的“心脏”。它管理着最核心的Agent循环(思考->调用工具->观察结果->再思考),负责与Anthropic API通信,处理流式响应,维持对话的生命周期。这是“智能”发生的主要场所。
-
工具编排层 (Tool Orchestration):当模型决定要调用工具时,这一层负责智能地调度和执行。它引入了本文后面会详细讲的读写分区并发策略,是平衡安全与性能的关键枢纽。
-
代理层 (Agent Layer):这是实现“多智能体”能力的核心。它负责创建和管理子代理(Sub-agent) 来处理后台任务(如压缩对话),并支撑Swarm模式下的多代理团队协作。在这里,Agent被当作一等公民来管理。
-
服务层 (Service Layer):一个由39个服务构成的共享能力池。包括API客户端、MCP服务管理、记忆(Memory)系统、遥测分析、文件监控等。这些是支撑上层业务逻辑的通用基础设施。
-
基础设施层 (Infrastructure):整个系统的基石。包含了四层权限决策链、27种Hook扩展系统、基于AsyncLocalStorage的异步上下文隔离,以及会话状态的持久化机制。这一层保障了系统的安全性、可扩展性和稳定性。
-
渲染层 (Rendering Layer):最让我意外的一层。Claude Code复杂的终端UI,竟然是用React渲染的!它基于Ink框架深度定制,甚至引入了Yoga布局引擎来实现终端里的Flexbox布局,配合差量渲染技术,提供了流畅、无闪烁的现代CLI体验。这意味着前端开发者可以无缝地贡献复杂的交互界面。
这个八层架构,体现了经典软件工程中的“分离关注点”思想,使得系统高度模块化、易于维护和扩展。
十大核心设计,揭秘工程精髓
在宏观架构之下,是无数个精妙的细节设计。我挑了十个最具启发性分享给你。
- 异步上下文隔离:用AsyncLocalStorage解决“串台”难题
这是我认为最优雅的设计之一。
// utils/agentContext.ts
const agentContextStorage = new AsyncLocalStorage<AgentContext>()
export function runWithAgentContext<T>(context: AgentContext, fn: () => T): T {
return agentContextStorage.run(context, fn)
}
export function getAgentContext(): AgentContext | undefined {
return agentContextStorage.getStore()
}
Claude Code支持将Agent挂起到后台,然后开启新会话。这就意味着单个Node.js进程里可能同时运行着多个Agent。如果使用全局状态,数据必然乱套。
他们的解决方案极其简洁:利用Node.js原生的AsyncLocalStorage。
每个Agent启动时,用自己的上下文包裹执行函数。此后,在该Agent的整个异步调用链中,无论嵌套多深,都可以随时安全地取到自己的上下文,完全无需手动传递参数。
这就好比给每个Agent分配了一个独立的、线程本地存储的“背包”,彻底解决了并发污染问题。
- 工具编排的并发哲学:读写分区,而非蛮干
当模型一次回复中要调用多个工具(比如同时读三个文件)时,怎么执行?全串行太慢,全并行又可能引发写入冲突。
Claude Code的解决方案充满智慧:像数据库一样,引入读写锁思想。
执行前,先将所有待调用工具按“是否只读”进行分区。像Read、Glob、Grep这样的只读工具,安全无副作用,直接并发执行(默认上限10个)。
而像Edit、Write、Bash这样的写入工具,则老老实实串行执行,确保状态变更的可预测性。
这个简单的策略,在实际编码场景中(读远多于写)带来了巨大的性能提升。
- 成本控制的艺术:System Prompt分段缓存
与大模型API交互,token就是金钱。Claude Code在Prompt缓存上做到了极致。它将庞大的系统提示词拆分成多个逻辑片段,并为每个片段独立管理缓存。
代码中甚至出现了DANGEROUS_uncachedSystemPromptSection这样的变量名,强制开发者在破坏缓存时必须三思并进行代码审查。这种对缓存命中率的极致追求,直接转化为了可观的成本节约。
- 无侵入的扩展:27种Hook编织的全生命周期网
系统提供了27个不同的事件钩子(Hook),覆盖了工具执行、会话开始/结束、上下文压缩等完整生命周期。
工具生命周期
PreToolUse ──▶ PermissionRequest ──▶ [工具执行] ──▶ PostToolUse
│ │ │
可阻断执行 可决定权限 可修改输出
可修改输入 可返回 allow/deny
会话生命周期
SessionStart ──▶ SubagentStart ──▶ ... ──▶ SessionEnd
压缩生命周期
PreCompact ──▶ [压缩执行] ──▶ PostCompact
最厉害的是,这些Hook可以用任何语言编写(Bash、Python、Go等),通过标准输入输出与主进程通信。
例如,一个PreToolUse钩子可以检查即将执行的Bash命令是否包含rm -rf /,并直接修改或阻断它。这相当于为整个系统提供了一个强大的、面向切面的中间件系统,将定制权和管控权深度下放给了用户和企业。
- 多代理协作(Swarm)的弹性设计
Claude Code支持多个Agent组队干活。其设计体现了极强的弹性:它支持三种后端协作模式,并按优先级自动降级。
Swarm Coordinator
iTerm2 tmux In-Process
原生分屏 分屏 同进程
Mailbox (文件系统消息队列)
.claude/swarms/<team>/mailbox/
首选:iTerm2的原生分屏API,体验最集成。
次选:tmux分屏,通用性更强。
保底:同进程内隔离运行,利用前述的AsyncLocalStorage保证隔离。
Agent间的通信也摒弃了复杂的IPC,采用最朴素的基于文件系统的Mailbox(在.claude/swarms/目录下读写文件),简单且可靠。这种“优雅降级”的思维,保证了功能在各种环境下的可用性。
- 编译期特性门控:一份代码,多个产品
在代码中,你会看到大量if (feature('KAIROS'))这样的条件判断。这里的feature()函数来自Bun打包器,关键点在于:这是编译期行为。
Bun在打包时,会根据特性标志(Feature Flag)直接进行死代码消除。
这意味着,Anthropic可以用同一套代码库,通过不同的编译开关,构建出内部开发版、企业特供版和公开发行版等不同产品变体。
KAIROS(主动助手)、BUDDY(电子宠物)等炫酷的未发布功能,早已静静地躺在代码中。这比维护多个代码分支要高明和高效得多。
- “不失忆”的上下文压缩
我们都知道对话太长时需要压缩,但大多数方案只是粗暴地让AI总结一下历史。
Claude Code的/compact命令是一个长达1700多行的复杂流程:
压缩前:剥离图片等重型附件,减少传输量。
压缩中:用独立的子代理执行,并巧妙复用主会话的Prompt缓存以节省成本。
压缩后(精华):自动将你最近正在编辑的文件内容重新注入上下文,恢复之前的计划(Plan)文件,恢复已激活的技能(Skill)指令。
最后,它还会检查压缩前后可用的工具、代理列表是否有变,并通知用户。
目标是明确的:压缩不是为了缩短历史,而是为了腾出空间的同时,让Agent不丢失当前的工作上下文和关键知识,体验无缝衔接。
- 四层权限决策链:纵深防御的安全网
对于一个能执行Bash命令和任意文件写入的本地Agent,安全是生命线。Claude Code设计了一个从快到慢、逐层过滤的四层决策链:
Tool Call 进入
|
▼
[1] Rule-Based Check ———— 最快,glob/regex 模式匹配
| 无匹配规则
▼
[2] PermissionRequest Hooks — 用户自定义脚本决策
| 返回 passthrough
▼
[3] Auto Classifier ———— 分析上下文自动判断
| 仍无法决定
▼
[4] Interactive Dialog ———— 弹出终端 UI 询问用户
规则匹配层:基于预设的glob/regex规则快速放行或拒绝(如,允许修改所有.ts文件,拒绝修改.gitconfig)。
自定义Hook层:调用用户配置的PermissionRequest钩子脚本做决策。
AI自动分类器层:一个内置的ML模型(代码中称为YOLO分类器)分析上下文,自动判断风险。
交互询问层:弹出终端UI,最终由用户拍板。
绝大多数操作在第一层就被处理了,只有极少数模糊请求才会走到最后的交互层。这种设计既保证了效率,又构筑了纵深防御体系。
- 基于React的终端渲染引擎
当我看到ink/目录下的51个子目录和147个React组件时,我震惊了。
他们用React + 自研的Ink渲染器 + Yoga布局引擎,为终端构建了一整套现代化的UI开发体系。
这意味着:
组件化开发:复杂的终端界面被拆分成可复用的组件。
状态管理:可以使用React Hooks(源码中有88个自定义Hook!)来管理交互状态。
高性能渲染:利用差量更新,只重绘屏幕上变化的部分,避免了传统console.log拼接带来的闪烁问题。
这虽然引入了一定的复杂度,但对于Claude Code这样交互极其丰富的CLI工具来说,这笔工程投资带来了巨大的开发体验和用户体验红利。
- 渐进式包装的工程哲学
纵观这一套设计,我认为Claude Code最核心的竞争力在于它处在一个最基础的“思考-行动”Agent循环之上,系统性地、一层层地叠加了12层渐进式工程包装。
这些包装包括:子代理隔离、任务持久化、按需技能加载、团队协作抽象、成本缓存优化、全生命周期钩子、纵深安全权限、终端渲染抽象等等。
这揭示了一个重要趋势:AI Agent产品的竞争,正从“模型能力竞赛”转向“系统工程与架构设计竞赛”。
优秀的体验,更多来自于这些精巧的“外壳工程”,而不仅仅是底层模型本身的强弱。
做个总结
翻完这51万行代码,我最大的感触是:Claude Code的成功,是软件工程的胜利。
它没有依赖某个神秘的“黑科技”,而是将模块化、缓存贯穿、异步隔离、安全递进这些经典的软件设计原则,完美地应用到了AI Agent这个新兴领域。
它给我们的一个启示是:在追求更强大模型的同时,请同等甚至更多地关注你的架构设计、成本核算、安全边界和用户体验工程。
AI的未来,最终还是会属于那些既能仰望星空,又能脚踏实地,用严谨工程将技术潜力转化为稳定生产力的团队啊~