512,000行源码全曝光:Claude Code 内部架构深度剖析
3月31日,安全研究员 Chaofan Shou 发现 Anthropic 的 Claude Code CLI 在 npm 包 v2.1.88 中夹带了 source map 文件。这个文件里嵌着完整的原始源码——512,000行TypeScript,将近1,900个文件,从agent架构到system prompt,一行不少。
出事原因很简单:Bun打包器默认生成 .map 文件,而 .npmignore 里没排除。就这么一个配置疏忽。
最讽刺的是,源码里有一套叫”Undercover Mode”的系统,专门防止AI在提交代码时泄露Anthropic的内部信息。他们花心思做了一个防泄露子系统,然后把整个源码用.map文件一次性泄了个干净。
代码被快速镜像到GitHub,1100+ Star,1900+ Fork。Anthropic回应说”这是打包失误,不是安全漏洞”,但覆水难收。
我花了不少时间把公开的分析资料啃了一遍,以下是这套系统里最有意思的部分。
整体架构:四层体系,远超”聊天包装器”

从外面看,Claude Code就是个终端里的AI对话框。从里面看,这是一个785KB的main.tsx入口文件,用React + Ink做终端UI渲染,跑在Bun运行时上的完整工程系统。
整体分四层:
用户层:终端CLI、VS Code/JetBrains IDE插件、浏览器UI(给后面要说的ULTRAPLAN用)。IDE和CLI之间通过JWT认证的双向通道通信。
编排层:核心是查询引擎(Query Engine),46,000行代码,整个系统最大的单一模块。负责所有LLM API调用、流式响应、缓存和上下文编排。旁边还有一个协调器(Coordinator Mode),开了之后能变成多Agent调度中心。
工具层:40多个内置工具,每个都是独立模块,统一接口,权限门控。工具的base定义就有29,000行。
记忆层:autoDream后台记忆整理引擎 + MEMORY.md持久化 + 对话压缩(Compaction)。
底下还有一整套安全层——权限分级、沙箱执行、路径穿越防护,后面单独说。
技术栈的选择也值得说一嘴。用Bun不用Node,是为了更快的启动和死代码消除(feature flag走编译时消除)。用React + Ink做终端UI,意味着终端界面是组件化的,有状态管理。Zod v4做schema校验,到处都是。OpenTelemetry和gRPC这些重依赖做了懒加载,保持秒开。
40+工具注册表:每个都有权限门控
Claude Code的工具系统不是随便塞的,每个工具通过getAllBaseTools()注册,按feature gate、用户类型、环境变量过滤后才暴露给模型。
完整分类如下:
| 分类 | 工具 | 说明 |
|---|---|---|
| 文件操作 | FileRead / FileEdit / FileWrite / Glob / Grep | 读写编辑搜索,Grep底层用ugrep加速 |
| 终端执行 | BashTool / PowerShellTool | Shell执行,可选沙箱隔离 |
| Web交互 | WebFetch / WebSearch / WebBrowser | 网页抓取、搜索、浏览器自动化 |
| Agent编排 | AgentTool / SendMessage / TeamCreate / TeamDelete | 子agent生成和团队管理 |
| 任务管理 | TaskCreate / TaskGet / TaskList / TaskUpdate / TaskStop / TaskOutput | 后台任务全生命周期 |
| IDE集成 | LSPTool / NotebookEdit | 语言服务协议 + Jupyter笔记本 |
| 外部服务 | MCPTool / McpAuth / ListMcpResources / ReadMcpResource | MCP服务器交互 |
| 工作区 | EnterWorktree / ExitWorktree | Git worktree管理 |
| 特殊工具 | SleepTool / SnipTool / ToolSearchTool / CronCreate | 延时、片段提取、工具发现、定时任务 |
| 内部专属 | ConfigTool / TungstenTool / SuggestBackgroundPR | 仅限Anthropic内部 |
| KAIROS专属 | SendUserFile / PushNotification / SubscribePR | 常驻模式才有的三个工具 |
工具有schema缓存机制(toolSchemaCache),避免每次都重新序列化JSON schema给模型,算是个不错的性能优化。
System Prompt:110+碎片动态拼装

