详解如何编写有效的Claude.md项目指令文件,帮助程序员充分利用AI编程助手能力。Hacker News高热度讨论(748点290条评论)。
注意:本文同样适用于 AGENTS.md,这是 CLAUDE.md 针对开源 agent 和如 OpenCode、Zed、Cursor 与 Codex 等 harness 的对等物。
LLM 是无状态函数。它们的权重在推理时已被冻结,所以不会随时间学习。模型唯一了解你代码库的方式,就是你输入给它的 token。
类似地,像 Claude Code 这样的编码 agent harness 通常需要你显式地管理 agent 的内存。CLAUDE.md(或 AGENTS.md)是唯一一个默认会进入你与 agent 每一次对话的文件。
这有三个重要含义:
编码 agent 在每个会话开始时对你的代码库一无所知。
每次启动会话时,都必须告诉 agent 任何关于你代码库的重要信息。
CLAUDE.md 是进行这项工作的首选方式。
由于 Claude 在每个会话开始时对你的代码库一无所知,你应该使用 CLAUDE.md 将 Claude 引入你的代码库。从高层来看,这意味着它应该涵盖:
WHAT:告诉 Claude 关于技术、你的技术栈、项目结构。为 Claude 提供代码库地图。这在 monorepo 中尤其重要!告诉 Claude 有哪些应用、共享包是什么、每样东西的用途是什么,这样它就知道去哪里寻找东西。
WHY:告诉 Claude 项目的目的,以及仓库中所有内容在做什么。项目不同部分的目的和功能是什么?
HOW:告诉 Claude 它应该如何在项目上工作。例如,你使用 bun 而不是 node?你想包括它在项目上进行有意义工作所需的所有信息。Claude 如何验证 Claude 的改动?它如何运行测试、类型检查和编译步骤?
但你这样做的方式很重要!不要试图在你的 CLAUDE.md 文件中堆砌 Claude 可能需要运行的每个命令 - 你会得到次优的结果。
无论你使用哪个模型,你可能会注意到 Claude 经常忽视你 CLAUDE.md 文件的内容。
你可以通过在 claude code CLI 和 Anthropic API 之间使用 ANTHROPIC_BASE_URL 放置日志代理来自己调查这一点。Claude code 在发送给 agent 的用户消息中,用你的 CLAUDE.md 文件注入以下系统提醒:
<system-reminder>
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>
<system-reminder>
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>
因此,如果 Claude 认为你的 CLAUDE.md 内容与其当前任务不相关,它就会忽略这些内容。你在文件中拥有的不能普遍适用于你让它处理的任务的信息越多,Claude 就越有可能忽视你文件中的指令。
Anthropic 为什么添加这个?很难确切地说,但我们可以做一些推测。我们遇到的大多数 CLAUDE.md 文件在文件中包含一堆不能广泛适用的指令。许多用户将文件视为一种方式,通过附加许多不一定能广泛适用的指令来添加"热修复"以解决他们不喜欢的行为。
我们只能假设 Claude Code 团队发现,通过告诉 Claude 忽视坏的指令,harness 实际上产生了更好的结果。
下面的部分提供了一些关于如何遵循上下文工程最佳实践编写好的 CLAUDE.md 文件的建议。
你的结果可能会有所不同。这些规则不一定对每个设置都是最优的。像其他任何事情一样,一旦你...就可以自由地打破规则:
你理解什么时候以及为什么可以打破它们
你有很好的理由这样做
把 Claude 可能需要运行的每一个命令,以及你的代码标准和风格指南都塞进 CLAUDE.md 可能很诱人。我们建议不要这样做。
虽然这个话题还没有被非常严格地研究过,但已经进行了一些研究表明以下几点:
前沿思考 LLM 能以合理的一致性跟随约 150-200 条指令。较小的模型能处理的指令比较大的模型少,非思考模型能处理的指令比思考模型少。
较小的模型变得糟糕得快得多。具体来说,随着指令数量的增加,较小的模型在遵循指令性能上往往表现出指数衰减,而较大的前沿思考模型表现出线性衰减(见下文)。因此,我们建议不要对多步骤任务或复杂的实现计划使用较小的模型。
LLM 倾向于关注提示外围的指令:在最开始(Claude Code 系统消息和 CLAUDE.md)和最后(最近的用户消息)。
随着指令数量增加,遵循指令的质量均匀下降。这意味着当你给 LLM 更多指令时,它不只是忽视新指令("文件中更靠下的")- 它开始均匀地忽视所有指令。
我们对 Claude Code harness 的分析表明,Claude Code 的系统提示包含约 50 条单独指令。根据你使用的模型,这几乎是你的 agent 已经能可靠遵循的指令的三分之一 - 这还没有计入规则、插件、技能或用户消息。
这意味着你的 CLAUDE.md 文件应该包含尽可能少的指令 - 最好只是那些对你的任务普遍适用的指令。
在其他条件相同的情况下,当 LLM 的上下文窗口充满了专注、相关的上下文(包括示例、相关文件、工具调用和工具结果)时,与上下文窗口有大量无关上下文时相比,LLM 在任务上的表现会更好。
由于 CLAUDE.md 进入每一个会话,你应该确保其内容尽可能普遍适用。
例如,避免包括(例如)如何构建新数据库架构的指令 - 当你在处理不相关的其他事情时,这不会很重要,也会分散模型的注意力!
从长度上讲,少即是多的原则也适用。虽然 Anthropic 没有关于你的 CLAUDE.md 文件应该有多长的官方建议,但普遍共识是 < 300 行是最好的,更短更好。
在 HumanLayer,我们的根 CLAUDE.md 文件少于 60 行。
编写一个简洁的 CLAUDE.md 文件,覆盖你想让 Claude 知道的一切可能很具有挑战性,特别是在较大的项目中。
为了解决这个问题,我们可以利用渐进式披露原则,确保 Claude 仅在需要时才看到特定于任务或项目的指令。
与其在你的 CLAUDE.md 文件中包括所有关于构建项目、运行测试、代码约定或其他重要上下文的不同指令,我们建议在项目中某处的单独 markdown 文件中保留特定于任务的指令,文件名具有自描述性。
agent_docs/
|- building_the_project.md
|- running_tests.md
|- code_conventions.md
|- service_architecture.md
|- database_schema.md
|- service_communication_patterns.md
agent_docs/
|- building_the_project.md
|- running_tests.md
|- code_conventions.md
|- service_architecture.md
|- database_schema.md
|- service_communication_patterns.md
然后,在你的 CLAUDE.md 文件中,你可以包括这些文件的列表,以及每个文件的简要描述,并指示 Claude 决定哪些(如果有的话)是相关的,在开始工作之前阅读它们。或者,要求 Claude 在读之前先向你提交它想要阅读的文件以供批准。
倾向于指针而不是副本。如果可能,不要在这些文件中包括代码片段 - 它们会很快过时。相反,包括 file:line 引用以指向 Claude 权威上下文。
从概念上讲,这与 Claude Skills 的预期工作方式非常相似,尽管 skills 更多地关注工具使用而不是指令。
我们看到人们在他们的 CLAUDE.md 文件中放入的最常见的事情之一是代码风格指南。永远不要派一个 LLM 去做 linter 的工作。与传统的 linter 和格式化工具相比,LLM 的成本相对较高,速度慢得令人难以置信。我们认为你应该尽可能使用确定性工具。
代码风格指南必然会在你的上下文窗口中添加一堆指令和大多数无关的代码片段,降低你的 LLM 的性能和指令遵循,并消耗你的上下文窗口。
LLM 是上下文中的学习者!如果你的代码遵循某组风格指南或模式,你应该发现,通过对你的代码库进行几次搜索(或一份好的研究文档!),你的 agent 应该倾向于不被告知而遵循现有的代码模式和约定。
如果你对此感到非常强烈,你甚至可能考虑设置一个 Claude Code Stop hook,运行你的格式化程序和 linter,并向 Claude 呈现错误以供其修复。不要让 Claude 自己找格式化问题。
额外加分:使用能够自动修复问题的 linter(我们喜欢 Biome),并仔细调整你关于什么可以安全自动修复的规则,以获得最大的(安全的)覆盖。
你也可以创建一个斜杠命令,包括你的代码指南,并指向 Claude 版本控制中的更改,或你的 git 状态,或类似的东西。这样,你可以分别处理实现和格式化。因此,你会看到两者的更好结果。
Claude Code 和其他带有 OpenCode 的 harness 都提供了自动生成 CLAUDE.md 文件(或 AGENTS.md)的方法。
因为 CLAUDE.md 进入每个与 Claude code 的会话,它是 harness 最高杠杆点之一 - 无论好坏,取决于你如何使用它。
坏的一行代码就是坏的一行代码。一个实现计划的坏一行有可能创建很多坏的代码行。一个研究的坏一行误解了系统如何工作可能导致计划中很多坏的行,因此导致很多更坏的代码行作为结果。
但 CLAUDE.md 文件影响你的工作流的每个阶段和由其产生的每个工件。因此,我们认为你应该花一些时间仔细思考进入其中的每一行:
CLAUDE.md 用于将 Claude 引入你的代码库。它应该定义你的项目的 WHY、WHAT 和 HOW。
更少的(指令)是更好的。虽然你不应该省略必要的指令,但你应该在文件中包括尽可能少的指令。
保持你的 CLAUDE.md 内容简洁和普遍适用。
使用渐进式披露 - 不要告诉 Claude 你可能想让它知道的所有信息。相反,告诉它如何找到重要信息,以便它可以找到并使用它,但仅当需要时避免膨胀你的上下文窗口或指令数。
Claude 不是一个 linter。使用 linter 和代码格式化工具,并根据需要使用其他功能如 Hook 和斜杠命令。
CLAUDE.md 是 harness 最高杠杆点,所以避免自动生成它。你应该仔细制作其内容以获得最佳结果。