docs(article): 添加 Claude Code 源码分析文章及相关架构图

- 新增 008 号文章《51 万行源码意外曝光!我扒完了 Claude Code 的全部家底》
- 添加 8 个 Mermaid 架构图文件,涵盖整体架构、启动流程、查询循环等
- 新增项目配置文件 CLAUDE.md,定义自媒体写作规范
- 创建详细的架构分析文档 claude-arch-by-claude.md
- 包含权限系统、工具调度、多智能体等核心技术解析
- 记录反蒸馏机制、KAIROS 守护进程等隐藏功能发现
- 提供完整的工具清单及安全防护措施说明
This commit is contained in:
邓文兵 2026-04-01 10:38:57 +08:00
parent 450056ee4a
commit 0686f1969c
21 changed files with 1839 additions and 0 deletions

View File

@ -17,4 +17,5 @@
- 七牛 CDN 域名:`https://cdn.union.jxyunge.com/self-media/` - 七牛 CDN 域名:`https://cdn.union.jxyunge.com/self-media/`
- 图片存放路径规则:`{编号}/{文件名}`,如 `005/cover.jpg`、`005/rubin-gpu.jpg` - 图片存放路径规则:`{编号}/{文件名}`,如 `005/cover.jpg`、`005/rubin-gpu.jpg`
- 禁止在正式文章中直接引用第三方图片链接(外链不稳定,可能失效) - 禁止在正式文章中直接引用第三方图片链接(外链不稳定,可能失效)
- 写文章时不能使用占位符图片链接,所有图片必须先实际生成/下载到本地,再通过 `/upload-qiniu` 上传到七牛,最后用真实的七牛 CDN 链接替换到文章中
- 使用 `/upload-qiniu` 工具上传图片到七牛 - 使用 `/upload-qiniu` 工具上传图片到七牛

View File

