3月31日 Claude Code 源码泄露,51万行 TypeScript 被扒了个底朝天。全网都在分析架构,但大部分文章只是"翻译源码"。我想换个角度——用我这两个月的实战经验,去印证源码里的设计决策:它为什么这么做,以及这些设计在真实场景里到底好不好使。
背景:泄露了什么
3月31日,有人发现 Claude Code 的 npm 包里保留了完整的 source map。不是被黑,是 Anthropic 自己忘了剥离——一个构建层面的低级失误。
被扒出来的数据:
| 指标 | 数值 |
|---|---|
| 总代码量 | ~512,000 行 TypeScript |
| 源文件数 | 1,902 个 |
| 内置工具 | ~40 个 |
| 运行时 | Bun(不是 Node.js) |
| 终端 UI | React + Ink |
全网在分析架构的时候,我正在用 Claude Code 开发一个全自动化测试 Skill。两个月下来,踩了不少坑,也摸到了一些规律。看到源码的那一刻,很多之前"知其然不知其所以然"的体验,突然就对上了。
这篇文章不做源码翻译——那些文章已经够多了。我只聊 5 个让我"原来如此"的设计,每个都结合我的实战体感来说。
设计一:Agentic Loop——一个 while(true) 撑起整个系统
源码揭示的 Claude Code 核心,简单到让人意外:
while (true) {
1. 组装上下文(System Prompt + 对话历史 + 工具定义)
2. 调用 LLM
3. 解析响应(纯文本 or 工具调用?)
4. 如果是工具调用 → 执行工具 → 结果追加到对话历史 → 继续循环
5. 如果是纯文本 → 输出给用户 → 结束
}
就这么简单。没有复杂的状态机,没有 DAG 编排,没有工作流引擎。
实战体感
我做谛听 Skill 的时候,让 Claude Code 执行一个完整的测试流程:读需求 → 侦察页面 → 生成用例 → 逐条执行 → 输出报告。这个流程在 Agentic Loop 里就是:LLM 决定"接下来该调哪个工具" → 调用 → 拿到结果 → LLM 再决定下一步。
它的强大不在于循环本身,而在于让 LLM 自己做路由决策。 我的 Skill 描述文件就是一份"操作手册",LLM 按手册一步步走,每步自己决定该调什么工具。不需要我写 if-else 来编排流程。
这个设计的代价是:你没法精确控制执行顺序。 LLM 偶尔会跳步或重复步骤。我在 Skill 里加了大量"必须先做 X 再做 Y"的约束,就是在补这个确定性缺口。
设计二:Prompt Cache 三层分段——成本控制的命脉
这是源码里最让我感慨的设计。
Claude Code 把 System Prompt 按变化频率切成三段:
| 段 | 内容 | 变化频率 |
|---|---|---|
| 第一段 | 角色定义、工具 Schema、基础规则 | 几乎不变 |
| 第二段 | CLAUDE.md 内容、项目规则 | 会话内不变 |
| 第三段 | 环境信息(git status、当前文件等) | 每轮可能变 |
Anthropic API 支持 Prompt Cache:如果请求的前缀和上次一样,直接从缓存读,成本降低 90%。
这三段设计的意思是:不变的放前面,会变的放后面,最大化前缀命中长度。
实战体感
我现在理解了为什么 CLAUDE.md 这么重要——它不只是"配置文件",它是 Prompt Cache 的第二层缓存锚点。
我在 CLAUDE.md 里写了大量的 Skill 规则和项目约定。以前以为这只是"方便 AI 理解项目",现在知道了:这些内容被注入到 System Prompt 的第二段,整个会话期间都会命中缓存。写得越好,AI 理解越准,而且不额外花钱。
反过来也解释了一个现象:当我频繁改 CLAUDE.md 的时候,响应似乎变慢了——因为缓存被频繁失效了。
还有一个细节:子代理(Subagent)共享父代理的 Prompt Cache。 这就是为什么 Claude Code 派生子代理的速度那么快、成本那么低。我用 Agent 工具并行搜索代码的时候,体感确实比串行快很多,而且 token 消耗没有翻倍。
设计三:四层权限纵深防御——为什么它总在问你"确认吗"
用 Claude Code 的人都有个体感:它隔三差五就弹确认框。rm 要确认、git push 要确认、写文件也要确认。有时候觉得烦。
看了源码才知道,这背后是四层安全设计:
| 层 | 机制 | 作用 |
|---|---|---|
| 第一层 | Prompt 约束 | 告诉 LLM "不要做危险操作" |
| 第二层 | 工具级权限 | 每个工具声明安全等级(safe / confirm / dangerous) |
| 第三层 | 白名单/黑名单 | 用户配置允许/禁止的命令列表 |
| 第四层 | 沙箱隔离 | 文件限制在项目目录、命令有超时 |
关键设计原则:Fail-closed(默认拒绝)。
大部分开源 Agent 框架是 fail-open——默认放行,出了事再说。Claude Code 反过来:拿不准就拒绝,让用户确认。
实战体感
我做谛听 Skill 的时候,需要调用 Dima API 自动提 Bug 单。第一次跑的时候直接报权限拒绝——因为 MCP 工具默认需要确认。我得去 settings.local.json 里手动加白名单才行。
当时觉得麻烦,现在觉得这个设计是对的。如果默认放行,万一 AI 误判把正常功能当成 Bug 提了单,那就是生产事故。宁可多确认一次,不能多提一个假单。
源码还揭示了一个细节:子代理的权限范围严格小于等于父代理。 这解释了为什么我用 Agent 工具派生的子代理有时候会报"权限不足"——它不能做父代理没有权限做的事。安全,但偶尔不方便。
设计四:CLAUDE.md 四层记忆——文件系统就是最好的数据库
这个设计最"朴素",也最让我佩服。
Claude Code 的记忆系统没有向量数据库,没有 RAG,没有 embedding。就是 Markdown 文件 + 文件系统:
| 层级 | 位置 | 作用域 |
|---|---|---|
| 全局 | ~/.claude/CLAUDE.md | 所有项目通用 |
| 项目 | {project}/.claude/CLAUDE.md | 当前项目 |
| 本地 | {project}/.claude/local/CLAUDE.md | 当前机器,不入 Git |
| 自动记忆 | MEMORY.md + 子文件 | 跨会话自动积累 |
每次会话启动时,按层级从全局到本地依次加载,注入 System Prompt。
实战体感
我现在的 MEMORY.md 已经有 50+ 行了,包含:用户偏好、项目结构、认证机制、踩坑记录、Skill 开发进展。
最大的好处是:记忆是可编辑的。 我可以直接改 MEMORY.md 来修正 AI 的"记忆偏差"。如果用向量数据库,我怎么改?我连存了什么都看不到。
还有一个好处是可 Git 管理。项目级的 CLAUDE.md 可以提交到仓库,团队共享。这意味着测试规范、项目约定不只是活在某个人脑子里,而是变成了所有人(和 AI)都能用的工程资产。
这个设计让我反思了一个常见误区:不是所有 AI 应用都需要向量数据库。 当你的记忆量不超过几千行文本(大部分项目都是这样),文件系统就是最好的方案——简单、可控、可调试、零额外依赖。
设计五:Coordinator + Subagent——不是多 Agent 噱头,是分工
源码揭示了三种多代理模式:
- Fork:从父代理分叉出子代理,共享上下文和缓存,适合并行探索
- Coordinator:协调者只有"派生子代理"和"发消息"两个工具,不能直接操作文件
- Swarm:带 Team Lead 的团队模式,多代理并行
最有意思的是 Coordinator 模式的设计:协调者被故意"削弱"了——它不能读文件、不能写文件、不能执行命令。它唯一能做的就是拆分任务、派生子代理、汇总结果。
实战体感
我在谛听 Skill 里用 Agent 工具做并行搜索:同时搜索多个文件、同时查多个页面状态。体感是真的快。
现在看源码知道了原因:Fork 模式的子代理共享父代理的 Prompt Cache,所以并行的边际成本很低。不是多花 N 倍钱开 N 个代理,而是几乎只多花执行工具的钱。
Coordinator 模式的设计也让我理解了为什么 Claude Code 的"大任务"完成质量比"一个大 prompt 塞所有要求"要好——它把规划和执行分开了。 协调者专注于想"该做什么",子代理专注于做"具体怎么做"。关注点分离,质量更高。
给测试人的 3 个启发
看完源码,除了技术细节,我更关注这些设计背后的工程思想,因为这些思想可以直接用在我们做测试工具和 Skill 开发中:
1. 极简内核 + 丰富外围
Claude Code 的核心就是一个 while-true 循环。所有复杂性——缓存、权限、多代理、记忆——都是在这个内核之上叠加的独立层。
对测试的启发:做测试 Skill 也应该先把核心流程跑通(侦察→执行→报告),再逐步加能力(自愈、提单、截图内联)。我的谛听 Skill 就是这么迭代的——V1 只有 180 行,V3 变成 466 行,但核心循环没变。
2. 缓存不是优化,是架构
Prompt Cache 不是事后加的性能优化,而是在架构设计阶段就决定了的。System Prompt 的分段方式、CLAUDE.md 的加载时机、子代理的上下文继承——都是围绕"如何最大化缓存命中"来设计的。
对测试的启发:做 Skill 的时候,把稳定的规则放在 CLAUDE.md 里(命中缓存),把变化的参数放在每次调用时传入。这样既省钱又稳定。
3. 安全不是限制,是信任基础
Fail-closed 设计表面上让操作变麻烦了,但它建立了用户信任。我现在敢让 Claude Code 操作我的代码仓库,就是因为我知道它不会偷偷 git push --force。
对测试的启发:做全自动化测试工具的时候,缺陷提单、环境操作这类动作必须留人工确认点。谛听 Skill 里用例确认和缺陷确认两个卡点,就是这个思路。
最后
Claude Code 51 万行源码里,我印象最深的不是某个具体实现,而是一个工程哲学:
朴素的核心 + 极致的工程包装。
一个 while-true 循环,包上 12 层工程能力,就变成了 2026 年最受欢迎的开发工具(46% 开发者好感度,远超 Cursor 的 19%)。
这对我们做测试工具的人来说,是最好的参考样本——不要追求酷炫的架构,先把核心流程跑通,再一层层叠加工程能力。
更多 AI + 测试实战,关注公众号「测试进化论」—— 测试不会消失,只会进化。