Claude Code 完整源码泄露了,花了一天读完全部源码,这是我发现的

「Claude Code 泄露事件全解析」
前两天发生了一件大事:Anthropic 的 Claude Code 完整源码泄露了。
起因挺离谱的。有人发现 npm 上 @anthropic-ai/claude-code 包里残留了 .map 文件,里面有个指向 Anthropic R2 存储桶的下载链接,没鉴权,直接就能下。zip 一解压,1903 个文件,51 万行 TypeScript,全部摊在眼前。
作为一个 Claude Code 的重度用户(也是 AI Agent 工程师),看到消息立刻 clone 下来通读了一遍。网上已经有很多文章在复述目录结构和技术栈了,这篇不聊那些。我只聊读完之后让我觉得”这个有意思”的东西。
4.2更新:这篇文章发了之后,私信被问爆了。为了不辜负大家期待,这两天肝出了很完善的开源项目,总结起来就两件事:
第一件:我用 950 行高质量 Python 代码重写了 Claude Code 51 万行代码的核心功能和设计。 下面分析的这些设计模式——四层上下文压缩、子代理生成、流式工具并行、搜索替换编辑——全部有可运行的 Python 实现。接入 Kimi、Claude、Gemini、Qwen 随便选。
完全开源,fork 下来读一遍你就能理解 Claude Code 的设计精华,然后就可以能在上面造你自己的 Coding Agent。已经有人拿去做毕设了。有用记得点 Star,这对我很重要:
https://github.com/he-yufeng/CoreCoder
https://zhuanlan.zhihu.com/p/2023060686217965634
第二件:写了 7 篇比这篇更深入的源码导读。 每篇拆一个核心设计模式,代码引用精确到行号,有工程权衡分析。从 Agent 循环到多 Agent 协作到 44 个未发布的 Feature Flag,比这篇分析讲得更细更透。导读也在同一个仓库里:
https://github.com/he-yufeng/CoreCoder/tree/main/article
https://zhuanlan.zhihu.com/p/2023020925688246285
言归正题,先说技术栈
Bun + TypeScript + React + Ink。TUI 层用 React 不算新鲜,Ink 2017 年就有了,Gatsby CLI、Prisma CLI 都在用。不过 Claude Code 的场景比一般 CLI 复杂不少:多个 Agent 并行、流式输出、工具执行中用户随时中断、权限弹窗。状态管理的复杂度到了这个级别,用 React 确实比手搓合理。
整个 Claude Code 最核心的文件是 src/query.ts,1729 行。注意不是 QueryEngine.ts(那个是外层的会话管理),真正的“大脑”在 query.ts 里,一个 while(true) 循环。
async function* queryLoop(params) {let state = { messages, toolUseContext, turnCount: 1, ... }while (true) {// 1) 一堆预处理:裁历史、压缩上下文、预取 memory 和 skills// 2) 调 Claude API(流式)// 3) 一边收流一边看有没有 tool_use block// 4) 有的话 → 检查权限 → 执行 → 结果塞回 messages → 回到 while// 5) 没有工具调用 → 退出}}
用过 Claude Code 的人都知道,长对话到后面它会自动”压缩”。我之前以为就是把早期对话摘要一下,读了源码才发现,它其实有四种不同粒度的压缩机制在同时工作:
-
HISTORY_SNIP:最精细的一层,直接把某些消息删掉,不做任何摘要。比如一个工具返回了 500 行搜索结果,模型只用了其中 3 行。剩下 497 行就是纯噪声,留着浪费 token,摘要它也是浪费 token,直接删最划算。 -
Microcompact:利用 API 层的 cache_deleted_input_tokens 能力,在缓存层面做编辑。它不改消息内容,而是告诉 API”这些 token 你缓存里有但别用了”。相当于在不动消息的情况下把 token 数降下来。 -
CONTEXT_COLLAPSE:把旧的对话轮次”归档”成摘要,维护一个类似 git log 的结构,每次新查询时重放。和 autocompact 的区别是它保留了结构,哪一轮做了什么事、结论是什么都还在,不是一坨糊在一起的摘要。 -
Autocompact:最后的兜底,调一次模型把整个历史压缩成一段话。
// StreamingToolExecutor.tsexport class StreamingToolExecutor {// 模型流式吐出一个 tool_use block,立刻开始执行addTool(block: ToolUseBlock, message: AssistantMessage): void { ... }// 并发安全的工具可以同时跑,写操作独占// 结果按接收顺序排队,保证输出确定性async *getRemainingResults(): AsyncGenerator<MessageUpdate> { ... }}
模型还在流式输出后面的内容,前面的工具就已经在跑了。每个工具有个 isConcurrencySafe 标记:读文件、grep 这种只读操作可以并行跑,写文件、bash 这种需要独占。结果按接收顺序缓冲,不会乱序。
用过 Claude Code 的人应该有感觉,它的工具执行响应比较快,原因之一就是这个。工具执行的延迟被藏在了模型推理的时间里,用户几乎感知不到。
const MAX_OUTPUT_TOKENS_RECOVERY_LIMIT = 3
模型输出撞到 max_output_tokens?循环不报错,”扣留”错误消息,悄悄重试,最多 3 次。对用户完全无感。
这段代码上面有段注释,模仿中世纪巫师口吻写的:
Heed these rules well, young wizard. For they are the rules of thinking, and the rules of thinking are the rules of the universe. If ye does not heed these rules, ye will be punished with an entire day of debugging and hair pulling.
做过 Agent 框架的人可能都习惯写一个 BaseTool 基类然后继承。Claude Code 完全没有继承,40 多个工具全是纯函数式的 buildTool() 工厂函数:
type ToolDef<T> = {name: stringdescription: stringinputSchema: ZodSchema<T> // Zod v4 做校验 + 自动生成 JSON Schemacall(input: T, ctx: ToolUseContext): AsyncGenerator<...>isReadOnly(): booleangetPermissions(): ToolPermission[]renderToolUse?(input: T): ReactNode // 直接渲染到终端getToolUseSummary?(input, result): string // 压缩上下文时的摘要}
每个工具完全自包含:schema、权限、执行逻辑、UI 渲染、压缩摘要,全在一个文件里。没有全局注册表,每个 session 动态组装工具池,静态工具、MCP 工具、Agent 定义的工具混在一起用。
其中最复杂的是 BashTool,单个文件 1143 行。它做的远不止 exec(command):
-
自动解析命令分类成 search/read/write,用于权限匹配 -
macOS 上走 sandbox-exec 沙箱,Linux 走 seccomp -
超过 15 秒的阻塞命令自动转后台 -
大输出存磁盘,只给模型一个文件路径引用 -
内置 sed 命令解析器,检测到 sed -i时 UI 从 “Bash” 变成文件编辑样式 -
复合命令( ls && git push)会被拆开逐段判定安全性
一个 BashTool 的复杂度就顶得上很多小型 Agent 框架的全部了。
import { feature } from 'bun:bundle'const voiceModule = feature('VOICE_MODE')? require('./voice/index.js'): null
feature() 是 Bun 的编译时宏。构建时被替换成 true 或 false,false 的分支直接被删除。不是”运行时不执行”,是从二进制文件里物理消失,连字符串字面量都不剩。
为什么?因为安全研究员会反编译你的二进制找隐藏功能。运行时 flag 再怎么关,字符串还在那里。编译时 DCE 才是真的”不存在”。
讽刺的是,他们在二进制层面做了这么多防护,最后被一个忘删的 .map 文件全部端掉了。
我搜到了二十多个编译时 flag,每一个都对应一个未发布的功能:VOICE_MODE、BRIDGE_MODE、DAEMON、KAIROS、COORDINATOR_MODE、PROACTIVE、ABLATION_BASELINE、CONTEXT_COLLAPSE、CHICAGO_MCP……
const enabled = checkStatsigFeatureGate_CACHED_MAY_BE_STALE('tengu_streaming_tool_execution2')
用于灰度发布和紧急 kill switch。所有 gate 名称都以 tengu_ 开头,tengu(天狗)是 Claude Code 项目的内部代号。从磁盘缓存读取,接受脏读,不阻塞启动。
这个发现挺有趣的。有个 flag 叫 ABLATION_BASELINE,启用后会一次性关掉思考模式、上下文压缩、自动记忆、后台任务:
if (feature('ABLATION_BASELINE') && process.env.CLAUDE_CODE_ABLATION_BASELINE) {for (const k of ['CLAUDE_CODE_DISABLE_THINKING','DISABLE_COMPACT','DISABLE_AUTO_COMPACT','CLAUDE_CODE_DISABLE_AUTO_MEMORY','CLAUDE_CODE_DISABLE_BACKGROUND_TASKS',]) {process.env[k] ??= '1';}}
做过 ML 研究的人都熟悉消融实验:逐个关掉组件看对最终效果的影响。但把这个方法论搬到产品工程上,在工业代码里我还是第一次见。
这意味着 Anthropic 每上线一个新功能(thinking、compact、memory……),都可以跑一组对照实验量化它的价值。不是”感觉有用就上”,是”数据证明有用才上”。
编译时 flag 门控住的那些功能,虽然在公开版二进制里看不到,但源码全暴露了。
src/voice/ 目录确认了语音模式的存在:
-
只支持 Claude.ai OAuth 认证(API key、Bedrock、Vertex 都不行) -
走专门的 voice_stream端点 -
有紧急 kill switch: tengu_amber_quartz_disabled -
从注释看已经开发完成,只是还没公开
src/bridge/ 有 31 个文件,实现了一个完整的远程控制系统。运行 claude remote-control 之后,你的本地环境就变成一个可以被 claude.ai 远程操控的”桥接环境”。
最多支持32 个并发会话,JWT 认证加可信设备机制,企业管理员可以通过策略禁用。这应该是为了让 claude.ai 网页版能直接操作你本地的开发环境,不用再手动复制粘贴代码了。
这个绝对是全源码里最出人意料的发现。
Claude Code 内置了一个完整的虚拟宠物系统,而且没有用 feature flag 门控,已经在每个用户的二进制里了:
// 18 种宠物export const SPECIES = [duck, goose, blob, cat, dragon, octopus, owl, penguin,turtle, snail, ghost, axolotl, capybara, cactus, robot,rabbit, mushroom, chonk] as const// 5 级稀有度export const RARITY_WEIGHTS = {common: 60, uncommon: 25, rare: 10, epic: 4, legendary: 1,}// RPG 式属性export const STAT_NAMES = ['DEBUGGING','PATIENCE','CHAOS','WISDOM','SNARK'] as const
18 种宠物,5 级稀有度(传说概率 1%),1% 闪光变体。还有帽子系统(皇冠、礼帽、螺旋桨帽、光环、巫师帽、豆豆帽、头顶小鸭子)和不同的眼睛样式。宠物属性用 Mulberry32 伪随机数生成器从用户 ID 确定性计算,每个用户绑定一只,不能刷。
在一个 51 万行的严肃工程项目里发现一套完整的抽卡养宠系统,还是挺有意思的。
但比宠物本身更有意思的是它物种名的编码方式:
const c = String.fromCharCodeexport const duck = c(0x64,0x75,0x63,0x6b) as 'duck'export const goose = c(0x67,0x6f,0x6f,0x73,0x65) as 'goose'export const capybara = c(0x63,0x61,0x70,0x79,0x62,0x61,0x72,0x61) as 'capybara'
18 个物种名全部用 hex 编码,一个都没用明文。注释写着:”One species name collides with a model-codename canary in excluded-strings.txt.”
也就是说,其中一个宠物名恰好是 Anthropic 某个未公开模型的内部代号。构建系统会 grep 二进制产物里有没有黑名单里的字符串,所以必须 hex 编码绕过检测。
到底是哪一个?这就要结合另一次泄露来看了。
3 月 28 日,也就是这次 npm 泄露的三天前,Anthropic 还出了另一件事:CMS 数据库权限没关,被 Fortune 记者翻出了近 3000 份内部文件。其中提到一个从未公开的模型叫 Claude Mythos,内部代号Capybara(水豚),定位在 Opus 之上的全新层级。
而在 Claude Code 源码的 prompts.ts 里,我找到了大量 @[MODEL LAUNCH] 注释(给新模型发布准备的 TODO checklist),里面反复出现这个名字:
// @[MODEL LAUNCH]: Update comment writing for Capybara// — remove or soften once the model stops over-commenting by default// @[MODEL LAUNCH]: False-claims mitigation for Capybara v8// (29-30% FC rate vs v4's 16.7%)
这些 TODO 还没完成,说明 Capybara 还没公开发布。但是 main.tsx 里已经有 capybara-fast、capybara-v2-fast[1m] 这些模型别名,说明 Anthropic 内部员工已经在日常使用了。
拼到一起就很清楚了:Capybara 是比 Opus 更强的下一代旗舰 Mythos 的内部代号。Opus 4.6 在代码里就叫 claude-opus-4-6,没有动物名。宠物系统里撞车的就是这只水豚。
顺带泄露了一个内部数据:Capybara v8 的虚假声明率 29-30%,比上一版 v4 的 16.7% 翻了快一倍。Anthropic 没有回退版本,而是在 prompt 层加指令做修补,内部员工先当小白鼠验证效果。
源码里还出现了另一个模型代号:
// @[MODEL LAUNCH]: Remove this section when we launch numbat.
Numbat(袋食蚁兽),又一个待发布的模型。和 Capybara 的关系目前还不清楚。
此外,Claude Code 项目本身的代号是 Tengu(天狗),不知道月亮指代的是什么😂
简单提两个设计,因为思路值得参考。
Skills 就是 Markdown 文件。.claude/skills/ 目录下放 .md 文件,YAML frontmatter 里写描述、触发条件、允许的工具、用哪个模型。Claude Code 读文件时如果发现目录下有 skills,会自动加载,不用显式注册。”约定优于配置”,很 Rails。
多 Agent 协调器意外地简单。Coordinator 模式下主 Agent 只有三个工具:生成 worker、给 worker 发消息、停止 worker。Worker 拿不到 TeamCreate 和 SendMessage,防止套娃。后端支持 tmux pane、in-process、remote 三种方式。
隐私保护写进了类型名:埋点数据的类型叫 AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS。用类型名本身提醒开发者”你确认过这不是代码或文件路径了吗”。简单,但有效。
投机执行:AppState 里有 speculationState,追踪每一轮的结束方式(bash / 文件编辑 / 正常结束 / 权限拒绝),用来预判下一步操作并提前执行。这解释了为什么 Claude Code 有时候“想”完就瞬间开始干活。
冷启动优化:--version 路径做到了零 import,直接读编译时内联的版本号,一个模块都不加载就退出。其他子命令走独立的 import() 路径。只有最终进主循环才加载完整的 React 应用。一个 800KB 的 React app,你不用的功能就不加载,启动时间自然快。
npm 发布时忘删 .map 文件,map 里引用了 R2 上的源码 zip,那个 URL 没有访问控制。就这么简单。
所以给所有发 npm 包的人提个醒:
-
package.json的 files字段要白名单制,只包含你想发布的东西 -
CI 里加一步检查发布产物有没有 .map文件 -
源码归档 URL 要有鉴权,别裸挂在 CDN 上 -
构建产物和源码的访问控制应该独立管理
他们在二进制里做了那么多防泄漏设计(编译时 DCE、物种名 hex 编码、excluded-strings 黑名单),最后被一个忘删的 map 文件全部端掉了。安全这件事,100 个环节做对 99 个,漏一个就等于没做。读完 51 万行代码,我最大的感受不是某个具体技术多牛,而是这个团队在用做研究的方法做工程。
消融实验基础设施、双层 feature flag、四种粒度的上下文管理、流式工具并行,每一个都不是拍脑袋加的,背后大概率有数据在支撑。这种“每个功能都有量化验证”的工程文化,比任何单点技术都值得学。
当然,宠物系统除外。那个纯粹是因为好玩。
源码我还在继续读,后面可能会写一篇深入某个模块的分析(BashTool 1143 行的沙箱和命令安全机制,或者 Coordinator 模式的多 Agent 编排细节,大家想看哪个?)。
感兴趣可以先关注。
CoreCoder仓库(用 950 行 Python 重写了 Claude Code 51万行代码的核心功能设计):
https://link.zhihu.com/?target=https%3A//github.com/he-yufeng/CoreCoder
本人领英主页,欢迎联系我:
https://www.linkedin.cn/incareer/in/yufenghe/
本文基于公开泄露的源码进行技术分析, Claude Code 所有代码版权归 Anthropic 所有。
审编|阿蓝
商务推广/稿件投递请添加:xinran199706(备注商务合作)




· 计划周期:深蓝学院将以3个月为一个周期,建立工程师&学术研究者的「同好社群」
· 覆盖方向:自动驾驶、具身智能(人形、四足、轮式、机械臂)、视觉、无人机、大模型、医学人工智能……16个热门领域
扫码添加阿蓝
选择想要加入的交流群即可
(按照提交顺序邀请,请尽早选择)
👇

夜雨聆风