跳到主要内容

CLAUDE.md 作为代码库 API:为什么你的 Agent 指令文件是你写过的最具杠杆效应的文档

· 阅读需 10 分钟
Tian Pan
Software Engineer

大多数团队对待 CLAUDE.md 的方式和对待 README 一样:写一次,然后忘掉它的存在,最后疑惑为什么什么都不好使。但 CLAUDE.md 不是文档。它是你的代码库和每一个接触它的 AI agent 之间的 API 契约。写对了,每一次 AI 辅助的提交都遵循你的架构。写错了——或者更糟,让它腐化——你实际上是在每次会话中让你的 agent 变得更笨。

AGENTbench 研究在 12 个代码库中测试了 138 个真实编码任务,发现自动生成的上下文文件实际上降低了 agent 的成功率,甚至不如完全没有上下文文件。三个月积累的指令,其中一半描述的代码库已经面目全非,不会指导 agent——它们会误导 agent。

指令预算比你想象的要小

每个 AI 编程 agent 都有有限的指令遵循能力。对前沿 LLM 的研究表明,它们大约能可靠地遵循 150-200 条指令并保持合理的一致性。这听起来很慷慨,直到你意识到仅 Claude Code 的系统提示就消耗了大约 50 个这样的槽位。Cursor 的 agent 基础设施同样会吃掉一部分预算。你的 CLAUDE.md 只能用剩下的部分。

这创造了一个大多数团队忽视的硬约束。一个 500 行的 CLAUDE.md,塞满了风格指南、架构决策、调试技巧和团队惯例,不是全面——而是噪音。LLM 表现出"中间遗失"效应,长文档中间部分的指令会被系统性地忽略。随着指令数量增加,所有指令的遵循质量都会均匀下降,而不仅仅是新增的指令。

实际上限大约是 300 行,而将文件保持在 60 行以下的团队报告了最一致的 agent 行为。60 行文件和 500 行文件的区别不是后者覆盖更多——而是后者什么都不能可靠覆盖。

什么该放在文件里(什么不该)

最高杠杆的内容遵循严格的优先顺序:

构建和测试命令排在第一位。这是你能放在上下文文件中最有价值的东西。不是"运行测试"而是 yarn test --coveragemake test-api。一个知道确切调用命令的 agent 可以验证自己的工作。一个被告知"运行测试"的 agent 会猜,而且会猜错。

技术栈及版本紧随其后。不是"我们用 React"而是"Next.js 15(App Router),TypeScript 5.7(严格模式),PostgreSQL 16 配合 Drizzle ORM"。具体性防止 agent 为错误的框架版本生成代码——当 agent 默认使用训练数据中最普遍的版本时,这是一个令人惊讶的常见失败模式。

架构约束很重要,但只有非显而易见的那些。如果你的项目使用带有薄控制器的仓储模式,说出来。如果业务逻辑绝不能存在于路由处理器中,说出来。agent 可以通过阅读代码推断很多,但它无法推断关于东西应该放在哪里的组织决策。

不该放的东西:

  • 风格规则。 永远不要让 LLM 做 linter 的工作。如果你在意 4 空格缩进或 React 组件中不用箭头函数,配置 ESLint 和 Prettier。用宝贵的指令预算来处理格式化是浪费。
  • agent 已经正确执行的事情。 如果 Claude 不用告知就已经在写 TypeScript,这条指令就是死重。把它转化为钩子或删除它。
  • 特定任务的指导。 关于特定功能或迁移的指令属于提示词,而不是永久上下文文件。每次会话都会为 CLAUDE.md 中的每一行支付 token 成本,无论它是否相关。

没人用的文件层级

大多数开发者创建一个单独的根级 CLAUDE.md 就完事了。但每个主要的 AI 编程工具都支持从宽泛到具体加载的层级结构,更具体的指令覆盖更宽泛的指令。

加载顺序通常是:先企业策略,然后用户级偏好,然后项目根目录,然后子目录级文件。这意味着你可以有一个覆盖项目范围惯例的根 CLAUDE.md,和一个 src/api/CLAUDE.md 来添加 API 特定约束——比如"所有端点必须用 Zod schema 验证输入"——而不会让根文件膨胀。

这个层级优雅地解决了 monorepo 问题。共享服务目录可以强制执行与前端应用目录不同的模式,全部在同一个仓库内。约束预算在本地而非全局消耗。

新兴的跨工具架构看起来像这样:

AGENTS.md (通用基础——被 60,000+ 项目支持)
├── CLAUDE.md (仅 Claude 特定的补充)
├── copilot-instructions.md (Copilot 特定)
└── .cursor/rules/ (Cursor 范围规则)

AGENTS.md 正在成为最接近通用标准的东西,由 Linux 基金会的 agents.md 倡议管理。同时维护 AGENTS.md(用于跨工具兼容性)和一个精简的 CLAUDE.md(用于 Claude 特定覆盖)的团队可以两全其美。

