Claude Code 源码泄漏 — 核心技术要点
📅 整理日期:2026-04-04 📥 来源:5 篇经抽查验证的高质量分析文章(详见末尾来源表) 📌 定位:按主题归类的技术事实提取,非二次分析
一、上下文注入架构
1.1 System Prompt 22 层结构
Claude Code 的 system prompt 由 22 个模块拼接(constants/prompts.ts:444-577),分三层缓存策略:
静态层(全局可缓存,跨用户复用)cacheScope: 'global'
1. Attribution Header(指纹校验)
2. CLI 前缀标识
3. 身份介绍
4. 系统规则(prompt injection 警告等)
5. 编码任务指南
6. 操作谨慎性指南
7. 工具使用指南
8. 语气风格
9. 输出效率
─── SYSTEM_PROMPT_DYNAMIC_BOUNDARY ───
动态层(会话级缓存)cacheScope: 'org'
10. 会话指导
11. ★ Memory 内容(loadMemoryPrompt)
12. 环境信息(平台、shell、模型名、Git 状态)
13. 语言偏好
14. 输出样式
易变层(每轮重算)DANGEROUS_uncached
15. MCP 服务器指令
16. 暂存板指令
17. 函数结果清除提醒
18. 工具结果摘要
条件注入
19-22. token 预算 / Advisor 指令 / 系统上下文
─── User Message 层(独立于 system prompt)───
第一条 user message: ★ CLAUDE.md 内容
第二条: 用户的第一句话
后续: 对话历史
关键结论:Memory 在 system prompt 第 11 位(高权重),CLAUDE.md 在 user message 层(低权重)。
1.2 缓存经济学
| 层 | 缓存范围 | 成本影响 |
|---|---|---|
| 静态层(1-9) | global — 跨用户复用 | 几乎零成本(cache hit) |
| 动态层(10-14) | org — 账户内复用 | 首次创建缓存,后续 hit |
| 易变层(15-18) | 不缓存,每轮重算 | 每轮都付费 |
| CLAUDE.md | user message 层,独立缓存 | 内容不变时缓存命中 |
- 修改 CLAUDE.md 不会导致 system prompt 缓存失效(不同层)
/compact和/clear清除所有动态层缓存,Memory 重新加载- MCP 配置变化免费(本来就在易变层)
二、CLAUDE.md 注入机制
2.1 不在 System Prompt 里
CLAUDE.md 通过 prependUserContext() 注入(utils/api.ts:449-474):
export function prependUserContext(messages, context): Message[] {
return [
createUserMessage({
content: `<system-reminder>
As you answer the user's questions, you can use the following context:
# claudeMd
${claudeMdContent}
IMPORTANT: this context may or may not be relevant to your tasks.
You should not respond to this context unless it is highly relevant to your task.
</system-reminder>`,
isMeta: true,
}),
...messages,
]
}
后果:
- 优先级低于 system prompt — system prompt 是”宪法”,user message 是”法律”
- 带降权信号 —
this context may or may not be relevant显式告诉模型可能不相关 - 有强指令对冲(
utils/claudemd.ts:89):OVERRIDE any default behavior and you MUST follow them exactly as written— 效果取决于指令具体性
2.2 目录遍历与优先级
从当前目录逐级向上到根目录,每级检查(utils/claudemd.ts:790-1075):
每级目录:
├── CLAUDE.md → Project 类型
├── .claude/CLAUDE.md → Project 类型
├── .claude/rules/*.md → Project 类型(递归扫描子目录)
└── CLAUDE.local.md → Local 类型
全局位置:
~/.claude/CLAUDE.md → User 类型
~/.claude/rules/*.md → User 类型
/etc/claude-code/CLAUDE.md → Managed 类型
加载顺序 = 优先级(最后加载 = 最高优先级,recency bias):
Managed → User → 仓库根 Project → 子目录 Project → 当前目录 → Local(最高)
2.3 @include 指令
utils/claudemd.ts:451-535,支持引入外部文件:
@./path— 相对于当前 CLAUDE.md@~/path— 相对于 home@/path— 绝对路径- 安全限制:扩展名白名单(~80 种文本格式)、循环引用检测、代码块内
@不解析 - 外部文件需
claudeMdExternalIncludesApproved配置审批 - 不存在的文件静默忽略
2.4 特殊控制
| 功能 | 方式 |
|---|---|
| 跳过所有 CLAUDE.md | claude --bare 或 CLAUDE_CODE_DISABLE_CLAUDE_MDS=1 |
| 禁用 Project/Local 类型 | settings.json 的 settingSources |
| 服务端远程禁用 | feature flag tengu_paper_halyard(默认关闭) |
| Git worktree 去重 | 自动检测嵌套 worktree,跳过主仓库的 Project 文件 |
三、Memory 系统
3.1 存储与加载
存储路径:~/.claude/projects/{sanitized-project-path}/memory/,按项目隔离。
通过 loadMemoryPrompt() 加载(memdir/memdir.ts:419-507),注入 system prompt 动态层第 11 位。无降权信号,模型视为系统级指令。
3.2 MEMORY.md 索引机制
硬编码截断(memdir/memdir.ts:35-38):
MAX_ENTRYPOINT_LINES = 200 // 超过 200 行直接丢弃
MAX_ENTRYPOINT_BYTES = 25_000 // 超过 25KB 在最近换行处截断
MEMORY.md 是索引不是记事本。每条一行 ≤150 字符,指向 topic 文件。Topic 文件无行数限制,但只在模型主动 Read 时才被看到——索引描述要足够清晰,模型据此判断是否读取 topic 文件。
3.3 四种类型(按行为影响排序)
| 类型 | 影响程度 | 用途 | 格式要求 |
|---|---|---|---|
| feedback | 最大 | 行为修正(纠正+确认都要记) | 规则 + Why + How to apply |
| user | 中等 | 用户画像,调整沟通方式 | 角色、经验、偏好 |
| project | 中等 | 不能从代码/git 推导的项目信息 | 事实 + Why + How to apply;相对日期→绝对日期 |
| reference | 最小 | 外部系统指针 | 系统名+用途 |
feedback 的关键设计:只记纠正不记确认 → 模型越来越保守。好的 feedback 两种都记。Why 让模型在边缘情况自主判断是否打破规则。
3.4 不该存的内容
源码硬编码排除清单:
- 代码模式/架构/文件路径 — 读代码就知道
- Git 历史 —
git log/git blame是权威源 - 调试方案 — 修复已在代码里
- CLAUDE.md 已有的内容 — 重复无意义
- 临时任务进度 — 用 task 系统
用户要求存 PR 列表时,模型应追问”什么是让你意外的?“——保存意外部分,不存整个列表。
3.5 陈旧机制
memdir/memoryAge.ts:
| 时间 | 行为 |
|---|---|
| 今天/昨天 | 无警告 |
| 2 天以上 | 追加提醒:verify against current code before asserting as fact |
验证规则:memory 提到文件路径 → 先检查是否存在;提到函数名 → 先 grep 确认。
3.6 Memory 与 CLAUDE.md 的配合策略
不要重复,用 feedback 加强 CLAUDE.md 的权重。
CLAUDE.md 写规则(user message 层,低权重)→ feedback 写对该规则的强调(system prompt 层,高权重)→ 两层叠加 > 写两遍同一句话。
3.7 自动记忆提取
满足条件时后台 agent 自动扫描对话提取值得保存的信息:
- 本轮主 agent 没有手动写过 memory
extractMemoriesfeature flag 启用- auto memory 开启
3.8 安全边界
Memory 目录路径不能通过项目级 settings.json 设置——防止恶意仓库指向 ~/.ssh。只有用户级和管理员级配置可改路径。Memory 文件内容无校验(设计意图:文件在本地磁盘,用户有完全控制权)。
四、Agent 系统
4.1 基本概念
Agent = 独立 context window 的工作单元。子 agent 从空白开始,只有传入的 prompt 字符串。Fork 模式继承父 agent 完整对话历史。
创建路由(tools/AgentTool/AgentTool.tsx):
Agent tool 调用
├─ 指定 subagent_type → 用该类型定义从零开始
├─ 未指定 + Fork 开启 → Fork(继承完整历史,prompt cache 1/10 成本)
└─ 未指定 + Fork 未开启 → General Purpose Agent
4.2 三种内置 Agent
| Agent | 模型 | 工具 | 特殊行为 |
|---|---|---|---|
| Explore | 外部用户: Haiku / Anthropic 员工: 继承主模型 | 只读 | omitClaudeMd: true(跳过 CLAUDE.md) |
| Plan | 继承主模型 | 只读 | — |
| General Purpose | 继承主模型 | 全部 | — |
Explore 模型差异源码(built-in/exploreAgent.ts):
model: process.env.USER_TYPE === 'ant' ? 'inherit' : 'haiku'
4.3 工具权限控制
子 agent 禁止使用的工具(constants/tools.ts):
TASK_OUTPUT, EXIT_PLAN_MODE, ENTER_PLAN_MODE, ASK_USER_QUESTION, TASK_STOP
+ 外部用户禁止 AGENT_TOOL(不能嵌套 agent,Anthropic 员工不受限)
后台 agent 工具白名单更窄:不含 ASK_USER_QUESTION(后台跑,用户看不到)。
4.4 自定义 Agent
在 .claude/agents/ 下创建 .md 文件,frontmatter 配置 + 正文 system prompt:
---
name: code-reviewer
description: 审查代码变更 # Claude 据此自动判断何时委派
tools: Read, Grep, Glob, Bash(git diff:*) # 严格白名单 + 内联权限
model: sonnet # inherit / sonnet / opus / haiku
isolation: worktree # 可选,独立 git worktree
background: true # 可选,后台运行
memory: project # 可选,独立记忆空间 .claude/agent-memory/{type}/
maxTurns: 15
---
覆盖优先级:企业策略 > 项目 .claude/agents/ > 用户 ~/.claude/agents/ > 插件 > 内置
覆盖 Explore 用 Sonnet:创建 .claude/agents/Explore.md 并设 model: sonnet。
4.5 权限模式
| 模式 | 行为 |
|---|---|
bubble(Fork 默认) | 权限提示冒泡到主终端 |
acceptEdits | 自动允许文件操作 |
plan | 只能规划不能执行 |
bypassPermissions | 全部自动批准 |
dontAsk | 全部自动拒绝 |
后台 agent 遇到需审批操作自动拒绝(因为用户看不到)。
4.6 并行与上限
无硬编码 MAX_WORKERS。实际约束:API 并发数、本地内存/CPU、远程 bridge 默认 32 并发。
推荐:5-8 个并行 agent,每个 5-8 文件。单 agent ~167K tokens 工作空间,5 个 = 835K tokens。
4.7 Agent Teams(实验性)
开启:CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
与 subagent 的区别:
| Subagent | Agent Team | |
|---|---|---|
| 通信 | 只向主 agent 汇报 | 队友间直接消息(Mailbox) |
| 协调 | 主 agent 管理 | 共享任务列表,自协调 |
| 成本 | 较低 | 较高(每个队友独立 context) |
建议 3-5 个队友,每人 5-6 个任务。支持 in-process(Shift+Down 切换)或 split panes(tmux/iTerm2)。
五、隐藏安全机制
5.1 反蒸馏(Anti-Distillation)
ANTI_DISTILLATION_CC flag 启用时:
- 假工具注入:API 请求带
anti_distillation: ['fake_tools'],服务端向 system prompt 静默注入伪造工具定义 - 服务端摘要签名:connector-text summarization + 密码学签名
绕过方式:环境变量 CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS 可关闭。
5.2 卧底模式(Undercover Mode)
undercover.ts(~90 行):在外部仓库中剥离内部代号(Capybara、Tengu 等),隐藏 AI 贡献归属。
- 默认开启,无 force-OFF 开关
- Dead-code elimination 使其在外部构建中不可逆
- 用途:Anthropic 员工用 Claude Code 向公开开源仓库提交代码时隐藏 AI 痕迹
5.3 情绪检测(Frustration Detection)
userPromptKeywords.ts:用正则匹配脏话/沮丧短语,不用 LLM 推理(更快更便宜)。检测结果作为 UX 信号。
5.4 客户端认证
请求头 cch=00000 占位符,由 Bun 的 Zig HTTP 栈在请求离开进程前替换为计算哈希。密码学证明请求来自官方 Claude Code 二进制文件——“basically DRM for API calls”。
5.5 内部代号
| 代号 | 对应 |
|---|---|
| Capybara | Claude 4.6 变体 |
| Fennec | Opus 4.6 |
| Numbat | 未发布,测试中 |
| Tengu | 旧代号 |
六、未发布功能
6.1 KAIROS — 自主守护进程
源码中引用 150+ 次。核心能力:
- 后台常驻 daemon 模式(5 分钟 cron 周期)
/dream命令触发记忆整合- append-only 日志
- GitHub webhooks 集成
- 15 秒阻塞预算
gated behind 内部 feature flag,外部 npm 包中不存在。
6.2 autoDream — 记忆整合
三重门控触发条件:
- 时间间隔 ≥ 24 小时
- 已完成 ≥ 5 个会话
- consolidation lock(mtime 追踪,支持回滚)
四阶段整合周期:Orient → Gather → Consolidate → Prune
6.3 ULTRAPLAN — 远程深度规划
将规划任务卸载到 Opus 远程会话,最长 30 分钟。
6.4 Coordinator Mode
一个主 Claude 实例同时生成和管理多个 worker agent。feature flag 控制。
七、工程细节
print.ts:单个函数 3167 行,12 层嵌套bashSecurity.ts:9707 行,23 项安全检查(含 Zsh 特定威胁防御)- 终端渲染:游戏引擎技术(Int32Array char pools、bitmask metadata)
- 上下文压缩:MicroCompact → AutoCompact → Full Compact,circuit breaker 在连续 3 次失败后触发(
MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3) - 自动压缩在 ~167,000 tokens 时触发
- BigQuery 日志揭示:1279 个会话有 50+ 次连续失败,浪费 ~250K API calls/day
来源表
| # | 文章 | 质量 | 核心覆盖 |
|---|---|---|---|
| 1 | LINUX DO — 从源码理解 CLAUDE.md | A | §二、§一 |
| 2 | LINUX DO — 从源码解构 MEMORY.md | A | §三 |
| 3 | LINUX DO — 从源码理解 Agent 系统 | A | §四 |
| 4 | Alex Kim — fake tools, undercover mode | A | §五 |
| 5 | Sabrina.dev — Comprehensive Analysis | A- | §六、§七 |