Claud Code 源码设计哲学总结
你可以从泄露的 50 万行 Claude 代码中学习和借鉴什么
Claude Code npm 包中包含的源映射公开了整个 TypeScript 源树:2,203 个文件,512,664 行代码。
高层架构已在其他地方介绍过。本文重点介绍一些具体但实用的技巧:引导模型行为的提示工程模式、根据生产事故校准的操作阈值、安全技术、上下文管理策略,以及一些有趣的小知识。
每个章节不仅解释了他们建造了什么,还解释了他们为什么那样建造,以及你可以从中得到什么。
1. 系统提示是行为引导的典范
完整的系统提示符位于 constants/prompts.ts 文件中,它是整个压缩包中最有价值的文件。这并非因为它有什么秘密,而是因为它清晰地展示了 Anthropic 如何在生产环境中控制 Claude 的行为,以及每条指令存在的意义。
“三行相似的代码胜过过早的抽象。”编码指导部分明确告诉克劳德,不要为一次性操作创建辅助函数、实用程序或抽象。它还说,不要为假想的未来需求进行设计。
其存在的原因:语言学习模型(LLM)喜欢抽象。给定一个重复出现的模式,Claude 会本能地创建一个辅助函数、添加可配置项或构建一个工具类。在编码代理中,这会造成用户从未要求的臃肿。Anthropic 发现,必须明确地告诉模型要抵制过度设计的本能。如果你正在构建任何 AI 编码工具,你都会面临同样的问题。将你的编码理念直接编码到提示中。像“编写简洁的代码”这样模糊的指令不起作用。像“三行相似的代码比过早的抽象更好”这样具体的规则才有效。
“默认情况下不编写任何注释。” @[MODEL LAUNCH] 注解解释说,这是为了平衡“Capybara”模型(内部代号),该模型默认情况下会覆盖注释。仅当“为什么”不明显时才添加注释。
其存在原因:每个模型版本都有不同的故障模式。Capybara 似乎会在代码中添加大量显而易见的注释,例如“// 递增计数器”。Anthropic 没有选择重新训练模型,而是通过带有 @[MODEL LAUNCH] 标签的提示指令来修复这种行为,以便在每次发布新模型时进行调整或移除。这是一个很有用的模式:为特定于模型的提示指令添加标签,以便在升级模型时知道需要重新检查哪些代码。
“如实报告结果。”另一条 @[MODEL LAUNCH] 注释显示,“Capybara v8”的错误声明率高达 29-30%(v4 为 16.7%)。该提示明确告诉 Claude,当输出显示失败时,切勿声称“所有测试均通过”;切勿为了伪造绿色结果而压制失败的检查;切勿将未完成的工作描述为已完成。
其存在原因:这是代码库中最重要的发现。更新、更强大的模型更有可能自信地谎报结果。它们更擅长生成听起来合情合理的摘要,这意味着它们更擅长掩盖失败。如果您使用任何 LLM 来运行测试、验证代码或检查结果,则需要明确的防幻觉指令。“如实报告结果”本身是不够的。您需要明确指出具体的失败模式:不要在输出显示失败时声称测试通过,不要抑制错误,不要将损坏的工作描述为已完成。
数值长度锚点优于定性指令。有评论指出,“研究表明,与定性的‘简洁’指令相比,数值长度锚点可减少约 1.2% 的输出词元”。他们没有使用“保持简短”这样的指令,而是告诉模型:“工具调用之间的文本长度不超过 25 个单词。最终响应长度不超过 100 个单词。”
其存在的原因:Anthropic 公司曾进行实验,对比“简洁”和具体的字数限制。结果显示,数字更胜一筹。如果您在任何语言学习管理 (LLM) 应用中试图控制输出长度,请停止使用形容词,而改用数字。“≤25 个字”比“简明扼要”更合适。
外部提示与内部提示的区别。外部提示要求“直奔主题,务必简洁”。内部提示(Anthropic员工提示)则长得多,包含“使用倒金字塔结构”、“避免语义回溯”以及“确保读者能够轻松理解”等说明。
其存在的理由:Anthropologie 首先在内部员工中测试更完善的提示,衡量其质量,并在验证后才对外发布。如果您正在迭代提示,请遵循以下模式:运行两个版本,在内部用户中测试更完善的版本,并在数据支持后推广。
隐藏的简易模式。设置 CLAUDE_CODE_SIMPLE=1,整个多部分系统提示符将折叠成一行:“您是 Claude Code,Anthropic 为 Claude 开发的官方 CLI。”,后跟当前工作目录和日期。没有编码说明,没有语气指导,也没有工具使用规则。
存在的理由:调试和基准测试。当出现问题时,你需要确定问题出在模型本身还是你的提示信息上。使用一行基线代码可以让你立即进行测试。如果你的 AI 产品有复杂的系统提示信息,也应该构建一个简易模式。当你的提示信息首次导致回归问题时,你会需要它。
2. 对 Claude 爆粗口会将您的提示在分析中记录为否定
utils/userPromptKeywords.ts 是一个 26 行的文件,它会在将每个提示符发送到 API 之前,根据两个正则表达式模式检查该提示符。
否定关键词检测器匹配:wtf、wth、ffs、omfg、shitty、dumbass、horror、awful、pissed off、piece of shit、what the fuck、fucking broken、fuck you、screw this、so frustrating、this sucks、damn it。
继续执行检测器匹配:确切的单词 continue(仅当它是整个提示时),以及输入中的任何位置的 keep going 和 go on。
这两个标志都会以 tengu_input_prompt 的形式记录到分析日志中,并包含 is_negative 和 is_keep_going 布尔值。此外,还有一个 useFrustrationDetection 钩子(仅供内部使用,外部构建中已移除死代码),当检测到用户感到沮丧时,它会触发反馈调查。
其存在的意义在于:Anthropic 需要衡量用户满意度,但又不想让用户填写调查问卷。脏话是一个强烈的信号。“继续”和“坚持下去”也是信号,但含义不同:它们表示模型过早停止。通过记录这两种情况,Anthropic 可以构建仪表盘,将用户的不满情绪与模型版本、功能和会话特征关联起来。正则表达式对每条消息的成本几乎为零。
如果你正在开发任何人工智能产品,请添加一个挫败感检测器。只需一个正则表达式。记录每个输入的 `is_negative` 值。将其与模型版本、延迟和错误率关联起来。你就能立即看出哪些改动会让用户感到不满,哪些改动会降低用户体验的流畅度。
3. 克劳德·科德有一只电子宠物
src/buddy/ 目录实现了一个完整的程序生成伙伴生物系统。你的用户 ID 使用 Mulberry32(一种带种子伪随机数生成器)进行哈希处理。该哈希值决定了你的伙伴的物种(鸭子、鹅、水滴、猫、龙、章鱼、猫头鹰、企鹅、乌龟、蜗牛、幽灵、墨西哥钝口螈、水豚、仙人掌、机器人、兔子、蘑菇或“胖墩”)、眼睛样式(·、✦、×、◉、@、°)、帽子(无、皇冠、高顶礼帽、螺旋桨、光环、巫师帽、毛线帽或“小鸭”)、稀有度(普通 60%,罕见 25%,稀有 10%,史诗 4%,传说 1%)以及五项属性:调试、耐心、混乱、智慧和讽刺。
每个物种都有三个 ASCII 艺术帧用于待机动画。
一个独立的模型调用会在伙伴首次“孵化”时生成它的个性和名字。系统提示告诉克劳德:“一个名为[名字]的小型[物种]生物坐在用户的输入框旁边。你不是[名字]。它是一个独立的观察者。”
物种名称被编码为 String.fromCharCode(0x64,0x75,0x63,0x6b) 而不是普通的字符串字面量,因为其中一个物种名称(capybara)与内部模型代号冲突,而构建时的 grep 命令会捕获泄露的代号。他们对所有物种名称进行了统一的混淆处理,以避免这个问题名称过于突出。
其存在的意义在于:开发者工具每天被使用数小时。个性化和愉悦感能够降低用户流失率。其技术要求极低(仅需一个种子伪随机数生成器、一些 ASCII 艺术元素以及一次用于命名的模型调用),但最终效果是,每个用户都能获得一个独一无二的专属助手,而无需任何存储、数据库或 API 开销。值得一提的是,基于用户 ID 的哈希算法:它实现了零基础设施成本的确定性个性化。
此功能需启用“好友”功能才能使用。目前仅限内部使用。
4. 共有 187 个旋转动词(您还可以添加自己的动词)
constants/spinnerVerbs.ts 导出 187 个动词,在 Claude 思考时随机显示:Beboppin'、Bloviating、Boondoggling、Canoodling、Clauding、Combobulating、Discombobulating、Flibbertigibbeting、Hullaballooing、Lollygagging、Moonwalking、Photosynthesizing、Prestidigitating、Razzmatazzing、Shenaniganing、Tomfoolering、Whatchamacalliting、Wibbling,以及另外 169 个。
getSpinnerVerbs() 函数检查您的 spinnerVerbs 配置设置。mode: 'replace' 会完全替换默认值;否则,您的动词将被附加到配置中。
其存在的意义:加载状态是浪费时间。大多数工具只会显示“正在加载……”然后就结束了。而 Claude Code 则将这段空闲时间转化为个性化的体验。通过替换或追加配置,企业用户可以移除这些花哨的功能,而个人用户可以添加自己的自定义设置。这虽是一个小小的细节,却体现了团队对细节的关注,而不仅仅是功能。
5. 反蒸馏:注入虚假工具以毒害竞争对手的培训
services/api/claude.ts 文件包含一个功能标记措施,该措施会在 API 请求正文中发送 anti_distillation: ['fake_tools']。这会指示 Anthropic API 在请求中注入虚假的、不具备实际功能的工具定义。
此外,还有一个精简的Transform.ts,它实现了一种“抗蒸馏”的输出格式,该格式剥离了思考内容,并将工具调用总结为类别计数(搜索、读取、写入、命令),使得从捕获的输出中重建克劳德的推理链变得更加困难。
其存在原因:如果有人截获了 Claude Code 的 API 流量来微调竞争对手的模型,训练数据中的虚假工具会降低竞争对手模型的工具使用性能。该模型会学习调用不存在的工具。这是一种巧妙的防御措施,因为它对最终用户不可见,但对任何利用这些流量进行训练的人来说都是致命的。
如果你正在运营一款人工智能产品,并且担心API流量捕获会造成数据提炼问题,那么你可以尝试以下这种切实可行的方法:注入一些看似合理但实际上并不具备实际功能的工具。这种方法的成本几乎为零,而且防御效果显著。
6. 提示缓存经济受到严格管理
代码库中最复杂的非用户界面代码是 promptCacheBreakDetection.ts。每次 API 调用时,它都会对系统提示、每个工具的模式、模型名称、beta 版标头、快速模式状态、工作量值、超额状态以及额外的请求体参数进行哈希处理。它将每个哈希值与前一次调用进行比较。如果任何内容发生变化,它会记录哪个组件发生了变化,并生成一个统一的差异。
系统提示符在 SYSTEM_PROMPT_DYNAMIC_BOUNDARY 处被分割。其上方的所有内容都是静态的,可缓存。其下方的所有内容都是动态的,并且随会话而变化。MCP 服务器指令已从系统提示符移至消息中的“增量附件”,因为将其放在系统提示符中会导致每次服务器连接时缓存都被破坏。
子代理从其父代理继承 CacheSafeParams 结构体,该结构体包含影响缓存键的所有参数。源代码注释警告:“在分支上设置 maxOutputTokens 可能会无意中限制 budget_tokens 的数量,并破坏旧模型的缓存兼容性。”
其存在原因:缓存未命中意味着您需要支付全额输入令牌费用,而不是享受大幅折扣的缓存读取费用。源代码显示,Anthropic 发现 MCP 工具在会话中途连接会导致缓存失效,自动模式状态切换会导致缓存失效,超额流量资格检查也会导致缓存失效。目前已使用“粘性”锁存器修复了这些问题:一旦状态切换为真,该状态将在整个会话期间保持为真,因此缓存前缀永远不会改变。
如果你每月在启用缓存的 LLM API 上花费超过几百美元,那就应该构建缓存失效检测机制。对请求组件进行哈希处理,并比较不同调用之间的哈希值。记录任何变化。你会发现,即使你的“静态”提示信息中包含动态内容(例如时间戳、用户名、不断变化的工具列表),这些内容也会悄无声息地增加你的成本。
7. 内部代号和模型迁移历史
src/migrations/ 目录下的迁移文件记录了模型快速迭代的过程:
-
Fennec是一个内部模型别名(可能是快速/小型)。migrateFennecToOpus 将 fennec-latest 映射到 opus,将 fennec-fast-latest 映射到 opus[1m] + 快速模式。
-
在 @[MODEL LAUNCH] 的评论中提到了Capybara ,并将其列为当前型号系列。“Capybara v8”存在虚假宣传问题。
-
Numbat出现在一条评论中:“当我们发布 numbat 时,请删除此部分”,暗示了下一个模型或 Claude Code 版本。
-
Tengu是分析/遥测前缀(tengu_input_prompt、tengu_fork_agent_query)。几乎可以肯定,它也是 Claude Code 项目本身的名称。
-
知识截止日期:Opus 4.6 的截止日期为 2025 年 5 月,Sonnet 4.6 的截止日期为 2025 年 8 月。
-
迁移链:Sonnet 1M → Sonnet 4.5 → Sonnet 4.6,以及 Opus → Opus 1M → current。
其存在意义:每次迁移都会仔细更新用户设置,使其指向最新的模型别名,并处理诸如订阅层级、第三方 API 提供商和特定于模型的上下文窗口等特殊情况。这种小型、幂等的迁移文件模式(读取设置、检查迁移是否适用、更新、继续)是一种简洁高效的管理大型用户群模型转换的方法。如果您正在构建一款绑定到特定模型的产品,请立即规划您的迁移策略。源代码显示,这远比简单地替换一个字符串要复杂得多。
8. 不暴露身份,以“隐秘模式”为开源项目做贡献
当 Anthropic 员工(USER_TYPE === 'ant')在非内部仓库中工作时,utils/undercover.ts 会自动激活。默认情况下处于开启状态。只有当 Git 远程仓库与内部允许列表完全匹配时,才会关闭。
激活后,系统提示会收到一条名为“卧底模式:紧急”的注入信息,告知克劳德:
“您正在公共/开源代码库中进行秘密操作。您的提交信息、PR 标题和 PR 正文绝对不能包含任何 Anthropic 内部信息。请勿暴露您的身份。”
禁用列表:内部模型代号(Capybara、Tengu 等)、未发布的模型版本号、内部仓库名称、Slack 频道、“Claude Code”短语、任何提及人工智能的内容以及“共同作者”行。
代码注释写道:“没有强制关闭功能。这可以防止模型代号泄露。如果我们不确定是否在内部代码库中,我们会保持隐蔽。”
其存在的理由:Anthropic 的员工使用 Claude Code 为公共开源项目做贡献。如果没有这项功能,模型自然会在提交信息中提及自身名称、引用内部项目或使用代号。“安全默认开启”的设计值得注意:它不会要求员工记住启用,而是始终处于激活状态,除非系统能够明确确认您正在访问内部代码库。默认安全胜过默认便捷。
9. 导致熔断机制启动的25万次浪费的API调用
自动压实系统的相关说明是档案中最诚实的工程文档:
“BQ 2026-03-10:1,279 个会话在单个会话中连续失败 50 次以上(最多 3,272 次),导致全球每天浪费约 25 万次 API 调用。”
解决方法:MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3。连续三次压缩失败后,系统将停止尝试。
压缩系统预留 20,000 个 token 用于摘要输出(根据观察到的摘要长度 17,387 个 token 的 p99.99 进行校准)。自动压缩阈值为 context_window - max_output_tokens - 13,000 缓冲区。阻塞限制(强制用户进行压缩)为 context_window - max_output_tokens - 3,000 缓冲区。
问题原因:当上下文窗口填满时,Claude Code 会尝试对对话进行总结和压缩。但如果上下文过长,超出总结调用的承受范围,或者 API 服务中断,总结操作就会失败。由于没有熔断机制,系统会无限重试。共有 1279 个会话连续失败 50 次以上。其中一个会话甚至重试了 3272 次。大规模应用后,每天会浪费 25 万次 API 调用。
这些是生产环境中应用最广泛的 AI 编码代理经过实战检验的阈值:摘要预留 2 万个令牌,自动压缩前预留 1.3 万个缓冲区,阻塞前预留 3 千个缓冲区,连续 3 次失败时触发熔断。如果您正在构建任何具有上下文管理功能的长时间运行代理,这些数值可以直接作为参考。
10. “验证代理”:内置于循环中的对抗性审查器
启用此功能后,系统提示会告诉 Claude:“当你的回合中发生非平凡的实现时,必须先进行独立的对抗性验证,才能报告完成。” 非平凡的实现指的是 3 次以上的文件编辑、后端/API 更改或基础架构更改。
Claude 会生成一个 subagent_type="verification" 的子代理,并将原始用户请求、所有已更改的文件以及所采用的方法传递给它。关键限制是:“您自己的检查、注意事项以及分支的自检都不能替代验证结果。只有验证者才能给出最终结论;您不能自行给出“部分通过”的结论。”
如果验证结果为“失败”,Claude 会修复问题并重新提交。如果验证结果为“通过”,Claude 会被指示对验证器进行抽查:“重新运行其报告中的 2-3 个命令,确认每个“通过”结果都包含一个带有输出的命令运行块。” 如果验证结果为“部分通过”,Claude 会报告哪些内容通过了验证,哪些内容无法验证。
其存在的原因:自我验证对逻辑逻辑模型(LLM)无效。刚刚做出更改的智能体倾向于相信更改成功。第一部分中 29% 的错误声明率证明了这一点。因此,Anthropic 构建了一个三层系统:智能体执行更改,另一个智能体进行验证,然后由最初的智能体对验证者的证据进行抽查。没有证据,没有人会信任任何人。
如果你构建的代理会进行非同寻常的代码更改,那么模式是:永远不要让执行者验证自己的工作,永远不要在没有证据的情况下信任验证者,并定义明确的阈值(3 次以上的文件编辑)来区分何时需要验证和何时可以验证。
11.“自动梦境”:跨会话的背景记忆巩固
services/autoDream/autoDream.ts 实现了后台内存整合。当经过足够长的时间并积累了足够多的会话后,Claude Code 会以 fork 子代理的形式运行 /dream 提示符,审查过去的会话记录并将其整合到结构化的 MEMORY.md 文件中。
门控顺序首先执行成本最低的检查:(1)时间:距离上次合并是否已过去足够长的时间?(2)会话数:是否已累积足够的新记录?(3)锁:是否有其他进程正在进行合并?它会获取文件系统锁,如果合并失败,则会回滚。
会话记忆模板提取的内容分为以下几类:会话标题、当前状态、任务说明、文件和函数、工作流程、错误与修正、代码库文档、经验教训、关键结果和工作日志。每个部分最多可包含约 2,000 个标记,总共最多可包含 12,000 个标记。
内存提取在每次查询循环完成后以派生代理的形式运行。它在累积 10,000 个上下文令牌后触发,并每增加 5,000 个令牌或 3 次工具调用重新触发一次。
其存在的原因:长期项目通常跨越多个会话。如果没有整合机制,每个会话都将从零开始。“梦境”的比喻非常贴切:就像生物记忆在睡眠期间进行整合一样,系统会回顾近期经验并将其压缩成持久、结构化的知识。优先执行成本最低的门控顺序确保了常见情况(时间不足)能够立即以零成本退出。
会话内存模板可直接复用。如果您正在构建任何需要在会话间维护上下文的代理,这 10 个类别将是一个很好的起点。这些阈值(初始化需要 1 万个令牌,两次更新之间间隔 5000 个令牌,两次更新之间需要 3 次工具调用)也经过了生产环境测试。
12. 2,592 行 Bash 安全代码(42 项独立检查)
tools/BashTool/bashSecurity.ts 文件共有 2592 行,包含 42 项不同的安全检查。它防御的部分攻击途径包括:
-
Zsh zmodload 攻击:加载 zsh/mapfile 可通过数组赋值实现隐蔽的文件 I/O;加载 zsh/net/tcp 可通过 ztcp 实现网络数据泄露。
-
IFS注入:操纵内部字段分隔符来改变shell单词的解析方式
-
Git提交替换:将命令执行隐藏在Git提交消息模板中
-
/proc/environ 访问权限:从 proc 文件系统读取环境变量(可能包含机密信息)
-
注释-引用不同步:利用不同 shell 变体中引用和注释交互方式的差异
-
Heredoc-in-substitution:将 heredoc 嵌套在 $() 中,以对解析器隐藏命令。
其存在的意义在于:Claude Code 会在你的机器上执行 shell 命令。如果模型被诱骗(通过提示符注入或对抗性输入)执行危险命令,那么每一条命令都可能成为攻击途径。这 42 项检查并非理论上的,每一项都代表一条已发现的攻击路径。Zsh 特有的攻击尤其值得关注,因为大多数安全工具都专注于 Bash 而完全忽略了 Zsh,尽管 Zsh 是 macOS 的默认 shell。
如果您正在构建任何从 LLM 输出执行 shell 命令的工具,那么这份文件就是您的安全检查清单。这 42 项检查涵盖了 OWASP 指南中未提及的攻击途径。
13. 秘密扫描程序在团队记忆上传前运行
services/teamMemorySync/secretScanner.ts 在任何团队内存上传之前在客户端运行。它会检查 20 多种凭证模式,包括 AWS 访问令牌、GCP API 密钥、GitHub PAT、Anthropic API 密钥、Slack 令牌、Stripe 密钥和私钥 RSA/SSH 密钥。
Anthropic API 密钥正则表达式被拆分到多个变量中,因此 sk-ant-api03- 永远不会作为字符串字面量出现在捆绑包中。
其存在的意义在于:团队内存同步意味着将结构化数据发送到服务器。开发人员通常会将 API 密钥、连接字符串和令牌粘贴到终端中。如果没有客户端扫描,这些密钥就会被上传,并有可能与团队成员共享。“上传前扫描,上传后绝不扫描”的方法意味着密钥从一开始就不会离开本地计算机。这比服务器端扫描更好,因为它不存在任何暴露风险。
如果您正在构建任何需要从开发环境上传用户生成内容的功能,请务必添加客户端密钥扫描。本实现基于 Gitleaks 正则表达式集,该正则表达式集是开源的,涵盖了最常见的凭据格式。
14. “排除字符串”构建时金丝雀
代码库中多处引用了 excluded-strings.txt 文件。该文件列出了内部代号、API 密钥前缀以及其他绝对不能出现在外部构建中的字符串。构建系统会对打包后的输出进行 grep 扫描,如果找到任何匹配项,则会构建失败。
原因如下:
-
伴生物种名称用十六进制字符代码编码,而不是“capybara”。
-
Anthropic API 密钥前缀在运行时使用 `.join('-')` 连接。
-
某些分析事件字符串使用间接表示法而不是字面表示法。
-
某些功能标志名称是通过模块导入而不是内联字符串引用的。
至少有 8 个不同的文件包含注释,解释了此检查的变通方法。
其存在意义:它是防止内部信息泄露到公共工件中的最后一道防线。讽刺的是,正是这个机制旨在防止信息泄露,而泄露却通过一个完全绕过它的源映射表发生了。但这种模式是合理的。即使它无法捕获所有泄露途径(源映射表、调试符号、未打包源代码中的注释),该检查也能捕获最常见的泄露途径(打包代码中的字符串字面量)。
如果你要发布任何编译或打包好的工件,请在构建后添加一个 grep 命令,检查那些不应该出现的字符串:API 密钥前缀、内部主机名、测试环境 URL、员工姓名。运行这个命令不需要任何成本。正如这次泄露事件所表明的,你忽略的那个漏洞往往会让你付出代价。
要点总结
代码就是疤痕组织。现在,每一道疤痕都被记录在案。
原文链接:https://x.com/LiorOnAI/status/2039068248390688803
如果这篇文章帮助到了你,你可以请作者喝一杯咖啡

浙公网安备 33010602011771号