跳到主要内容

机器可读的项目上下文:为什么你的 CLAUDE.md 比模型选择更重要

· 阅读需 9 分钟
Tian Pan
Software Engineer

大多数采用 AI 编程智能体的团队,都会把第一周花在争论使用哪个模型上。他们用人为设计的例子对 Opus、Sonnet 和 GPT-4o 进行基准测试,痴迷于排行榜,最终选出一个。然后他们花接下来三个月纳闷,为什么智能体一直在重建错误的抽象、忽视他们的测试策略,以及反复询问该用哪个包管理器。

问题不在模型。问题在上下文文件。

每款 AI 编程工具——Claude Code、Cursor、GitHub Copilot、Windsurf——都会在每次会话开始时读取一个项目专属的 Markdown 文件。这些文件有不同的名字:CLAUDE.md、.cursor/rules/.github/copilot-instructions.md、AGENTS.md。但它们的目的相同:告诉智能体那些无法通过阅读代码推断出来的信息。这个文件的质量如今比背后的模型更可靠地预测输出质量。然而大多数团队只写一次、写得很糟,然后再也不碰。

为何所有工具都殊途同归

这种趋同并非刻意为之,而是源于同一个实际约束:AI 编程智能体是无状态的。它们在会话之间没有记忆。每次开启新对话,模型都从零开始——它从未见过你的代码库,不知道你用的是 Yarn 而非 npm,也不知道 generated/ 目录是自动生成的、永远不应该手动编辑。

上下文文件就是这个问题的解决方案。把文件放在仓库根目录,工具在响应任何内容之前会自动读取它。智能体进场时就了解你的规则,而不是通过犯错来摸索规则。

Anthropic 在 Claude Code 中引入了 CLAUDE.md。Cursor 推出了 .cursorrules,后来将其弃用,改为 .cursor/rules/——一个由带 YAML 前置元数据的 .mdc 文件组成的目录,可将规则限定到特定文件模式。GitHub Copilot 使用 .github/copilot-instructions.md。OpenAI 于 2025 年 8 月发布了 AGENTS.md,明确将其定位为跨工具标准。到 2025 年 12 月,Linux 基金会新成立的 Agentic AI Foundation 已将 AGENTS.md 与 MCP 一同作为开放标准接纳,Anthropic、OpenAI、Google、Microsoft 和 AWS 均为联合创始人。

AGENTS.md 此后已被超过 60,000 个开源项目采用。同时运行多款工具的团队可以将 AGENTS.md 软链接到工具专属文件,避免维护多个各自漂移的版本。

这种模式现在已是基础设施,而非偏好选择。问题不在于是否要写一个——而在于你写的是否足够好。

研究实际揭示了什么

苏黎世联邦理工大学的一项研究得出了一个反直觉的发现:由 LLM 生成的上下文文件会损害智能体的性能。具体而言,自动生成的文件将任务成功率降低了 0.5%–2%,同时将推理成本增加了 20%–23%。原因在于:语言模型通过阅读代码库并总结所发现内容来生成上下文摘要。但智能体工具在执行任务时本就会进行这样的探索。自动生成的文件重复了智能体本会自行发现的内容,增加了 token 开销却没有增加任何信号。

人工编写的文件表现更好——在标准基准测试上提升约 4%——但仍然带来了大致相同的 19%–20% 的 token 开销。这意味着:上下文文件中的每个 token 都要付出代价,只有当内容确实无法从代码中推断出来时才值得。

这是编写有效项目上下文文件的核心约束。对每一行要问的问题是:"一位称职的工程师通过阅读代码能推断出这一点吗?"如果能,删掉它。如果不能,它才应该出现在文件里。

属于上下文文件的三类内容

无法推断的操作细节。 当你使用非标准工具链时,构建命令并不显而易见。如果你使用的是 Pixi 而非 pip、带自定义任务图的 Turborepo,或者封装了多步测试套件的 Makefile——请记录精确的命令及完整的参数。智能体会反复引用这些内容;将它们放在文件靠前的位置,可以减少在上下文变长时被忽略的可能。

看起来有问题的刻意架构决策。 每个代码库都有一些看起来像错误的模式,直到你理解它们存在的原因。违反了所有 SOLID 原则的单体事务处理器。在你理解读取路径之前看起来多余的数据反规范化。被刻意排除在类型检查之外的文件。如果没有解释,智能体会去"修复"这些问题。有了解释,它就能理解意图并不去碰它们。