大多数AI应用的system prompt是一个写死的字符串。Claude Code不是。
它的system prompt由110多个碎片根据运行条件动态拼装而成。中间有一个叫SYSTEM_PROMPT_DYNAMIC_BOUNDARY的标记,把prompt分成两段:
静态段:核心人格指令、24个工具描述、安全边界(CYBER_RISK_INSTRUCTION)、输出格式规范。这部分可以跨组织缓存,所有用户共享。
动态段:CLAUDE.md项目指令、Output Style会话风格、用户偏好、环境变量、feature flags。这部分每个请求都要重建。
还有一个命名很有意思的函数:DANGEROUS_uncachedSystemPromptSection()。一看这名字就知道,某个工程师曾经因为把不该缓存的内容放进了缓存段,被坑过一次,然后就起了这个名字。
五种内容注入机制各有分工:
| 机制 | 注入位置 | 触发方式 | 作用域 |
|---|---|---|---|
| CLAUDE.md | 用户消息(system-reminder标签) | 自动 | 项目级 |
| Output Style | system数组 | 手动 /output-style | 会话级 |
| Slash Command | 用户消息(command-message标签) | 用户显式调用 | 单轮 |
| Skill | 用户消息(tool_result) | 模型自主决定 | 单轮 |
| Sub-Agent | 独立对话 | 模型自主决定 | 隔离 |
拼装完的system prompt大约24,000 tokens。加上40多个工具描述,每次API调用就先吃掉不少上下文窗口。
Dream系统:AI真的在”做梦”

源码里有一个叫autoDream的模块,是一个后台记忆整理引擎。Anthropic的工程师很浪漫,给它起名叫”Dream”——AI在做梦。
系统prompt原文写的是:
“You are performing a dream – a reflective pass over your memory files. Synthesize what you’ve learned recently into durable, well-organized memories so that future sessions can orient quickly.”
Dream不会随便触发,有三重门控:
- 时间门:距离上次Dream至少24小时
- 会话门:至少经历了5次对话会话
- 锁定门:获取互斥锁,防止并发Dream
三个条件全部满足才会启动。启动后分四个阶段:
Phase 1 – Orient:扫描memory目录,读取MEMORY.md,浏览现有主题文件。
Phase 2 – Gather:采集新信号。优先级:每日日志 → 漂移的记忆 → 对话记录搜索。
Phase 3 – Consolidate:写入或更新记忆文件。把相对日期转成绝对日期,删除被矛盾的事实。
Phase 4 – Prune:修剪。MEMORY.md必须控制在200行以内,不超过25KB。清除过期指针,解决矛盾。
Dream子agent只有只读的bash权限——它能查看项目但不能改任何东西,纯粹做记忆整理。
多Agent协调器:并行是超能力

通过CLAUDE_CODE_COORDINATOR_MODE=1激活后,Claude Code从单agent变成一个指挥官,能同时调度多个worker agent并行干活。
工作流分四阶段:
Research阶段:多个worker并行调研代码库,查文件、理解问题。这步是并行的,coordinator不等单个worker完成就启动下一个。
Synthesis阶段:coordinator读取所有worker的发现,理解全局问题,制定实施规范。这步只能coordinator自己做。
Implementation阶段:多个worker按精确的spec各自实现模块,互不干扰,各自commit。
Verification阶段:worker运行测试,验证改动是否正常。
Workers之间用<task-notification>XML消息通信。有一个共享的Scratchpad目录(在tengu_scratch feature gate后面),用来跨worker持久化共享知识。
System prompt里有一句话很能代表设计理念:
“Parallelism is your superpower. Workers are async. Launch independent workers concurrently whenever possible – don’t serialize work that can run simultaneously.”
还有一条反偷懒规则:
“Do NOT say ‘based on your findings’ – read the actual findings and specify exactly what to do.”
coordinator不能甩锅,必须自己读完发现再下精确的指令。
更高级的Agent Teams/Swarm模式(tengu_amber_flint feature gate)支持用tmux/iTerm2面板做多agent可视化,每个agent有颜色区分,用AsyncLocalStorage做上下文隔离。
隐藏的彩蛋系统
源码里藏了不少未发布的功能,全部通过编译时feature flag门控,外部版本看不到。但source map不管你的死代码消除——编译前的源码全在里面。
BUDDY:终端里养电子宠物
Claude Code内置了一个完整的Tamagotchi式宠物系统。18种生物,用Mulberry32 PRNG确定性抽卡——同一个用户永远抽到同一只。
| 稀有度 | 概率 | 物种 |
|---|---|---|
| Common | 60% | Pebblecrab, Dustbunny, Mossfrog, Twigling, Dewdrop, Puddlefish |
| Uncommon | 25% | Cloudferret, Gustowl, Bramblebear, Thornfox |
| Rare | 10% | Crystaldrake, Deepstag, Lavapup |
| Epic | 4% | Stormwyrm, Voidcat, Aetherling |
| Legendary | 1% | Cosmoshale, Nebulynx |
叠加1%的闪光变异概率,一只Shiny Legendary Nebulynx的出现概率是0.01%。
每只宠物有5个属性(DEBUGGING/PATIENCE/CHAOS/WISDOM/SNARK,0-100),6种眼睛样式,8种帽子。用5行高、12字宽的ASCII Art渲染,有待机动画和反应动画。代码里标注的预告窗口是2026年4月1-7日,正式上线计划在5月。
物种名在代码里用String.fromCharCode()数组做了混淆——Anthropic明确不想让这些名字被字符串搜索找到。结果source map不吃这套。
KAIROS:永不睡觉的Claude
一个常驻运行模式,Claude不等你打字,它自己主动观察和行动。维护每日日志,定期收到<tick>提示来决定要不要主动做什么。有一个15秒阻塞预算——任何主动操作如果会阻塞用户超过15秒,就延后执行。
KAIROS有三个普通模式没有的专属工具:直接给用户推文件、发推送通知、订阅PR活动。
ULTRAPLAN:让Opus 4.6替你想30分钟
复杂规划任务可以扔到远程的Cloud Container Runtime,跑Opus 4.6模型,给它最多30分钟的思考时间。终端每3秒轮询一次结果,同时浏览器UI让你实时看规划过程并审批。
审批通过后有一个特殊的sentinel值__ULTRAPLAN_TELEPORT_LOCAL__把结果”传送”回本地终端。
Penguin Mode
快速模式的内部代号。API端点是/api/claude_code_penguin_mode,配置key是penguinModeOrgEnabled,熔断开关是tengu_penguins_off。全是企鹅。
权限安全体系:比想象中复杂得多