杀死指令文件的三个反模式

厨房水槽综合症是最常见的失败。每个团队成员添加他们偏好的惯例,每次调试会话产生一条新规则,三个月内这个文件就变成了 600 行的策略文档,agent 把它当作背景噪音。修复方法很简单但需要纪律:如果你添加一行,你必须证明它为什么适用于每一次会话,而不仅仅是当前任务。

上下文腐化更加隐蔽。你的 CLAUDE.md 说项目用 Express.js,但你两个月前迁移到了 Fastify。它引用了一个 src/utils/auth.ts 文件,该文件已被重构为三个独立模块。过时的结构引用不仅浪费 token——它们会主动误导。agent 为不再存在的架构生成代码,由此产生的 bug 很微妙,因为代码对于文档记载的结构来说看起来是对的。上下文腐化比完全没有上下文文件更糟糕,这正是 AGENTbench 研究所证明的。

指令矛盾发生在规则累积而没有审查的时候。"总是写全面的测试"与"保持 PR 小而聚焦"矛盾。"到处使用依赖注入"与"避免过早抽象"矛盾。agent 不可预测地解决矛盾,有时遵循一条规则,有时另一条,有时都不遵循。结果是不一致的行为,侵蚀对工具的信任。

渐进式披露:可扩展的架构

指令预算问题的解决方案不是把更多内容塞进更少的行中——而是渐进式披露。你的 CLAUDE.md 变成一个按需加载详情的入口点,而不是一个总是加载所有内容的单体文件。

模式是这样工作的:你的根 CLAUDE.md 包含 30-60 行普遍适用的指令。它引用单独的文档——docs/architecture.mddocs/testing-guide.mddocs/api-conventions.md——agent 只在任务需要时才读取。Cursor 的范围规则通过基于文件类型的激活原生支持这一点。Claude Code 的技能系统类似地工作,只在检测到匹配任务时才加载专门的指令。

这反映了好的 API 的工作方式。你不会把整个数据库 schema 倾倒到每个响应中。你提供端点,为当前请求返回相关数据。你的 CLAUDE.md 应该以同样的方式工作——一个轻量级路由器,在需要时将 agent 引导到详细上下文,而不是一个将所有内容强制放入每次会话的平面文件。

一些团队更进一步使用确定性工作流。他们不寄希望于 agent 遵循"写测试"这样的通用指令,而是定义命名命令——$prepare$start-design$start-feature$commit——加载特定上下文并强制执行顺序。$prepare 命令加载核心上下文并验证其存在。$start-design 命令在编写任何代码之前创建设计文档。$commit 命令运行验证清单。如果 $prepare 在当前会话中没有运行过,agent 产出的一切都被视为不可信的草稿。

维护纪律

没有维护流程的指令文件是一个倒计时到无关紧要的文件。让这些文件保持承重作用的纪律并不复杂,但它要求将文件当作代码而非文档来对待。

随代码一起审查。 当 PR 改变了技术栈、架构或测试策略时,CLAUDE.md 应该在同一个 PR 中更新。不是作为后续任务。不是作为单独的工单。在同一个 diff 中。

每季度审计。 阅读每一行并问:这还适用吗?这是 agent 不需要被告知就会正确执行的吗?是否应该有一个钩子或 linter 来强制执行这个?无情地删除。一条错误的指令比没有指令更糟。

测试它。 把你的 CLAUDE.md 给一个新团队成员(或一个全新的 agent 会话),让他们完成一个典型任务。如果他们尽管遵循了文件却产出了违反惯例的代码,文件是坏的。如果他们不读一半文件也能产出正确的代码,那一半应该被删除。

关注信号。 Claude Code 负责大约 4% 的所有公共 GitHub 提交——每天约 135,000 次。Cursor 的采用已被测量为将合并 PR 率提高了 39%。这些生产力提升只有在 agent 在正确约束内运作时才能实现。报告最高生产力提升的团队——Stripe 的工程成本在采用 Cursor 后明显下降——不是拥有最长指令文件的团队。而是拥有最准确指令文件的团队。

你的 CLAUDE.md 是一个产品

思维转变虽小但意义重大:停止把你的指令文件当作文档,开始把它当作一个有用户的产品。用户恰好是 AI agent,但它们和任何 API 消费者有同样的需求——清晰的契约、准确的 schema,以及没有意外。

保持简短。保持最新。偏好指针而非副本。永远不要让 LLM 做 linter 的工作。删除任何 agent 不需要被告知就会正确遵循的指令。

你写过的最具杠杆效应的文档不是覆盖所有内容的那个。而是恰好覆盖重要内容的那个,在它不再正确的那一刻就更新。

References:Let's stay in touch and Follow me for more thoughts and updates