明确的边界。 智能体永远不应该修改什么?自动生成的文件、锁文件、供应商目录、已经运行过的迁移文件。把这些写明确。三层模型效果很好:可以自由修改修改前先询问永不修改。智能体遵守明确约束的效果远好于遵守它们必须自行推断的隐式惯例。

什么不该放:代码库概览、架构摘要,以及任何读起来像文档的内容。智能体通过代码探索来发现这些——把它们放进上下文文件浪费 token,而且随着代码演进,往往几周内就会过时。

各格式的特殊注意事项

CLAUDE.md 在会话开始时被读取。它支持嵌套文件:你可以在子目录中放置 CLAUDE.md 文件,将指令限定在 monorepo 的特定部分。保持根文件简短——300 行以内是合理目标,100 行以内更好。如果某些工作流需要详细说明,以独立文件的形式引用,而不是把所有内容都内联进来。

Cursor rules.cursor/rules/ 中使用 YAML 前置元数据来控制规则何时生效。你可以将一条规则限定为仅在编辑 src/components/ 中的 TypeScript 文件时触发,这样智能体只会看到相关指令,而不是为每项任务加载所有内容。这比单一根文件更精准,但需要更严格的维护纪律,以防规则不断积累并相互矛盾。

AGENTS.md 设计为工具无关的。OpenAI 的规范优先考虑可执行命令、约束和非标准工具链。它明确指出代码库概览属于 README,而不是 AGENTS.md。

在所有格式中,一种失败模式反复出现:"中间迷失"问题。在长会话中,智能体对开始时加载的上下文越来越不在意。关键约束——那些违反后会造成真实损害的约束——应该出现在文件顶部,而不是埋在代码风格小节里。

会主动损害性能的反模式

大杂烩式文件。 团队随时间不断添加规则,却从不删除旧的。从 50 行开始的文件增长到 500 行。指令不断积累,有些相互矛盾,智能体开始忽视它们,因为同时满足所有规则已不可能。关于指令遵循的研究表明,前沿模型在 150–200 条指令左右开始出现合规性下降——而 Claude Code 自身的系统提示已经占用了约 50 个槽位。留给你的空间比大多数团队以为的要少。

风格指南。 上下文文件不能代替 linter。告诉智能体"始终使用单引号"或"优先用 const 而非 let",比在每个文件上运行 Prettier 和 ESLint 更慢、更不可靠。这些规则增加了噪音,占用了本可用于操作上下文的空间。

过时的结构文档。 "主要 API 在 src/api/v2/"今天是对的,六个月后就错了。随着代码库演进,仓库结构引用会变得误导性,而跟着过时地图走的智能体会自信地犯错。如果要记录结构,指向模式而非路径。

自动生成的内容。 关于这一点的研究结论是明确的。不要从代码库生成你的上下文文件。工具本就会读取代码库。你在为 token 付两次钱,却没有任何收益。

维护纪律

精心编写的上下文文件的失败模式是熵增。它们在项目开始时被认真编写,然后随着代码库变化,无人问津。六个月后,文件引用的是已被替换的包、已被重组的目录、已被放弃的测试策略。

把上下文文件当代码对待:它们属于版本控制,修改时需要审查,需要有人负责。有效的实践纪律是:当一个任务揭示智能体不知道它本该知道的事情时,这就是更新文件的信号。当构建流程改变时,文件随之改变。当一个架构决策被推翻时,文件中的解释随之更新。

反方向同样重要:当你向文件添加内容时,问一问已有的内容是否可以删除。大多数上下文文件应该随着时间推移而缩短,因为团队会逐渐理解哪些内容真正有价值,哪些是出于防御性考虑而添加却从未需要过的。

维护良好的文件带来的回报

在一个准确、简洁的上下文文件上投入 30 分钟,会在每次会话中产生回报。维护这类文件的团队报告说,智能体不再犯同类错误——错误的包管理器、错误的测试命令、被"修复"的本属刻意设计的抽象。智能体的第一次响应校准更准确,这意味着更少的纠正循环,意味着任务完成得更快。

模型的选择在边际上仍然重要。但任何模型在你的代码库中能做什么的上限,取决于它对你的代码库了解多少。平庸的上下文文件配上优秀的模型,产出的结果不如优秀的上下文文件配上一个不错的模型。

所有工具都殊途同归于这种模式,因为它有效。执行差距在于把它当作配置产物,而不是一等工程资产来对待。

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