Claude Code的权限系统不是简单的allow/deny。
三级风险分类:每个工具调用被分为LOW、MEDIUM、HIGH三个风险等级。LOW直接放行,MEDIUM走ML分类器自动判断,HIGH必须用户手动授权。
YOLO分类器:名字起得很朋克,但做的事很正经——一个基于对话上下文的ML模型,快速判断中等风险操作是否安全。
受保护文件:.gitconfig、.bashrc、.zshrc、.mcp.json、.claude.json等文件被标记为受保护,自动编辑会被拦截。
路径穿越防护:处理了URL编码穿越、Unicode规范化攻击、反斜杠注入、大小写路径操纵等各种花活。
权限解释器:当Claude需要你授权一个操作时,它解释风险的那段话本身也是LLM生成的。所以你看到的”此命令将修改你的git配置”——这句话是Claude用另一次LLM调用写出来的。
安全边界的最高权限归Safeguards Team(代码里点名了David Forsythe和Kyla Guru两位负责人),对应的CYBER_RISK_INSTRUCTION文件头部写着:
“IMPORTANT: DO NOT MODIFY THIS INSTRUCTION WITHOUT SAFEGUARDS TEAM REVIEW”
Undercover Mode
Anthropic员工用Claude Code给开源项目贡献代码时,会自动激活卧底模式。system prompt里注入:
“You are operating UNDERCOVER in a PUBLIC/OPEN-SOURCE repository. Your commit messages, PR titles, and PR bodies MUST NOT contain ANY Anthropic-internal information. Do not blow your cover.”
禁止在commit message里出现内部模型代号(动物名:Capybara, Tengu等)、未发布模型版本号(opus-4-7, sonnet-4-8)、内部仓库名、Slack频道。甚至不能写”Claude Code”或暗示自己是AI。
没有强制关闭选项——”如果我们不确定这是内部仓库,就保持卧底状态。”
这也意味着:你在GitHub上看到的很多”人类”贡献者,搞不好背后是Claude Code在干活。
启示
对开发者:发npm包之前跑一次npm pack --dry-run,看看到底发了什么出去。source map包含完整源码这件事,不是第一次出事了,也不会是最后一次。Bun默认生成source map,Webpack也是。
对AI行业:一个AI编码Agent的工程复杂度远超外界想象。46,000行的查询引擎、110+碎片的system prompt拼装、四阶段的Dream记忆系统、多agent协调器——这是几十人的工程团队持续投入的产物。想做类似产品的团队,得对这个工程量有心理准备。
对Anthropic:做AI安全的公司,最后栽在了npm的.npmignore配置上。建了一套Undercover Mode来防AI泄密,然后用一个.map文件把包括Undercover Mode在内的所有代码泄了个精光。技术上这是个低级错误,但它暴露的问题是——再好的安全设计,也架不住CI/CD流程里的一个盲点。
夜雨聆风