@ -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 上公开。
<!-- TODO: Chaofan Shou 推特截图 -->
几小时内,**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-10BQ 分析显示 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 个 crate31 个 `.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 CLIOpenAI 开源了 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)

View File

@ -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 编程智能体"的内部实现。
---
## 一、技术栈总览
| 维度 | 技术选型 |
|------|---------|
| 语言 | TypeScript1,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<br/>CLI 入口"]
MCP_ENTRY["mcp.ts<br/>MCP Server 入口"]
SDK["agentSdkTypes.ts<br/>SDK 入口"]
end
subgraph Core["核心引擎"]
MAIN["main.tsx<br/>4,683 行<br/>REPL 编排器"]
QE["QueryEngine.ts<br/>1,295 行<br/>会话管理器"]
QUERY["query.ts<br/>1,729 行<br/>流式查询循环"]
API["claude.ts<br/>3,419 行<br/>Anthropic API 客户端"]
end
subgraph Tools["工具系统"]
TOOL_DEF["Tool.ts<br/>792 行<br/>工具接口定义"]
TOOL_REG["tools.ts<br/>389 行<br/>工具注册表"]
TOOL_ORCH["toolOrchestration.ts<br/>并发调度"]
TOOL_EXEC["toolExecution.ts<br/>1,745 行<br/>执行引擎"]
end
subgraph Agent["多智能体"]
COORD["coordinatorMode.ts<br/>协调器"]
AGENT_RUN["runAgent.ts<br/>973 行<br/>子智能体启动器"]
TASKS["tasks/<br/>任务状态机"]
end
subgraph Infra["基础设施"]
PERM["permissions/<br/>24 个文件<br/>权限系统"]
MCP_CLIENT["mcp/client.ts<br/>3,348 行<br/>MCP 客户端"]
BRIDGE["bridge/<br/>27 个文件<br/>IDE 桥接"]
MEMDIR["memdir/<br/>9 个文件<br/>记忆系统"]
INK["ink/<br/>终端渲染引擎"]
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: 快速路径检查<br/>(--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<string> // 每轮发现的技能
└── loadedNestedMemoryPaths: Set<string> // 已加载的 CLAUDE.md 路径
```
核心方法 `submitMessage()` 是一个 `AsyncGenerator<SDKMessage>`,每次调用经历:
1. 构建系统提示词(`fetchSystemPromptParts()`
2. 处理斜杠命令(`processUserInput()`
3. 持久化用户消息到 transcript
4. 进入流式查询循环(`query()`yield 出 `SDKMessage`
5. 处理上下文压缩、权限、最大轮次限制
### 4.2 query.ts — 流式查询循环
```mermaid
flowchart TD
START["用户消息"] --> BUILD["构建查询配置"]
BUILD --> CALL["queryModelWithStreaming()<br/>调用 Anthropic API"]
CALL --> STREAM["流式接收响应"]
STREAM --> CHECK{是否有工具调用?}
CHECK -->|有| RUN_TOOLS["runTools()<br/>执行工具"]
RUN_TOOLS --> BUDGET["applyToolResultBudget()<br/>结果预算控制"]
BUDGET --> HOOKS["executePostSamplingHooks()"]
HOOKS --> COMPACT{"需要压缩?"}
COMPACT -->|是| AUTO_COMPACT["autoCompactIfNeeded()"]
AUTO_COMPACT --> CALL
COMPACT -->|否| CALL
CHECK -->|无| RECOVERY{max_output_tokens<br/>恢复?}
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<Input, Output, P>` 是一个功能丰富的接口,定义了工具的完整生命周期:
```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{"工具自身<br/>checkPermissions()"}
TOOL_CHECK -->|拒绝| BLOCKED
TOOL_CHECK -->|允许| CLASSIFIER{"AI 分类器<br/>(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["协调器智能体<br/>全局视角 + 任务分配"]
end
subgraph Workers["工作智能体 (Workers)"]
W1["Worker 1<br/>文件探索"]
W2["Worker 2<br/>代码修改"]
W3["Worker 3<br/>测试验证"]
end
C -->|"AgentTool<br/>生成"| W1
C -->|"AgentTool<br/>生成"| W2
C -->|"SendMessageTool<br/>追加指令"| W1
W1 -->|"task-notification<br/>XML 回报"| C
W2 -->|"task-notification<br/>XML 回报"| C
C -->|"AgentTool<br/>生成"| W3
W3 -->|"task-notification<br/>XML 回报"| C
C -->|"TaskStopTool<br/>终止"| 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 {
<<enumeration>>
local_bash
local_agent
remote_agent
in_process_teammate
local_workflow
monitor_mcp
dream
}
class TaskStatus {
<<enumeration>>
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
```
---
## 八、MCPModel 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<br/>记忆索引<br/>(≤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["语义搜索<br/>findRelevantMemories()"]
NOTE2 --> SEMANTIC
NOTE3 --> SEMANTIC
SEMANTIC --> INJECT["注入上下文"]
```
记忆系统(`memdir/`9 个文件)采用**文件驱动**的设计:
- `MEMORY.md` 作为入口索引文件,限制 200 行 / 25KB注入到系统提示词中
- 每条记忆是独立的 Markdown 文件,带有 frontmattername、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()<br/>智能体身份 + 安全指令"]
SYSTEM["getSimpleSystemSection()<br/>工具使用 + 权限模式"]
TASKS_SEC["getSimpleDoingTasksSection()<br/>软件工程行为规范"]
ACTIONS["getActionsSection()<br/>操作可逆性策略"]
TOOL_GUIDE["getUsingYourToolsSection()<br/>工具使用指南"]
end
BOUNDARY["═══ SYSTEM_PROMPT_DYNAMIC_BOUNDARY ═══"]
subgraph Dynamic["动态段(用户/会话级,不跨组织缓存)"]
HOOKS_SEC["getHooksSection()<br/>用户钩子指令"]
UNDERCOVER["Undercover 指令<br/>(ant-only)"]
MEMORY["loadMemoryPrompt()<br/>记忆内容"]
LANG["语言偏好"]
CONTEXT["getUserContext()<br/>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-10BQ 分析显示 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<br/>2,999 行<br/>CCR WebSocket 服务器"]
REPL_BRIDGE["replBridge.ts<br/>2,406 行<br/>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<SDKMessage>`。工具执行期间通过 `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 撤回。

491
articles/008/cover.html Normal file
View File

@ -0,0 +1,491 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Noto+Sans+SC:wght@900&display=swap');
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 900px;
height: 383px;
overflow: hidden;
background: #0a0a0f;
font-family: 'Noto Sans SC', sans-serif;
}
.canvas {
position: relative;
width: 900px;
height: 383px;
overflow: hidden;
background:
radial-gradient(ellipse 80% 60% at 75% 50%, rgba(220, 80, 40, 0.12) 0%, transparent 70%),
radial-gradient(ellipse 50% 80% at 20% 80%, rgba(40, 80, 220, 0.08) 0%, transparent 60%),
linear-gradient(160deg, #0a0a12 0%, #0d0d18 40%, #0a0f1a 100%);
}
/* Scrolling code background */
.code-rain {
position: absolute;
inset: 0;
opacity: 0.12;
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
line-height: 1.6;
color: #7faaff;
overflow: hidden;
pointer-events: none;
}
.code-col {
position: absolute;
top: -20px;
white-space: pre;
animation: codeScroll 20s linear infinite;
}
@keyframes codeScroll {
from { transform: translateY(-50%); }
to { transform: translateY(0); }
}
.code-col:nth-child(1) { left: 2%; animation-duration: 18s; color: #5a7fbb; }
.code-col:nth-child(2) { left: 14%; animation-duration: 22s; animation-delay: -3s; color: #6b8fcc; }
.code-col:nth-child(3) { left: 26%; animation-duration: 16s; animation-delay: -7s; }
.code-col:nth-child(4) { left: 54%; animation-duration: 25s; animation-delay: -2s; color: #5a7fbb; }
.code-col:nth-child(5) { left: 66%; animation-duration: 19s; animation-delay: -5s; }
.code-col:nth-child(6) { left: 78%; animation-duration: 21s; animation-delay: -9s; color: #6b8fcc; }
.code-col:nth-child(7) { left: 88%; animation-duration: 17s; animation-delay: -4s; }
/* Glitch scan line */
.scanline {
position: absolute;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, rgba(220, 80, 40, 0.4), rgba(255, 120, 60, 0.6), rgba(220, 80, 40, 0.4), transparent);
animation: scan 3s ease-in-out infinite;
z-index: 2;
box-shadow: 0 0 20px rgba(220, 80, 40, 0.3);
}
@keyframes scan {
0%, 100% { top: -2px; opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { top: 383px; opacity: 0; }
}
/* Grid overlay */
.grid-overlay {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(100, 150, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(100, 150, 255, 0.03) 1px, transparent 1px);
background-size: 40px 40px;
z-index: 1;
}
/* Main content */
.content {
position: relative;
z-index: 10;
width: 100%;
height: 100%;
display: flex;
padding: 36px 48px;
gap: 20px;
}
.left {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
gap: 14px;
}
/* Leak badge */
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
background: rgba(220, 50, 30, 0.15);
border: 1px solid rgba(220, 50, 30, 0.5);
color: #ff6b4a;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
font-weight: 700;
padding: 4px 12px;
border-radius: 4px;
letter-spacing: 2px;
text-transform: uppercase;
width: fit-content;
animation: badgePulse 2s ease-in-out infinite;
}
.badge::before {
content: '';
width: 6px;
height: 6px;
background: #ff4030;
border-radius: 50%;
animation: dot 1s ease-in-out infinite;
}
@keyframes dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
@keyframes badgePulse {
0%, 100% { box-shadow: 0 0 10px rgba(220, 50, 30, 0.1); }
50% { box-shadow: 0 0 20px rgba(220, 50, 30, 0.25); }
}
/* Title */
.title {
font-size: 46px;
font-weight: 900;
line-height: 1.15;
letter-spacing: -1px;
color: #f0f0f5;
text-shadow: 0 2px 30px rgba(0,0,0,0.5);
}
.title .num {
background: linear-gradient(135deg, #ff6b3d, #ff4019);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-size: 52px;
}
.title .leak {
position: relative;
color: #ff6b4a;
-webkit-text-fill-color: #ff6b4a;
}
.subtitle {
font-size: 17px;
color: rgba(180, 195, 230, 0.7);
font-weight: 400;
letter-spacing: 0.5px;
line-height: 1.5;
}
.subtitle strong {
color: rgba(220, 230, 255, 0.9);
font-weight: 700;
}
/* Right side - terminal card */
.right {
width: 280px;
display: flex;
align-items: center;
justify-content: center;
}
.terminal {
width: 100%;
background: rgba(12, 14, 24, 0.85);
border: 1px solid rgba(100, 150, 255, 0.12);
border-radius: 10px;
overflow: hidden;
box-shadow:
0 4px 40px rgba(0, 0, 0, 0.5),
0 0 60px rgba(220, 80, 40, 0.06),
inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.terminal-bar {
height: 28px;
background: rgba(20, 22, 35, 0.9);
display: flex;
align-items: center;
padding: 0 10px;
gap: 6px;
border-bottom: 1px solid rgba(100, 150, 255, 0.06);
}
.terminal-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.terminal-dot:nth-child(1) { background: #ff5f57; }
.terminal-dot:nth-child(2) { background: #ffbd2e; }
.terminal-dot:nth-child(3) { background: #28c840; }
.terminal-body {
padding: 14px;
font-family: 'JetBrains Mono', monospace;
font-size: 10.5px;
line-height: 1.7;
color: #8899bb;
}
.terminal-body .cmd { color: #28c840; }
.terminal-body .path { color: #ffbd2e; }
.terminal-body .err { color: #ff5f57; }
.terminal-body .str { color: #7faaff; }
.terminal-body .comment { color: #4a5568; }
.terminal-body .highlight { color: #ff6b4a; font-weight: 700; }
.terminal-body .white { color: #c8d4e8; }
/* Bottom bar */
.bottom-bar {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg,
transparent,
#ff4019 20%,
#ff6b3d 50%,
#ff4019 80%,
transparent
);
z-index: 10;
opacity: 0.7;
}
/* Corner accents */
.corner {
position: absolute;
width: 20px;
height: 20px;
z-index: 10;
opacity: 0.3;
}
.corner--tl { top: 12px; left: 12px; border-top: 2px solid #ff6b4a; border-left: 2px solid #ff6b4a; }
.corner--tr { top: 12px; right: 12px; border-top: 2px solid #ff6b4a; border-right: 2px solid #ff6b4a; }
.corner--bl { bottom: 12px; left: 12px; border-bottom: 2px solid #ff6b4a; border-left: 2px solid #ff6b4a; }
.corner--br { bottom: 12px; right: 12px; border-bottom: 2px solid #ff6b4a; border-right: 2px solid #ff6b4a; }
/* Noise texture */
.noise {
position: absolute;
inset: 0;
z-index: 5;
opacity: 0.035;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
pointer-events: none;
}
</style>
</head>
<body>
<div class="canvas">
<!-- Code rain background -->
<div class="code-rain">
<div class="code-col">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&lt;string&gt;
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()
}
}</div>
<div class="code-col">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)
}
}</div>
<div class="code-col">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()
}</div>
<div class="code-col">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)
}</div>
<div class="code-col">// 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</div>
<div class="code-col">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',
]</div>
<div class="code-col">// 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</div>
</div>
<div class="scanline"></div>
<div class="grid-overlay"></div>
<div class="noise"></div>
<div class="corner corner--tl"></div>
<div class="corner corner--tr"></div>
<div class="corner corner--bl"></div>
<div class="corner corner--br"></div>
<!-- Main content -->
<div class="content">
<div class="left">
<div class="badge">source leaked</div>
<div class="title">
<span class="num">51万行</span>源码<span class="leak">曝光</span><br>
我扒完了Claude Code<br>的全部家底
</div>
<div class="subtitle">
<strong>512,664行</strong> TypeScript · <strong>1,884</strong> 文件 · <strong>44</strong> 特性开关
</div>
</div>
<div class="right">
<div class="terminal">
<div class="terminal-bar">
<div class="terminal-dot"></div>
<div class="terminal-dot"></div>
<div class="terminal-dot"></div>
</div>
<div class="terminal-body">
<span class="comment">// npm source map leak</span><br>
<span class="cmd">$</span> <span class="white">npm pack @anthropic-ai/claude-code</span><br>
<span class="path"></span> <span class="str">claude-code-2.1.88.tgz</span><br>
<span class="path"></span> <span class="str">index.js.map</span> <span class="highlight">59.8MB</span><br><br>
<span class="comment">// found R2 bucket URL...</span><br>
<span class="err">⚠ EXPOSED:</span><br>
<span class="white">&nbsp;&nbsp;files: </span><span class="highlight">1,884</span><br>
<span class="white">&nbsp;&nbsp;lines: </span><span class="highlight">512,664</span><br>
<span class="white">&nbsp;&nbsp;flags: </span><span class="highlight">44</span><br>
<span class="white">&nbsp;&nbsp;tools: </span><span class="highlight">40+</span><br><br>
<span class="err">█ KAIROS █ ANTI_DISTILL</span><br>
<span class="err">█ BUDDY &nbsp;█ UNDERCOVER</span>
</div>
</div>
</div>
</div>
<div class="bottom-bar"></div>
</div>
</body>
</html>

BIN
articles/008/cover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

View File

@ -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行)<br/>REPL 编排器"]
QE["QueryEngine.ts (1,295行)<br/>会话管理"]
QUERY["query.ts (1,729行)<br/>流式查询循环"]
end
subgraph Layer3["第三层:工具执行"]
TOOLS["40+ 工具<br/>文件/Shell/网络/智能体"]
ORCH["并发调度器<br/>读写分离"]
PERM["权限系统<br/>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

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

View File

@ -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: 快速路径检查<br/>(--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: 光标闪烁,等你说话

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

View File

@ -0,0 +1,19 @@
flowchart TD
START["你的消息"] --> BUILD["组装查询配置"]
BUILD --> CALL["调用 Anthropic API<br/>(SSE 流式传输)"]
CALL --> STREAM["实时接收 token"]
STREAM --> CHECK{模型要调用工具?}
CHECK -->|是| TOOLS["执行工具<br/>(读文件/改代码/跑命令...)"]
TOOLS --> BUDGET["结果预算控制<br/>(太大就存磁盘)"]
BUDGET --> COMPACT{"快爆上下文窗口了?"}
COMPACT -->|是| COMPRESS["自动压缩对话历史"]
COMPRESS --> CALL
COMPACT -->|否| CALL
CHECK -->|否| DONE{"输出被截断?"}
DONE -->|是,≤3次| CALL
DONE -->|否| END["完成"]
style TOOLS fill:#e1f5fe
style COMPRESS fill:#fff3e0

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

View File

@ -0,0 +1,8 @@
flowchart LR
INPUT["模型一次返回 5 个工具调用"] --> SPLIT{"只读?"}
SPLIT -->|"Glob ✓<br/>Grep ✓<br/>FileRead ✓"| PAR["并发执行<br/>(最多 10 个)"]
SPLIT -->|"FileEdit ✗<br/>Bash ✗"| SEQ["串行执行<br/>(一个一个来)"]
PAR --> MERGE["合并结果,返回模型"]
SEQ --> MERGE

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -0,0 +1,14 @@
flowchart TD
REQ["工具调用请求"] --> DENY{"在黑名单?"}
DENY -->|是| NO["拒绝"]
DENY -->|否| ALLOW{"在白名单?"}
ALLOW -->|是| YES["放行"]
ALLOW -->|否| TOOL{"工具自检<br/>checkPermissions()"}
TOOL -->|危险| CLASS{"AI 分类器<br/>(仅 auto 模式)"}
CLASS -->|安全| YES
CLASS -->|危险| ASK{"能弹窗吗?"}
ASK -->|能| USER["问用户"]
ASK -->|不能| NO
style NO fill:#ffcdd2
style YES fill:#c8e6c9

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

View File

@ -0,0 +1,18 @@
graph TB
subgraph Boss["协调器"]
C["全局视角<br/>任务分配<br/>质量把关"]
end
subgraph Team["工作团队"]
W1["Worker 1<br/>探索代码结构"]
W2["Worker 2<br/>修改文件"]
W3["Worker 3<br/>运行测试"]
end
C -->|"生成"| W1
C -->|"生成"| W2
C -->|"追加指令"| W1
W1 -.->|"回报结果"| C
W2 -.->|"回报结果"| C
C -->|"验收后生成"| W3
W3 -.->|"回报结果"| C

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@ -0,0 +1,10 @@
graph LR
INDEX["MEMORY.md<br/>记忆索引<br/>(≤200行)"] --> M1["user_role.md<br/>用户信息"]
INDEX --> M2["feedback_testing.md<br/>纠正记录"]
INDEX --> M3["project_context.md<br/>项目背景"]
PROMPT["系统提示词"] -->|注入| INDEX
M1 --> SEARCH["语义搜索"]
M2 --> SEARCH
M3 --> SEARCH
SEARCH --> INJECT["注入当前对话"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB