diff --git a/CLAUDE.md b/CLAUDE.md index cfc0e06..31dafe4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,4 +17,5 @@ - 七牛 CDN 域名:`https://cdn.union.jxyunge.com/self-media/` - 图片存放路径规则:`{编号}/{文件名}`,如 `005/cover.jpg`、`005/rubin-gpu.jpg` - 禁止在正式文章中直接引用第三方图片链接(外链不稳定,可能失效) +- 写文章时不能使用占位符图片链接,所有图片必须先实际生成/下载到本地,再通过 `/upload-qiniu` 上传到七牛,最后用真实的七牛 CDN 链接替换到文章中 - 使用 `/upload-qiniu` 工具上传图片到七牛 diff --git a/articles/008-51万行源码意外曝光!我扒完了Claude Code的全部家底.md b/articles/008-51万行源码意外曝光!我扒完了Claude Code的全部家底.md new file mode 100644 index 0000000..158a79f --- /dev/null +++ b/articles/008-51万行源码意外曝光!我扒完了Claude Code的全部家底.md @@ -0,0 +1,405 @@ +# 51 万行源码意外曝光!我扒完了 Claude Code 的全部家底 + +> 发布日期:2026-04-01 +> 分类:技术解读 / 深度分析 +> 作者:老邓唠AI + +![封面](https://cdn.union.jxyunge.com/self-media/008/cover.png) + +## 引子:Anthropic 自己把自己扒光了 + +3 月 31 日凌晨,AI 圈炸了一颗核弹。 + +不是发新模型,不是融资消息——是 **Anthropic 自己把 Claude Code 的完整源码泄漏了**。 + +事情是这样的:Anthropic 在 npm 发布 `@anthropic-ai/claude-code@2.1.88` 时,打包进了一个 59.8MB 的 JavaScript Source Map 文件。这个 `.map` 文件本来是内部调试用的,但它直接指向了 Anthropic 自家 Cloudflare R2 存储桶上的**完整 TypeScript 源码压缩包**。 + +安全研究员 Chaofan Shou 第一个发现了这个链接,并在 X 上公开。 + + + +几小时内,**1,900 个 TypeScript 文件、512,664 行代码**被完整镜像到 GitHub 上。有人甚至在 2 小时内就用 Python 重写了核心逻辑,仓库星标飙到 5 万。 + +更讽刺的是,这已经是 Anthropic **第二次**犯同样的错误——2025 年 2 月就出过一次几乎一模一样的 source map 泄漏。而就在几天前,他们还刚刚意外暴露了内部模型代号 "Mythos"。 + +Anthropic 官方的回应是:*"This was a release packaging issue caused by human error, not a security breach."*(这是人为错误导致的发布打包问题,不是安全漏洞。) + +但代码已经在互联网上了。**DMCA 撤回通知能删仓库,删不掉已经下载到本地的 zip 包。** + +我花了一整天时间,把这 51 万行代码从头到尾扒了一遍。下面是我发现的全部内容。 + +--- + +## 一、这到底是个多大的工程? + +先看硬核数据: + +| 指标 | 数据 | +|------|------| +| 总代码量 | **512,664 行** TypeScript | +| 文件数 | 1,884 个 `.ts/.tsx` 文件 | +| 运行时 | Bun(不是 Node.js) | +| 终端 UI | 自研 Ink 分支 + React + Yoga Layout | +| Schema 校验 | Zod v4(所有工具输入、API 响应、配置文件) | +| 实验平台 | GrowthBook(所有开关都用 `tengu_` 前缀) | +| 最大单文件 | `print.ts` — **5,594 行,单个函数 3,167 行,12 层嵌套** | + +51 万行是什么概念?Linux 内核 0.01 版不到 1 万行,整个 VS Code 编辑器大约 30 万行。Claude Code 一个 CLI 工具,代码量比 VS Code 还多。 + +**这不是一个"LLM 套壳",这是一个完整的操作系统级智能体。** + +--- + +## 二、整体架构:五层洋葱 + +从源码来看,Claude Code 的架构像一颗洋葱,从外到内分五层: + +![五层洋葱架构](https://cdn.union.jxyunge.com/self-media/008/01-architecture.png) + +我们一层一层拆。 + +--- + +## 三、启动流程:快到你感觉不到 + +你在终端敲下 `claude` 回车,背后发生了什么? + +![启动流程](https://cdn.union.jxyunge.com/self-media/008/02-startup.png) + +关键设计:**入口文件只有 302 行**。通过动态 `import()` 延迟加载 4,683 行的主模块,确保 `claude --version` 这种简单命令毫秒级响应。所有重依赖(MCP、GrowthBook、keychain)都是**并行初始化**,不互相等待。 + +这是一个对启动速度有执念的团队写出来的代码。 + +--- + +## 四、核心引擎:一个永不停歇的循环 + +Claude Code 的心脏是一个**流式查询循环**。你发一条消息,引擎就开始转: + +![核心查询循环](https://cdn.union.jxyunge.com/self-media/008/03-query-loop.png) + +几个精妙的设计: + +**1. 输出恢复机制**:当模型因 `max_output_tokens` 截断时,自动续写,最多重试 3 次。你以为 Claude 一口气写了 2000 行代码?其实它可能分了 3 次才写完,但你看不出接缝。 + +**2. 工具结果预算**:工具返回的结果如果太大(比如 `grep` 搜到了 1 万行),不会直接塞进上下文窗口。而是**存到磁盘**,给模型一个文件路径 + 预览摘要。这就是为什么 Claude Code 处理大项目不容易爆上下文。 + +**3. 自动压缩**:当 token 数接近上下文窗口极限时(默认留 20,000 token 缓冲区),自动触发一轮"摘要"调用,把历史对话压缩成精简版。你聊了 100 轮,模型看到的可能只有最近 10 轮 + 前 90 轮的摘要。 + +--- + +## 五、工具系统:40+ 个武器库 + +Claude Code 注册了超过 40 个工具。但更有意思的是它们的**分类和调度策略**。 + +### 完整工具清单 + +| 分类 | 工具 | 说明 | +|------|------|------| +| 文件操作 | FileRead, FileWrite, FileEdit, Glob, Grep, NotebookEdit | 读写搜索编辑 | +| 系统执行 | Bash, PowerShell | Shell 命令 | +| 网络 | WebFetch, WebSearch | 抓网页、搜索 | +| 智能体 | Agent, SendMessage, TeamCreate, TeamDelete | 生成/管理子智能体 | +| 任务 | TaskCreate/Get/Update/List/Stop/Output | 后台任务管理 | +| 规划 | EnterPlanMode, ExitPlanMode | 只读规划模式 | +| Git | EnterWorktree, ExitWorktree | Worktree 隔离 | +| MCP | MCPTool, ListMcpResources, ReadMcpResource | MCP 协议 | +| 辅助 | ToolSearch, Skill, AskUserQuestion, Config, Brief, LSP, TodoWrite | 杂项 | +| **KAIROS 专属** | Sleep, CronCreate/Delete/List, Monitor, PushNotification | 自主守护模式 | + +### 读写分离调度 + +![读写分离调度](https://cdn.union.jxyunge.com/self-media/008/04-rw-dispatch.png) + +每个工具都声明了自己是否"并发安全"(`isConcurrencySafe`)。读文件、搜索这类只读操作可以 10 个并发跑;改文件、执行命令这类写操作必须排队。 + +这就是为什么你让 Claude Code 探索一个大项目时速度特别快——它在后台同时搜 10 个文件。 + +--- + +## 六、权限系统:六种模式,层层过滤 + +这可能是 Claude Code 最严谨的模块,**24 个文件**专门负责权限控制。 + +### 六种安全模式 + +| 模式 | 行为 | 典型场景 | +|------|------|---------| +| `default` | 每次新操作都问你 | 日常使用 | +| `plan` | 只能读,不能写 | 审查代码 | +| `acceptEdits` | 自动接受文件编辑 | 信任的项目 | +| `bypassPermissions` | 跳过所有检查 | YOLO 模式 | +| `dontAsk` | 不问就拒绝 | 最严格 | +| `auto` | **AI 自动判断安全性** | Anthropic 内部专用 | + +### 权限决策链 + +![权限决策链](https://cdn.union.jxyunge.com/self-media/008/05-permission.png) + +白名单支持 glob 模式:`Bash(git *)` 表示允许所有 `git` 开头的命令。连续被拒绝太多次后,系统会自动降级到手动确认模式,防止模型"硬闯"。 + +--- + +## 七、多智能体:一个包工头带一群工人 + +Claude Code 的多智能体系统分两层:**协调器**(包工头)和**工作智能体**(工人)。 + +![多智能体协调](https://cdn.union.jxyunge.com/self-media/008/06-multi-agent.png) + +协调器的系统提示词长达 300 多行,定义了**四阶段工作流**: + +1. **Research** — 先派人探索代码库 +2. **Synthesis** — 汇总发现,制定方案 +3. **Implementation** — 派多个工人并行修改 +4. **Verification** — 跑测试,验收结果 + +最有意思的是,这套协调逻辑**不是写在代码里的,而是写在 prompt 里的**。协调器通过系统提示词被"教会"如何当领导: + +> *"Do not rubber-stamp weak work"*(不要草率通过低质量工作) +> *"You must understand findings before directing follow-up work"*(必须理解发现后才能指导下一步) + +用 prompt 而非代码来编排多智能体——这可能是目前最优雅的 Agent 编排方式。 + +--- + +## 八、记忆系统:文件驱动的长期记忆 + +Claude Code 的记忆不是什么花哨的向量数据库,而是**最朴素的文件系统**: + +![记忆系统](https://cdn.union.jxyunge.com/self-media/008/07-memory.png) + +每条记忆是一个独立的 Markdown 文件,带 frontmatter(标题、描述、类型)。`MEMORY.md` 是索引文件,限制 200 行 / 25KB,直接注入系统提示词。需要回忆时,通过语义搜索找到相关记忆文件再注入。 + +还有一个**记忆老化**机制(`memoryAge.ts`),会逐步淘汰过时的记忆。 + +简单、可靠、可调试。不需要起一个 Pinecone 实例。 + +--- + +## 九、系统提示词:分段缓存的精密工程 + +Claude Code 的系统提示词不是一个大字符串,而是分成**静态段**和**动态段**,中间用一个缓存边界分隔: + +![系统提示词缓存](https://cdn.union.jxyunge.com/self-media/008/08-prompt-cache.png) + +静态段通过 Anthropic API 的 `cache_control` 参数跨会话缓存,动态段每次重新构建。这直接影响成本——缓存命中的 token **不计费**。 + +源码注释里有一句话让我印象深刻: + +> *"在按 token 付费时,缓存失效不再是计算机科学笑话,而是会计问题。"* + +为此,他们写了一个 `promptCacheBreakDetection.ts`,追踪 **12 个缓存破坏维度**。一旦检测到缓存命中率异常下降,就触发报警。 + +--- + +## 十、隐藏彩蛋:源码里的"不能说的秘密" + +这才是本次泄漏最劲爆的部分。源码里藏着大量**从未公开的功能和机制**。 + +### 10.1 反蒸馏机制:给竞争对手下毒 + +```typescript +// services/api/claude.ts (301-313) +if (feature('ANTI_DISTILLATION_CC')) { + if (process.env.CLAUDE_CODE_ENTRYPOINT === 'cli' && + shouldIncludeFirstPartyOnlyBetas()) { + result.anti_distillation = ['fake_tools'] + } +} +``` + +当启用时,向 API 请求注入 `anti_distillation: ['fake_tools']`。效果:**服务端会在工具调用中混入虚假的工具响应**。 + +什么意思?如果有竞争对手在录制 Claude Code 的 API 流量来训练自己的模型,这些虚假的工具数据就会**污染他们的训练集**。 + +简单说:**你抄我的作业?我给你塞几道错题。** + +不过分析者指出,这个机制其实很容易绕过——MITM 代理在请求到达 API 前就能剥离该字段。*"真正的保护可能是法律而非技术。"* + +### 10.2 伪装模式:Anthropic 员工的"隐身衣" + +`utils/undercover.ts` 大约 90 行,但信息量巨大。 + +当 Anthropic 内部员工用 Claude Code 在**外部开源仓库**工作时,这个模式自动启用。它会: + +- 删除所有 "Co-Authored-By: Claude" 标识 +- 禁止提及内部代码名(Capybara、Tengu 等) +- 隐藏内部 Slack 频道和仓库名 +- 不暴露未发布的模型版本号 + +最关键的一行注释: + +> *"There is NO force-OFF. This guards against model codename leaks."* + +**没有强制关闭开关。** 这是一扇单向门——一旦检测到外部仓库就自动启用,谁也关不掉。 + +这说明什么?**Anthropic 的员工一直在用 Claude Code 给开源项目提交代码,而且不想让任何人知道。** + +### 10.3 挫折感检测:它知道你在骂人 + +```typescript +// utils/userPromptKeywords.ts +const negativePattern = + /\b(wtf|wth|ffs|omfg|shit(ty|tiest)?|dumbass|horrible|awful| + piss(ed|ing)? off|piece of (shit|crap|junk)|what the (fuck|hell)| + fucking? (broken|useless|terrible|awful|horrible)|fuck you| + screw (this|you)|so frustrating|this sucks|damn it)\b/ +``` + +这段正则表达式扫描你的每一条输入。一旦检测到你在骂 Claude,就会弹出一个分享对话记录的提示——方便 Anthropic 内部员工快速提交反馈。 + +为什么用正则而不是让 LLM 判断?注释写道:**"正则比 LLM 推理更快更便宜"**——用于简单的脏话检测,杀鸡不用牛刀。 + +> 放心,这个功能在外部版本中是被编译器完整删除的。你骂了也没人知道。 + +### 10.4 KAIROS:一直在线的 AI 守护者 + +**KAIROS**——古希腊语"恰当的时机"——是这次泄漏中**最重磅的发现**。 + +它在源码中被提及超过 **150 次**,是一个完全已经开发好但尚未发布的功能:**始终在线的后台智能体**。 + +当前的 Claude Code 是"你问我答"模式。但 KAIROS 模式下,Claude Code 变成了一个**永不下线的守护进程**: + +- **autoDream**:你不用 Claude Code 的时候,它在后台自动"做梦"——整理记忆、合并发现、消除矛盾 +- **Cron 任务**:每 5 分钟刷新一次计划任务 +- **GitHub webhook**:监听你仓库的 PR、Issue、CI 状态 +- **推送通知**:主动找你汇报发现 + +autoDream 的触发条件也在源码里: +1. 距离上次整合 ≥ 24 小时 +2. 至少 5 个新会话 +3. 同一时间只有一个进程执行整合(进程锁) + +**这不再是一个工具,这是一个 AI 同事。** + +### 10.5 Buddy 伴侣系统:愚人节彩蛋?认真的? + +`buddy/` 目录包含一个完整的 **Tamagotchi 风格虚拟宠物系统**: + +- **18 种物种**:鸭子、龙、章鱼、水豚、幽灵、蘑菇……物种名用十六进制编码,因为其中一个物种名跟内部模型代号撞了 +- **稀有度**:普通(60%)、非凡(25%)、稀有(10%)、史诗(4%)、**传说(1%)** +- **RPG 属性**:DEBUGGING、PATIENCE、CHAOS、WISDOM、SNARK +- **防篡改**:宠物数据从 `hash(userId)` 确定性生成,不存在本地配置里。你想改配置文件把自己的宠物变成传说级?不好意思,每次都是现算的 + +活跃窗口:**2026 年 4 月 1-7 日**。没错,就是今天开始。 + +--- + +## 十一、Bash 安全:23 道防线 + +Claude Code 让 AI 在你电脑上执行 Shell 命令。这意味着安全必须做到极致。 + +`bashSecurity.ts` 实现了 **23 项编号安全检查**: + +| 防御类别 | 具体内容 | +|---------|---------| +| 命令注入 | 拦截 `$()`、`${}`、进程替换 `<()`、`>()` | +| Zsh 危险命令 | 封禁 `zmodload`、`sysopen`、`ztcp` 等 18 个内置命令 | +| 绕过攻击 | 防御 Zsh 的 `=curl` 等号展开(能绕过 curl 权限检查) | +| Unicode 攻击 | 检测零宽空格注入、不可见 Unicode 字符 | +| 环境变量 | 防御 IFS 空字节注入 | +| 混淆手法 | 花括号展开、注释/引号边界错位 | +| 审计发现 | HackerOne 报告的格式错误 token 绕过 | + +每次触发都记录事件(`tengu_bash_security_check_triggered` + 检查编号),用于持续监控攻击模式。 + +--- + +## 十二、250,000 次 API 调用的浪费——三行代码修好 + +源码注释里有一段让人目瞪口呆的记录: + +> **2026-03-10:BQ 分析显示 1,279 个会话在单次会话中有 50+ 连续自动压缩失败(最高达 3,272 次),全球每日浪费约 250,000 次 API 调用。** + +发生了什么?当上下文窗口接近极限时,Claude Code 会自动尝试压缩对话。但如果上下文已经太大,压缩也会失败。原来的代码没有失败上限,就**一直重试、一直失败、一直烧钱**。 + +修复方案: + +```typescript +const MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3 +``` + +**三行代码,每天省 25 万次 API 调用。** + +--- + +## 十三、44 个特性开关:产品路线图全曝光 + +Claude Code 使用 Bun 的构建时特性开关系统。`feature('FLAG_NAME')` 在编译时被常量折叠——外部版本中,所有内部功能的代码直接**物理删除**,不是注释掉,是根本不存在于二进制中。 + +但源码里全都有。一共 **44 个特性开关**,部分列举: + +| 开关 | 功能 | 状态 | +|------|------|------| +| `KAIROS` | 始终在线守护智能体 | 开发完成,未发布 | +| `VOICE_MODE` | 语音输入(Deepgram STT) | 开发完成,未发布 | +| `COORDINATOR_MODE` | 多智能体协调 | 已发布 | +| `BUDDY` | 虚拟宠物 | 愚人节限定 | +| `ANTI_DISTILLATION_CC` | 反蒸馏投毒 | 内部启用 | +| `DAEMON` | 后台守护进程 | 开发中 | +| `BRIDGE_MODE` | IDE 桥接 | 已发布 | +| `AGENT_TRIGGERS` | 智能体触发器 | 开发中 | +| `NATIVE_CLIENT_ATTESTATION` | 客户端证明 | 开发中 | +| `TORCH` / `ULTRAPLAN` | 未知 | 未知 | + +**这基本上就是 Anthropic 未来半年的产品路线图。** 竞争对手(OpenAI Codex、Google Gemini CLI)现在知道 Anthropic 在做什么了。 + +源码可以被重构。但战略意外,无法被 DMCA 撤回。 + +--- + +## 十四、社区的反应:2 小时 5 万星 + +泄漏发生后,GitHub 上迅速出现了多个镜像仓库。其中最火的是 `claw-code`——一个韩国开发者在凌晨 4 点被手机通知吵醒,**连夜用 Python 重写了 Claude Code 的核心架构**,然后推上了 GitHub。 + +> *"My girlfriend in Korea was genuinely worried I might face legal action from Anthropic just for having the code on my machine — so I did what any engineer would do under pressure: I sat down, ported the core features to Python from scratch, and pushed it before the sun came up."* + +2 小时后,仓库星标突破 **5 万**——成为 GitHub 历史上达到 5 万星最快的仓库。 + +还有人用 Rust 重写了 `runtime` 层(6 个 crate,31 个 `.rs` 文件),声称性能提升了 3 倍。 + +Anthropic 很快发出了 DMCA 撤回通知,删除了原始镜像。但 Python 重写版因为是"clean-room rewrite"(洁净室重写),目前仍然在线。 + +--- + +## 十五、这件事意味着什么? + +### 对开发者 + +Claude Code 的架构中有大量值得学习的模式: +- **流式优先**:整个链路都是 `AsyncGenerator` +- **读写分离的工具调度**:简单但高效 +- **prompt 编排多智能体**:用自然语言而非代码定义工作流 +- **文件驱动的记忆系统**:简单可靠,不依赖外部服务 +- **构建时死代码消除**:一套代码,两个版本 + +### 对行业 + +1. **AI 编程工具的复杂度远超想象**。51 万行代码、44 个特性开关、23 项安全检查——这不是一个周末 hackathon 能搞定的东西 +2. **KAIROS 代表着方向**。AI 编程助手正在从"你问我答"走向"始终在线的 AI 同事"。Anthropic 已经把它做出来了,只是没发布 +3. **开源 vs 闭源的边界越来越模糊**。Google 开源了 Gemini CLI,OpenAI 开源了 Codex agent SDK。但那些只是工具包。Claude Code 暴露的是**旗舰产品的完整内部实现**——这不一样 + +### 对 Anthropic + +这是一周内的第二次意外泄露。对于一家以"AI 安全"为品牌核心的公司来说,连续的安全事故无疑让人尴尬。不过换个角度看——如果你的代码足够好,被看到也不是世界末日。 + +从源码质量来看,Claude Code 的工程水平确实很高。虽然 `print.ts` 有 5,594 行、单个函数 3,167 行、12 层嵌套这种"史诗级屎山",但整体架构思路清晰、安全意识到位、性能优化深入。 + +**51 万行代码,一次意外,全世界都看见了。** + +--- + +> 如果你觉得这篇文章有价值,欢迎转发给身边的开发者朋友。这可能是我们唯一一次机会,看到一个世界级 AI 编程智能体的完整内部实现。 +> +> 关注"老邓唠AI",下一篇我们聊聊从 Claude Code 的架构中,普通开发者能学到哪些可以直接用的设计模式。 + +--- + +**参考资料:** + +- [The Register: Anthropic accidentally exposes Claude Code source code](https://www.theregister.com/2026/03/31/anthropic_claude_code_source_code/) +- [DEV Community: Claude Code's Entire Source Code Was Just Leaked](https://dev.to/gabrielanhaia/claude-codes-entire-source-code-was-just-leaked-via-npm-source-maps-heres-whats-inside-cjo) +- [Alex Kim's Blog: The Claude Code Source Leak](https://alex000kim.com/posts/2026-03-31-claude-code-source-leak/) +- [Fortune: Anthropic leaks its own AI coding tool's source code](https://fortune.com/2026/03/31/anthropic-source-code-claude-code-data-leak-second-security-lapse-days-after-accidentally-revealing-mythos/) +- [VentureBeat: Claude Code's source code appears to have leaked](https://venturebeat.com/technology/claude-codes-source-code-appears-to-have-leaked-heres-what-we-know) +- [GitHub: claw-code (Python rewrite)](https://github.com/instructkr/claw-code) diff --git a/articles/008/claude-arch-by-claude.md b/articles/008/claude-arch-by-claude.md new file mode 100644 index 0000000..6100747 --- /dev/null +++ b/articles/008/claude-arch-by-claude.md @@ -0,0 +1,796 @@ +# Claude Code 源码泄漏深度架构分析 + +> 2026年3月31日,Anthropic 在 npm 发布 `@anthropic-ai/claude-code@2.1.88` 时,意外将一个 59.8MB 的 JavaScript Source Map 文件打包在内。这个 `.map` 文件指向了 Anthropic 自家 Cloudflare R2 存储桶上的完整 TypeScript 源码压缩包。安全研究员 Chaofan Shou 率先发现并公开了这个链接,数小时内,1,900 个 TypeScript 文件、512,664 行代码被完整镜像到了 GitHub 上。 +> +> 本文将从架构层面,深入拆解这个"可能是当前最复杂的 AI 编程智能体"的内部实现。 + +--- + +## 一、技术栈总览 + +| 维度 | 技术选型 | +|------|---------| +| 语言 | TypeScript(1,884 个 `.ts/.tsx` 文件) | +| 运行时 | Bun(非 Node.js) | +| 终端 UI | 自研 Ink 分支 + React + Yoga Layout | +| Schema 校验 | Zod v4 | +| API 通信 | Anthropic SDK + SSE 流式传输 | +| 构建系统 | Bun Bundler(`bun:bundle` 特性开关) | +| 实验平台 | GrowthBook(`tengu_*` 前缀) | +| 可观测性 | OpenTelemetry + Datadog + Perfetto | + +--- + +## 二、整体架构 + +```mermaid +graph TB + subgraph Entry["入口层"] + CLI["cli.tsx
CLI 入口"] + MCP_ENTRY["mcp.ts
MCP Server 入口"] + SDK["agentSdkTypes.ts
SDK 入口"] + end + + subgraph Core["核心引擎"] + MAIN["main.tsx
4,683 行
REPL 编排器"] + QE["QueryEngine.ts
1,295 行
会话管理器"] + QUERY["query.ts
1,729 行
流式查询循环"] + API["claude.ts
3,419 行
Anthropic API 客户端"] + end + + subgraph Tools["工具系统"] + TOOL_DEF["Tool.ts
792 行
工具接口定义"] + TOOL_REG["tools.ts
389 行
工具注册表"] + TOOL_ORCH["toolOrchestration.ts
并发调度"] + TOOL_EXEC["toolExecution.ts
1,745 行
执行引擎"] + end + + subgraph Agent["多智能体"] + COORD["coordinatorMode.ts
协调器"] + AGENT_RUN["runAgent.ts
973 行
子智能体启动器"] + TASKS["tasks/
任务状态机"] + end + + subgraph Infra["基础设施"] + PERM["permissions/
24 个文件
权限系统"] + MCP_CLIENT["mcp/client.ts
3,348 行
MCP 客户端"] + BRIDGE["bridge/
27 个文件
IDE 桥接"] + MEMDIR["memdir/
9 个文件
记忆系统"] + INK["ink/
终端渲染引擎"] + end + + CLI --> MAIN + MCP_ENTRY --> MAIN + SDK --> QE + + MAIN --> QE + QE --> QUERY + QUERY --> API + QUERY --> TOOL_ORCH + + TOOL_ORCH --> TOOL_EXEC + TOOL_EXEC --> TOOL_DEF + TOOL_REG --> TOOL_DEF + + TOOL_EXEC --> AGENT_RUN + COORD --> AGENT_RUN + AGENT_RUN --> TASKS + AGENT_RUN --> QUERY + + TOOL_EXEC --> PERM + MAIN --> MCP_CLIENT + MAIN --> BRIDGE + QE --> MEMDIR + MAIN --> INK +``` + +--- + +## 三、启动流程 + +```mermaid +sequenceDiagram + participant User as 用户终端 + participant CLI as cli.tsx + participant Main as main.tsx + participant GB as GrowthBook + participant MCP as MCP Servers + participant REPL as REPL 循环 + + User->>CLI: claude 命令 + CLI->>CLI: 快速路径检查
(--version, --dump-system-prompt) + CLI->>Main: 动态 import main.tsx + + par 并行初始化 + Main->>GB: 加载特性开关 + Main->>Main: 读取 settings / MDM / keychain + Main->>MCP: 连接 MCP 服务器 + Main->>Main: 加载工具 & 命令 + end + + Main->>Main: 构建系统提示词 + Main->>REPL: launchRepl() + REPL->>User: 就绪,等待输入 +``` + +**关键设计**:`cli.tsx` 仅 302 行,通过动态 `import()` 延迟加载 `main.tsx`(4,683 行),确保 `--version` 等快速路径毫秒级响应。所有重量级依赖(MCP、GrowthBook、keychain)都通过并行初始化加载。 + +--- + +## 四、核心查询循环 + +### 4.1 QueryEngine — 会话管理器 + +`QueryEngine` 是 SDK/headless 模式下的会话管理器,一个实例管理一次完整对话: + +``` +QueryEngine +├── mutableMessages: Message[] // 消息历史(随对话增长) +├── abortController: AbortController // 会话级中止控制 +├── permissionDenials: SDKPermissionDenial[] // 权限拒绝记录 +├── totalUsage: NonNullableUsage // Token 用量聚合 +├── discoveredSkillNames: Set // 每轮发现的技能 +└── loadedNestedMemoryPaths: Set // 已加载的 CLAUDE.md 路径 +``` + +核心方法 `submitMessage()` 是一个 `AsyncGenerator`,每次调用经历: + +1. 构建系统提示词(`fetchSystemPromptParts()`) +2. 处理斜杠命令(`processUserInput()`) +3. 持久化用户消息到 transcript +4. 进入流式查询循环(`query()`),yield 出 `SDKMessage` +5. 处理上下文压缩、权限、最大轮次限制 + +### 4.2 query.ts — 流式查询循环 + +```mermaid +flowchart TD + START["用户消息"] --> BUILD["构建查询配置"] + BUILD --> CALL["queryModelWithStreaming()
调用 Anthropic API"] + CALL --> STREAM["流式接收响应"] + STREAM --> CHECK{是否有工具调用?} + + CHECK -->|有| RUN_TOOLS["runTools()
执行工具"] + RUN_TOOLS --> BUDGET["applyToolResultBudget()
结果预算控制"] + BUDGET --> HOOKS["executePostSamplingHooks()"] + HOOKS --> COMPACT{"需要压缩?"} + COMPACT -->|是| AUTO_COMPACT["autoCompactIfNeeded()"] + AUTO_COMPACT --> CALL + COMPACT -->|否| CALL + + CHECK -->|无| RECOVERY{max_output_tokens
恢复?} + RECOVERY -->|是,≤3次| CALL + RECOVERY -->|否| STOP_HOOKS["handleStopHooks()"] + STOP_HOOKS --> END["返回结果"] +``` + +**关键机制**: +- **Output Recovery**:当模型因 `max_output_tokens` 截断时,自动重试最多 3 次 +- **工具结果预算**:大结果持久化到磁盘,用文件路径 + 预览替代,防止上下文窗口膨胀 +- **自动压缩**:接近上下文窗口限制时触发对话摘要压缩 +- **依赖注入**:`QueryDeps` 接口注入 `callModel`、`microcompact`、`autocompact`、`uuid`,方便单元测试 + +--- + +## 五、工具系统 + +### 5.1 Tool 接口 + +`Tool` 是一个功能丰富的接口,定义了工具的完整生命周期: + +```mermaid +classDiagram + class Tool { + +name: string + +description(input, options): string + +inputSchema: ZodSchema + +call(args, context, canUseTool, parentMessage, onProgress?) + +checkPermissions(input, context): PermissionResult + +validateInput(input, context): ValidationResult + +isReadOnly(input): boolean + +isConcurrencySafe(input): boolean + +isDestructive(input): boolean + +maxResultSizeChars: number + +shouldDefer: boolean + +renderToolUseMessage(input, options): ReactNode + +renderToolResultMessage(...): ReactNode + +toAutoClassifierInput(input): string + } + + class ToolUseContext { + +options: Options + +abortController: AbortController + +appState: AppState + +permissionContext: PermissionContext + +fileStateCache: FileStateCache + +sessionMetadata: SessionMetadata + } + + Tool --> ToolUseContext : 接收 +``` + +### 5.2 完整工具清单 + +源码中注册了 **40+ 个工具**,按功能分类: + +| 分类 | 工具名 | 说明 | +|------|--------|------| +| **文件操作** | FileReadTool, FileWriteTool, FileEditTool, GlobTool, GrepTool, NotebookEditTool | 文件读写、搜索、编辑 | +| **系统执行** | BashTool, PowerShellTool | Shell 命令执行 | +| **网络访问** | WebFetchTool, WebSearchTool | 网页抓取、搜索 | +| **智能体** | AgentTool, SendMessageTool, TeamCreateTool, TeamDeleteTool | 多智能体生成与协调 | +| **任务管理** | TaskCreateTool, TaskGetTool, TaskUpdateTool, TaskListTool, TaskStopTool, TaskOutputTool | 后台任务管理 | +| **规划模式** | EnterPlanModeTool, ExitPlanModeTool | 只读规划模式切换 | +| **Worktree** | EnterWorktreeTool, ExitWorktreeTool | Git Worktree 隔离 | +| **MCP** | MCPTool, ListMcpResourcesTool, ReadMcpResourceTool | MCP 协议交互 | +| **其他** | ToolSearchTool, SkillTool, AskUserQuestionTool, ConfigTool, BriefTool, LSPTool, TodoWriteTool | 工具搜索、技能、配置等 | +| **KAIROS 专属** | SleepTool, CronCreateTool, CronDeleteTool, CronListTool, MonitorTool, PushNotificationTool | 自主守护模式工具 | + +### 5.3 工具执行调度 + +```mermaid +flowchart LR + subgraph Parallel["并发批次"] + direction TB + G1["GlobTool ✓"] + G2["GrepTool ✓"] + G3["FileReadTool ✓"] + end + + subgraph Serial["串行执行"] + direction TB + S1["FileEditTool"] + S2["BashTool"] + end + + INPUT["工具调用列表"] --> PARTITION{"isConcurrencySafe?"} + PARTITION -->|true| Parallel + PARTITION -->|false| Serial + Parallel --> MERGE["合并结果"] + Serial --> MERGE +``` + +`toolOrchestration.ts` 将工具调用分为两类: +- **只读工具**(`isConcurrencySafe=true`):`GlobTool`、`GrepTool`、`FileReadTool` 等,最多 10 个并发执行 +- **写入工具**(`isConcurrencySafe=false`):`FileEditTool`、`BashTool` 等,严格串行执行 + +--- + +## 六、权限系统 + +权限系统由 24 个文件组成,是 Claude Code 安全模型的核心。 + +### 6.1 权限模式 + +| 模式 | 说明 | +|------|------| +| `default` | 每次新操作提示用户确认 | +| `plan` | 只读规划模式,禁止写操作 | +| `acceptEdits` | 自动接受文件编辑 | +| `bypassPermissions` | 绕过所有权限检查 | +| `dontAsk` | 从不询问(自动拒绝未允许的操作) | +| `auto` | AI 驱动的自动审批(Anthropic 内部专用) | + +### 6.2 权限决策流程 + +```mermaid +flowchart TD + REQ["工具调用请求"] --> DENY{"在 alwaysDeny 规则中?"} + DENY -->|是| BLOCKED["❌ 拒绝"] + DENY -->|否| ALLOW{"在 alwaysAllow 规则中?"} + ALLOW -->|是| PASS["✅ 允许"] + ALLOW -->|否| TOOL_CHECK{"工具自身
checkPermissions()"} + TOOL_CHECK -->|拒绝| BLOCKED + TOOL_CHECK -->|允许| CLASSIFIER{"AI 分类器
(auto 模式)"} + CLASSIFIER -->|安全| PASS + CLASSIFIER -->|危险| DIALOG{"shouldAvoidPermissionPrompts?"} + DIALOG -->|是| BLOCKED + DIALOG -->|否| USER["🔔 提示用户确认"] + USER -->|允许| PASS + USER -->|拒绝| BLOCKED +``` + +权限规则支持 glob 模式匹配,例如 `Bash(git *)` 允许所有 `git` 开头的 bash 命令。`denialTracking.ts` 追踪连续拒绝次数,超过阈值后触发降级到手动确认模式。 + +--- + +## 七、多智能体架构 + +### 7.1 协调器模式 + +```mermaid +graph TB + subgraph Coordinator["协调器 (Coordinator)"] + C["协调器智能体
全局视角 + 任务分配"] + end + + subgraph Workers["工作智能体 (Workers)"] + W1["Worker 1
文件探索"] + W2["Worker 2
代码修改"] + W3["Worker 3
测试验证"] + end + + C -->|"AgentTool
生成"| W1 + C -->|"AgentTool
生成"| W2 + C -->|"SendMessageTool
追加指令"| W1 + W1 -->|"task-notification
XML 回报"| C + W2 -->|"task-notification
XML 回报"| C + C -->|"AgentTool
生成"| W3 + W3 -->|"task-notification
XML 回报"| C + C -->|"TaskStopTool
终止"| W1 +``` + +协调器系统提示词(300+ 行)定义了 **四阶段工作流**: + +1. **Research** — 探索代码库,理解上下文 +2. **Synthesis** — 综合发现,制定方案 +3. **Implementation** — 并行执行代码修改 +4. **Verification** — 验证结果,运行测试 + +关键原则写在 prompt 里而非代码里: +- *"Do not rubber-stamp weak work"*(不要草率通过低质量工作) +- *"You must understand findings before directing follow-up work"*(在指导后续工作前必须理解发现) + +### 7.2 子智能体启动流程 + +`runAgent.ts`(973 行)是子智能体的核心启动器: + +1. 生成唯一 `AgentId` +2. 创建独立的 `FileStateCache` +3. 通过 `createSubagentContext()` fork 父级的 `ToolUseContext` +4. 初始化智能体专属 MCP 服务器(来自 frontmatter) +5. 运行独立的 `query()` 流式循环 +6. 注册 Perfetto tracing(性能追踪) +7. 写入智能体元数据和 sidechain transcript + +### 7.3 任务类型 + +```mermaid +classDiagram + class TaskType { + <> + local_bash + local_agent + remote_agent + in_process_teammate + local_workflow + monitor_mcp + dream + } + + class TaskStatus { + <> + pending + running + completed + failed + killed + } + + class LocalAgentTask + class InProcessTeammateTask + class RemoteAgentTask + class LocalShellTask + class DreamTask + + TaskType <-- LocalAgentTask + TaskType <-- InProcessTeammateTask + TaskType <-- RemoteAgentTask + TaskType <-- LocalShellTask + TaskType <-- DreamTask +``` + +--- + +## 八、MCP(Model Context Protocol)集成 + +Claude Code 既是 MCP **客户端**(连接外部 MCP 服务器),也可以作为 MCP **服务器**运行。 + +### 8.1 支持的传输类型 + +| 传输方式 | 配置类型 | 说明 | +|----------|---------|------| +| `stdio` | `McpStdioServerConfig` | 标准进程通信 | +| `sse` | `McpSSEServerConfig` | Server-Sent Events | +| `sse-ide` | — | IDE 专用 SSE | +| `http` | `McpHTTPServerConfig` | HTTP 直连 | +| `ws` | `McpWebSocketServerConfig` | WebSocket | +| `sdk` | `McpSdkServerConfig` | SDK 内嵌 | + +### 8.2 MCP 连接状态机 + +```mermaid +stateDiagram-v2 + [*] --> Pending: 初始化 + Pending --> Connected: 连接成功 + Pending --> Failed: 连接失败 + Pending --> NeedsAuth: 需要认证 + NeedsAuth --> Connected: OAuth 完成 + Connected --> Failed: 断开连接 + Connected --> Disabled: 用户禁用 + Failed --> Pending: 重连 +``` + +`mcp/client.ts`(3,348 行)是最大的 MCP 相关文件,负责连接管理、工具发现、资源预取和认证流程(支持 OAuth 和 XAA 跨应用访问)。 + +--- + +## 九、记忆系统 + +```mermaid +graph LR + MEMORY_MD["MEMORY.md
记忆索引
(≤200 行 / 25KB)"] --> NOTE1["user_role.md"] + MEMORY_MD --> NOTE2["feedback_testing.md"] + MEMORY_MD --> NOTE3["project_auth.md"] + + SYSTEM_PROMPT["系统提示词"] --> MEMORY_MD + SYSTEM_PROMPT --> TYPES["记忆类型指令"] + SYSTEM_PROMPT --> RULES["存取规则"] + + NOTE1 --> SEMANTIC["语义搜索
findRelevantMemories()"] + NOTE2 --> SEMANTIC + NOTE3 --> SEMANTIC + SEMANTIC --> INJECT["注入上下文"] +``` + +记忆系统(`memdir/`,9 个文件)采用**文件驱动**的设计: + +- `MEMORY.md` 作为入口索引文件,限制 200 行 / 25KB,注入到系统提示词中 +- 每条记忆是独立的 Markdown 文件,带有 frontmatter(name、description、type) +- 支持语义搜索(`findRelevantMemories()`) +- 记忆老化/淘汰机制(`memoryAge.ts`) +- 团队共享记忆支持(`teamMemPaths.ts`,TEAMMEM 特性开关后) + +--- + +## 十、终端渲染引擎 + +Claude Code 使用**自研的 Ink 分支**(非 npm 上的 Ink 库),基于 React + Yoga Layout 实现终端 UI。 + +``` +ink/ +├── root.ts — render() / createRoot() 入口 +├── dom.ts — 虚拟 DOM 实现 +├── frame.ts — 渲染帧管理,防闪烁 +├── focus.ts — 键盘焦点管理 +├── components/ +│ ├── App.tsx — 根组件 +│ ├── Box.tsx — 布局容器 +│ ├── Text.tsx — 文本组件 +│ ├── ScrollBox.tsx — 滚动区域 +│ └── AlternateScreen.tsx — 全屏覆盖 +├── events/ — 自定义事件系统 +├── hooks/ — use-input, use-app, use-animation-frame 等 +├── termio/ — 原始终端 I/O +└── Ansi.tsx — ANSI 转义码渲染组件 +``` + +据泄漏分析文章指出,其终端渲染使用了 `Int32Array` 支持的 ASCII 字符池和位掩码编码的样式元数据,声称"在 token 流式传输期间将 `stringWidth` 调用减少约 50 倍"。 + +--- + +## 十一、系统提示词构建 + +系统提示词是分段动态组装的,带有缓存边界标记: + +```mermaid +graph TB + subgraph Static["静态段(全局可缓存 scope='global')"] + INTRO["getSimpleIntroSection()
智能体身份 + 安全指令"] + SYSTEM["getSimpleSystemSection()
工具使用 + 权限模式"] + TASKS_SEC["getSimpleDoingTasksSection()
软件工程行为规范"] + ACTIONS["getActionsSection()
操作可逆性策略"] + TOOL_GUIDE["getUsingYourToolsSection()
工具使用指南"] + end + + BOUNDARY["═══ SYSTEM_PROMPT_DYNAMIC_BOUNDARY ═══"] + + subgraph Dynamic["动态段(用户/会话级,不跨组织缓存)"] + HOOKS_SEC["getHooksSection()
用户钩子指令"] + UNDERCOVER["Undercover 指令
(ant-only)"] + MEMORY["loadMemoryPrompt()
记忆内容"] + LANG["语言偏好"] + CONTEXT["getUserContext()
Git 状态 / CLAUDE.md / 平台信息"] + MCP_INST["MCP 指令"] + end + + Static --> BOUNDARY + BOUNDARY --> Dynamic +``` + +这种设计让静态段可以跨会话缓存(通过 Anthropic API 的 `cache_control` 参数),而动态段每次重新构建。 + +--- + +## 十二、隐藏特性与彩蛋 + +### 12.1 反蒸馏机制(Anti-Distillation) + +```typescript +// services/api/claude.ts (301-313) +if ( + feature('ANTI_DISTILLATION_CC') + ? process.env.CLAUDE_CODE_ENTRYPOINT === 'cli' && + shouldIncludeFirstPartyOnlyBetas() && + getFeatureValue_CACHED_MAY_BE_STALE( + 'tengu_anti_distill_fake_tool_injection', false) + : false +) { + result.anti_distillation = ['fake_tools'] +} +``` + +当启用时,向 API 请求注入 `anti_distillation: ['fake_tools']`,服务端会在工具调用中混入虚假工具响应。目的:如果竞争对手录制 Claude Code 的 API 流量来训练模型,虚假工具数据会污染训练集。 + +**绕过分析**:MITM 代理可在请求到达 API 前剥离该字段;设置 `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` 环境变量可禁用;第三方 SDK 入口完全绕过。正如分析者所言:"真正的保护可能是法律而非技术"。 + +### 12.2 伪装模式(Undercover Mode) + +`utils/undercover.ts` — Anthropic 内部员工在外部开源仓库工作时自动启用: + +- 禁止提及内部代码名(Capybara、Tengu 等) +- 隐藏内部 Slack 频道和仓库名称 +- 删除所有 "Co-Authored-By" 标识 +- 不暴露未发布的模型版本号 + +**关键限制**:**没有强制关闭开关**。注释明确写道:*"There is NO force-OFF. This guards against model codename leaks."* 这是一扇单向门。 + +### 12.3 挫折感检测 + +```typescript +// utils/userPromptKeywords.ts +const negativePattern = + /\b(wtf|wth|ffs|omfg|shit(ty|tiest)?|dumbass|horrible|awful| + piss(ed|ing)? off|piece of (shit|crap|junk)|what the (fuck|hell)| + fucking? (broken|useless|terrible|awful|horrible)|fuck you| + screw (this|you)|so frustrating|this sucks|damn it)\b/ +``` + +仅在 Anthropic 内部版本中启用(外部构建通过死代码消除移除)。当检测到用户情绪消极时,弹出 transcript 分享提示,方便内部员工快速提交反馈。选用正则而非 LLM 的原因:比模型推理调用更快更便宜。 + +### 12.4 KAIROS — 自主守护智能体 + +**KAIROS**(古希腊语"恰当的时机")是一个被提及 150+ 次的特性开关,代表着一个全新的交互范式——**始终在线的后台智能体**。 + +核心能力: +- `/dream` 技能 — "夜间记忆蒸馏" +- `autoDream` 守护进程 — 用户空闲时自动进行记忆整合 +- GitHub webhook 订阅 — 监听仓库事件 +- Cron 定时任务 — 每 5 分钟计划刷新 +- 推送通知 — 主动通知用户 + +**autoDream 触发条件**: +1. 距离上次整合 ≥ 24 小时 +2. 至少 5 个新会话 +3. 进程锁(同一时间只有一个进程执行整合) + +### 12.5 Buddy 伴侣系统(愚人节彩蛋) + +``` +buddy/ +├── companion.ts — Mulberry32 PRNG 确定性生成 +├── types.ts — 物种、稀有度、属性定义 +├── CompanionSprite.tsx — 500ms 刷新的终端动画精灵 +├── sprites.ts — ASCII 艺术帧 +├── prompt.ts — 系统提示词注入 +└── useBuddyNotification.tsx — 预告逻辑 +``` + +一个 Tamagotchi 风格的虚拟宠物系统: + +- **18 种物种**:鸭子、鹅、blob、猫、龙、章鱼、猫头鹰、企鹅、海龟、蜗牛、幽灵、美西螈、水豚、仙人掌、机器人、兔子、蘑菇、胖墩。物种名用十六进制字符数组编码,避免触发内部代码名扫描器 +- **稀有度**:普通(60%)、非凡(25%)、稀有(10%)、史诗(4%)、传说(1%) +- **RPG 属性**:DEBUGGING、PATIENCE、CHAOS、WISDOM、SNARK +- **防篡改**:骨骼数据(物种、稀有度、闪光)从 `hash(userId)` 确定性生成,不存储在配置中,无法伪造传说级 +- **活跃窗口**:2026 年 4 月 1-7 日(跨时区滚动上线) + +--- + +## 十三、Bash 安全检查 + +`tools/BashTool/bashSecurity.ts` 实现了 **23 项编号安全检查**: + +| 检查项 | 防御内容 | +|--------|---------| +| 命令替换 | `$()`、`${}`、进程替换 `<()`、`>()` | +| Zsh 危险内置 | `zmodload`、`emulate`、`sysopen`、`ztcp`、`zsocket`、`zf_rm` 等 18 个 | +| Zsh 等号展开 | `=curl` 绕过 curl 权限检查 | +| Unicode 攻击 | 零宽空格注入、Unicode 空白字符 | +| IFS 注入 | 空字节 IFS 注入 | +| Shell 元字符 | 混淆标志、花括号展开、中间单词哈希 | +| 控制字符 | 不可见控制字符注入 | +| 注释/引号错位 | 注释与引号边界不对齐攻击 | +| PowerShell | PowerShell 语法检测 | +| HackerOne 发现 | 格式错误 token 绕过(安全审计中发现) | + +每次触发的检查都会记录 `tengu_bash_security_check_triggered` 事件(带数字 ID),用于安全监控和统计。 + +--- + +## 十四、Prompt 缓存经济学 + +`services/api/promptCacheBreakDetection.ts` 追踪 **12+ 个缓存破坏维度**: + +``` +系统提示词哈希 | 工具 Schema 哈希 | cache_control 哈希 +单工具 Schema 变更 | 模型切换 | 快速模式 +全局缓存策略 | Beta 头部 | effort 值 +Auto 模式状态 | 超限状态 | 微压缩状态 +``` + +当检测到缓存破坏(>5% 缓存读取 token 下降 且 >2,000 绝对 token 下降)时: +- 触发 `tengu_prompt_cache_break` 分析事件 +- 写入 diff 文件到 `~/.claude/tmp/cache-break-*.diff` +- 区分服务端破坏 vs TTL 过期 + +正如源码注释所言:*"在按 token 付费时,缓存失效不再是计算机科学笑话,而是会计问题。"* + +--- + +## 十五、自动压缩与 250K API 调用浪费 + +`services/compact/autoCompact.ts` 中有一段引人注目的注释: + +> 2026-03-10:BQ 分析显示 1,279 个会话在单次会话中有 50+ 连续自动压缩失败(最高达 3,272 次),全球每日浪费约 250,000 次 API 调用。 + +修复方案:**三行代码**。 + +```typescript +const MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3 +``` + +添加一个断路器,连续失败 3 次后停止重试。 + +自动压缩参数: +- 缓冲区:13,000 tokens(`AUTOCOMPACT_BUFFER_TOKENS`) +- 警告阈值:上下文窗口 - 20,000 tokens +- 摘要输出预留:20,000 tokens(基于 p99.99 实际摘要为 17,387 tokens) + +--- + +## 十六、IDE 桥接(Bridge) + +```mermaid +graph LR + subgraph IDE["IDE 端"] + VSCODE["VS Code 扩展"] + JETBRAINS["JetBrains 插件"] + end + + subgraph Bridge["桥接层 (27 个文件)"] + BRIDGE_MAIN["bridgeMain.ts
2,999 行
CCR WebSocket 服务器"] + REPL_BRIDGE["replBridge.ts
2,406 行
REPL 远程模式"] + end + + subgraph Cloud["claude.ai"] + CCR["Claude Code Remote"] + end + + subgraph Local["本地 CLI"] + CLAUDE["claude 进程"] + end + + VSCODE <-->|JWT 认证| BRIDGE_MAIN + JETBRAINS <-->|JWT 认证| BRIDGE_MAIN + BRIDGE_MAIN <-->|WebSocket| CCR + REPL_BRIDGE <-->|WebSocket| CCR + BRIDGE_MAIN --> CLAUDE + REPL_BRIDGE --> CLAUDE +``` + +桥接系统支持: +- WebSocket 双向通信 +- JWT 认证 + Token 刷新调度 +- 指数退避重连 +- 可信设备 Token 管理 +- 容量感知唤醒(`capacityWake.ts`) +- 消息流控门(`flushGate.ts`) + +--- + +## 十七、构建时特性开关系统 + +Claude Code 最精妙的设计之一是其构建时特性开关系统: + +```typescript +// 使用 bun:bundle 的 feature() 函数 +if (feature('KAIROS')) { + // 此代码在外部构建中被完整删除 + loadKairosModule() +} + +// 用户类型检查也会被常量折叠 +if ("external" === 'ant') { + // 外部构建:编译为 if (false) → 死代码消除 + loadInternalOnlyFeature() +} +``` + +**已知特性开关**(44 个,部分列表): + +| 开关名 | 功能 | +|--------|------| +| `KAIROS` / `PROACTIVE` | 自主守护智能体 | +| `ANTI_DISTILLATION_CC` | 反蒸馏保护 | +| `COORDINATOR_MODE` | 多智能体协调 | +| `BRIDGE_MODE` | IDE 桥接 | +| `DAEMON` | 后台守护进程 | +| `VOICE_MODE` | 语音输入 | +| `BUDDY` | 伴侣系统 | +| `HISTORY_SNIP` | 历史裁剪 | +| `WORKFLOW_SCRIPTS` | 工作流脚本 | +| `AGENT_TRIGGERS` | 智能体触发器 | +| `FORK_SUBAGENT` | 分叉子智能体 | +| `REACTIVE_COMPACT` | 响应式压缩 | +| `CONTEXT_COLLAPSE` | 上下文折叠 | +| `TRANSCRIPT_CLASSIFIER` | 转录分类器 | +| `NATIVE_CLIENT_ATTESTATION` | 原生客户端证明 | +| `TEMPLATES` | 模板系统 | +| `TORCH` / `ULTRAPLAN` / `UDS_INBOX` | 未知内部功能 | + +--- + +## 十八、语音输入 + +`hooks/useVoice.ts` 实现了**按住说话**的语音输入: + +- 使用 Anthropic 的 `voice_stream` STT 端点(Deepgram 后端) +- macOS 原生音频或 SoX 录制 +- WebSocket 连接到 `conversation_engine` 端点 +- 支持多语言(BCP-47 编码,从系统 locale 自动检测) +- "Keyterms" 注入提升识别准确度 +- 5 次快速按键激活阈值(防止正常打字误触发) +- 通过 `VOICE_MODE` 构建开关完整移除 + +--- + +## 十九、关键架构模式总结 + +### 19.1 流式优先(Streaming-First) + +从 `submitMessage()` 到 `query()` 到 `queryModelWithStreaming()`,整个链路都是 `AsyncGenerator`。工具执行期间通过 `onProgress` 回调发出进度消息。 + +### 19.2 依赖注入测试 + +`QueryDeps` 接口注入 `callModel`、`microcompact`、`autocompact`、`uuid`,避免测试中使用 `spyOn`。 + +### 19.3 上下文穿透 + +`ToolUseContext` 是贯穿整个工具执行链路的"胖上下文"对象。子智能体通过 `createSubagentContext()` 获得 fork 的副本。 + +### 19.4 双层特性门控 + +- **构建时**:`feature()` 从 `bun:bundle` 常量折叠,死代码消除 +- **运行时**:GrowthBook 远程开关(`tengu_*`),支持灰度发布和 A/B 测试 + +### 19.5 分叉子智能体 + +后台任务(autoDream、压缩、会话记忆、推测执行)都通过 `runForkedAgent()` 运行——隔离的子智能体,有自己的查询来源,防止递归并共享父级的缓存安全参数。 + +--- + +## 二十、代码质量观察 + +| 指标 | 数据 | +|------|------| +| 总代码量 | 512,664 行 TypeScript | +| 文件数 | 1,884 个 `.ts/.tsx` | +| 最大文件 | `cli/print.ts`(5,594 行,单函数 3,167 行,12 层嵌套) | +| 第二大文件 | `main.tsx`(4,683 行) | +| API 客户端 | `claude.ts`(3,419 行) | +| MCP 客户端 | `mcp/client.ts`(3,348 行) | +| 桥接主模块 | `bridgeMain.ts`(2,999 行) | + +一些值得注意的代码风格: +- 偏好单文件大函数而非过度抽象(`print.ts` 是极端案例) +- 大量使用 `feature()` 门控保持外部构建精简 +- 独创的 analytics 安全类型:`AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS`——防止开发者意外将文件路径或代码片段发送到分析系统 +- `tengu_` 前缀统一所有实验名和事件名(Tengu 是内部代号,讽刺的是在 Undercover Mode 的注释中被列为"不应暴露的代码名"示例) + +--- + +## 结语 + +Claude Code 的 512,664 行源码揭示了一个工程复杂度远超预期的系统。它不仅仅是一个"LLM 套壳"——从自研终端渲染引擎到 23 项 Bash 安全检查,从多智能体协调到 prompt 缓存经济学,每一个模块都体现了在真实生产环境中打磨 AI 编程工具的深度工程投入。 + +最具战略意义的发现不是源码本身(它可以被重构),而是那 44 个特性开关背后的产品路线图:KAIROS 自主守护智能体、语音输入、团队协作记忆……这些代表着 Anthropic 对 AI 编程工具未来形态的判断。而这种战略意外,无法被 DMCA 撤回。 diff --git a/articles/008/cover.html b/articles/008/cover.html new file mode 100644 index 0000000..1bf50bf --- /dev/null +++ b/articles/008/cover.html @@ -0,0 +1,491 @@ + + + + + + + + +
+ +
+
const query = async () => { + const stream = api.stream() + for await (const chunk of stream) { + if (chunk.type === 'tool_use') { + await executeTool(chunk) + } + yield chunk.delta + } +} +export class QueryEngine { + private sessions: Map<string> + async compact(history) { + if (tokens > MAX_CONTEXT) { + return summarize(history) + } + } +} +const PERMISSIONS = [ + 'FileRead', 'FileWrite', + 'Bash', 'Glob', 'Grep', +] +function checkSecurity(cmd) { + for (const rule of RULES) { + if (rule.match(cmd)) block() + } +}
+
interface Tool { + name: string + isConcurrencySafe: boolean + execute(input: unknown) +} +async function dispatch(calls) { + const reads = calls.filter(safe) + const writes = calls.filter(!safe) + await Promise.all(reads) + for (const w of writes) { + await w.execute() + } +} +// KAIROS daemon mode +class KairosDaemon { + private cron: CronScheduler + async autoDream() { + await consolidateMemory() + await mergeFindingss() + } + watch(repo: Repository) { + repo.on('pr', handle) + repo.on('issue', handle) + } +}
+
const FEATURE_FLAGS = { + KAIROS: false, + VOICE_MODE: false, + COORDINATOR: true, + BUDDY: true, + ANTI_DISTILL: true, + DAEMON: false, + BRIDGE: true, + TORCH: false, +} +// anti-distillation +if (feature('ANTI_DISTILL')) { + result.anti_distillation + = ['fake_tools'] +} +// undercover mode +export function isUndercover() { + return isExternalRepo() + && isAnthropicUser() +}
+
export async function main() { + const config = loadConfig() + const keys = await keychain() + + await Promise.all([ + growthbook.init(), + mcp.connect(servers), + registerTools(TOOLS), + ]) + + const prompt = buildSystem({ + identity: AGENT_IDENTITY, + tools: TOOL_SPECS, + memory: loadMemory(), + claudeMd: readClaudeMd(), + }) + + launchRepl(prompt, config) +}
+
// bashSecurity.ts +const CHECKS = 23 +function validateCommand(cmd) { + // Check 1: $(command) + // Check 2: process substitution + // Check 7: zmodload bypass + // Check 12: unicode zero-width + // Check 19: IFS null byte + // Check 23: HackerOne report + if (dangerous(cmd)) { + telemetry.track( + 'bash_security_triggered', + { check: checkId } + ) + return BLOCKED + } +} +// 512,664 lines total +// 1,884 .ts/.tsx files +// Runtime: Bun
+
class MemorySystem { + private index: MemoryIndex + + async recall(query: string) { + const matches = semantic( + this.memories, query + ) + return matches.slice(0, 5) + } + + async age() { + for (const m of this.memories) { + if (isStale(m)) { + await this.archive(m) + } + } + } +} +// buddy/species.ts +const SPECIES = [ + 'duck', 'dragon', 'octopus', + 'capybara', 'ghost', 'mushroom', +]
+
// coordinator prompt (300+ lines) +// Phase 1: Research +// Phase 2: Synthesis +// Phase 3: Implementation +// Phase 4: Verification +// +// "Do not rubber-stamp +// weak work" +// +// prompt cache strategy: +// static segments: cached +// dynamic segments: rebuilt +// +// cache_control: { +// type: 'ephemeral' +// } +// +// MAX_AUTOCOMPACT = 3 +// saved 250k API calls/day
+
+ +
+
+
+ +
+
+
+
+ + +
+
+
source leaked
+
+ 51万行源码曝光
+ 我扒完了Claude Code
的全部家底 +
+
+ 512,664行 TypeScript · 1,884 文件 · 44 特性开关 +
+
+ +
+
+
+
+
+
+
+
+ // npm source map leak
+ $ npm pack @anthropic-ai/claude-code
+ claude-code-2.1.88.tgz
+ index.js.map 59.8MB

+ // found R2 bucket URL...
+ ⚠ EXPOSED:
+   files: 1,884
+   lines: 512,664
+   flags: 44
+   tools: 40+

+ █ KAIROS █ ANTI_DISTILL
+ █ BUDDY  █ UNDERCOVER +
+
+
+
+ +
+
+ + diff --git a/articles/008/cover.png b/articles/008/cover.png new file mode 100644 index 0000000..903cd72 Binary files /dev/null and b/articles/008/cover.png differ diff --git a/articles/008/diagrams/01-architecture.mmd b/articles/008/diagrams/01-architecture.mmd new file mode 100644 index 0000000..3442717 --- /dev/null +++ b/articles/008/diagrams/01-architecture.mmd @@ -0,0 +1,37 @@ +graph TB + subgraph Layer1["第一层:入口"] + CLI["cli.tsx — CLI 入口 (302行)"] + MCP_E["mcp.ts — MCP Server"] + SDK_E["agentSdkTypes.ts — SDK"] + end + + subgraph Layer2["第二层:核心引擎"] + MAIN["main.tsx (4,683行)
REPL 编排器"] + QE["QueryEngine.ts (1,295行)
会话管理"] + QUERY["query.ts (1,729行)
流式查询循环"] + end + + subgraph Layer3["第三层:工具执行"] + TOOLS["40+ 工具
文件/Shell/网络/智能体"] + ORCH["并发调度器
读写分离"] + PERM["权限系统
24 个文件"] + end + + subgraph Layer4["第四层:智能体协调"] + COORD["协调器模式"] + AGENT["子智能体启动器"] + TASK["7 种任务类型"] + end + + subgraph Layer5["第五层:基础设施"] + API_C["Anthropic API 客户端"] + MCP_C["MCP 客户端 (3,348行)"] + BRIDGE["IDE 桥接 (27个文件)"] + MEM["记忆系统"] + INK["终端渲染引擎"] + end + + Layer1 --> Layer2 + Layer2 --> Layer3 + Layer3 --> Layer4 + Layer4 --> Layer5 diff --git a/articles/008/diagrams/01-architecture.png b/articles/008/diagrams/01-architecture.png new file mode 100644 index 0000000..a84bbb7 Binary files /dev/null and b/articles/008/diagrams/01-architecture.png differ diff --git a/articles/008/diagrams/02-startup.mmd b/articles/008/diagrams/02-startup.mmd new file mode 100644 index 0000000..98c227d --- /dev/null +++ b/articles/008/diagrams/02-startup.mmd @@ -0,0 +1,22 @@ +sequenceDiagram + participant U as 你的终端 + participant CLI as cli.tsx (302行) + participant Main as main.tsx (4,683行) + participant GB as GrowthBook 特性开关 + participant MCP as MCP 服务器 + participant REPL as REPL 交互循环 + + U->>CLI: $ claude + CLI->>CLI: 快速路径检查
(--version? --help?) + CLI->>Main: 动态 import() + + par 并行初始化(不阻塞) + Main->>GB: 加载 44 个特性开关 + Main->>Main: 读取配置 / 密钥链 + Main->>MCP: 连接所有 MCP 服务器 + Main->>Main: 注册 40+ 工具 + end + + Main->>Main: 组装系统提示词 + Main->>REPL: launchRepl() + REPL->>U: 光标闪烁,等你说话 diff --git a/articles/008/diagrams/02-startup.png b/articles/008/diagrams/02-startup.png new file mode 100644 index 0000000..e76c687 Binary files /dev/null and b/articles/008/diagrams/02-startup.png differ diff --git a/articles/008/diagrams/03-query-loop.mmd b/articles/008/diagrams/03-query-loop.mmd new file mode 100644 index 0000000..25badba --- /dev/null +++ b/articles/008/diagrams/03-query-loop.mmd @@ -0,0 +1,19 @@ +flowchart TD + START["你的消息"] --> BUILD["组装查询配置"] + BUILD --> CALL["调用 Anthropic API
(SSE 流式传输)"] + CALL --> STREAM["实时接收 token"] + STREAM --> CHECK{模型要调用工具?} + + CHECK -->|是| TOOLS["执行工具
(读文件/改代码/跑命令...)"] + TOOLS --> BUDGET["结果预算控制
(太大就存磁盘)"] + BUDGET --> COMPACT{"快爆上下文窗口了?"} + COMPACT -->|是| COMPRESS["自动压缩对话历史"] + COMPRESS --> CALL + COMPACT -->|否| CALL + + CHECK -->|否| DONE{"输出被截断?"} + DONE -->|是,≤3次| CALL + DONE -->|否| END["完成"] + + style TOOLS fill:#e1f5fe + style COMPRESS fill:#fff3e0 diff --git a/articles/008/diagrams/03-query-loop.png b/articles/008/diagrams/03-query-loop.png new file mode 100644 index 0000000..6a48903 Binary files /dev/null and b/articles/008/diagrams/03-query-loop.png differ diff --git a/articles/008/diagrams/04-rw-dispatch.mmd b/articles/008/diagrams/04-rw-dispatch.mmd new file mode 100644 index 0000000..0215842 --- /dev/null +++ b/articles/008/diagrams/04-rw-dispatch.mmd @@ -0,0 +1,8 @@ +flowchart LR + INPUT["模型一次返回 5 个工具调用"] --> SPLIT{"只读?"} + + SPLIT -->|"Glob ✓
Grep ✓
FileRead ✓"| PAR["并发执行
(最多 10 个)"] + SPLIT -->|"FileEdit ✗
Bash ✗"| SEQ["串行执行
(一个一个来)"] + + PAR --> MERGE["合并结果,返回模型"] + SEQ --> MERGE diff --git a/articles/008/diagrams/04-rw-dispatch.png b/articles/008/diagrams/04-rw-dispatch.png new file mode 100644 index 0000000..225b318 Binary files /dev/null and b/articles/008/diagrams/04-rw-dispatch.png differ diff --git a/articles/008/diagrams/05-permission.mmd b/articles/008/diagrams/05-permission.mmd new file mode 100644 index 0000000..5d2df99 --- /dev/null +++ b/articles/008/diagrams/05-permission.mmd @@ -0,0 +1,14 @@ +flowchart TD + REQ["工具调用请求"] --> DENY{"在黑名单?"} + DENY -->|是| NO["拒绝"] + DENY -->|否| ALLOW{"在白名单?"} + ALLOW -->|是| YES["放行"] + ALLOW -->|否| TOOL{"工具自检
checkPermissions()"} + TOOL -->|危险| CLASS{"AI 分类器
(仅 auto 模式)"} + CLASS -->|安全| YES + CLASS -->|危险| ASK{"能弹窗吗?"} + ASK -->|能| USER["问用户"] + ASK -->|不能| NO + + style NO fill:#ffcdd2 + style YES fill:#c8e6c9 diff --git a/articles/008/diagrams/05-permission.png b/articles/008/diagrams/05-permission.png new file mode 100644 index 0000000..b90d088 Binary files /dev/null and b/articles/008/diagrams/05-permission.png differ diff --git a/articles/008/diagrams/06-multi-agent.mmd b/articles/008/diagrams/06-multi-agent.mmd new file mode 100644 index 0000000..640b718 --- /dev/null +++ b/articles/008/diagrams/06-multi-agent.mmd @@ -0,0 +1,18 @@ +graph TB + subgraph Boss["协调器"] + C["全局视角
任务分配
质量把关"] + end + + subgraph Team["工作团队"] + W1["Worker 1
探索代码结构"] + W2["Worker 2
修改文件"] + W3["Worker 3
运行测试"] + end + + C -->|"生成"| W1 + C -->|"生成"| W2 + C -->|"追加指令"| W1 + W1 -.->|"回报结果"| C + W2 -.->|"回报结果"| C + C -->|"验收后生成"| W3 + W3 -.->|"回报结果"| C diff --git a/articles/008/diagrams/06-multi-agent.png b/articles/008/diagrams/06-multi-agent.png new file mode 100644 index 0000000..326164c Binary files /dev/null and b/articles/008/diagrams/06-multi-agent.png differ diff --git a/articles/008/diagrams/07-memory.mmd b/articles/008/diagrams/07-memory.mmd new file mode 100644 index 0000000..84a57f5 --- /dev/null +++ b/articles/008/diagrams/07-memory.mmd @@ -0,0 +1,10 @@ +graph LR + INDEX["MEMORY.md
记忆索引
(≤200行)"] --> M1["user_role.md
用户信息"] + INDEX --> M2["feedback_testing.md
纠正记录"] + INDEX --> M3["project_context.md
项目背景"] + + PROMPT["系统提示词"] -->|注入| INDEX + M1 --> SEARCH["语义搜索"] + M2 --> SEARCH + M3 --> SEARCH + SEARCH --> INJECT["注入当前对话"] diff --git a/articles/008/diagrams/07-memory.png b/articles/008/diagrams/07-memory.png new file mode 100644 index 0000000..1010a86 Binary files /dev/null and b/articles/008/diagrams/07-memory.png differ diff --git a/articles/008/diagrams/08-prompt-cache.mmd b/articles/008/diagrams/08-prompt-cache.mmd new file mode 100644 index 0000000..7bb0853 --- /dev/null +++ b/articles/008/diagrams/08-prompt-cache.mmd @@ -0,0 +1,18 @@ +graph TB + subgraph Cache["可缓存(跨会话复用)"] + A["智能体身份 + 安全指令"] + B["工具使用规范"] + C["软件工程行为准则"] + D["操作可逆性策略"] + end + + WALL["══ CACHE BOUNDARY ══"] + + subgraph Fresh["每次重建"] + E["用户钩子"] + F["记忆内容"] + G["Git 状态 / CLAUDE.md"] + H["MCP 指令"] + end + + Cache --> WALL --> Fresh diff --git a/articles/008/diagrams/08-prompt-cache.png b/articles/008/diagrams/08-prompt-cache.png new file mode 100644 index 0000000..fddd066 Binary files /dev/null and b/articles/008/diagrams/08-prompt-cache.png differ