译:如何写好一个 CLAUDE.md
原文: https://www.humanlayer.dev/blog/writing-a-good-claude-md
作者: Kyle Mistele
译者: Gemini 2.5 Pro
注意:本文同样适用于 AGENTS.md,它是 CLAUDE.md 的开源等价物,用于像 OpenCode、Zed、Cursor 和 Codex 这类 agent 和工具框架。
原则:LLM 基本上是无状态的
LLM 是无状态的函数。当它们用于推理时,其权重是固定的,所以它们不会随着时间的推移而学习。模型对你代码库的全部了解,仅限于你输入给它的 token。
同样,像 Claude Code 这样的编程 agent 框架,通常需要你明确地管理 agent 的记忆。CLAUDE.md (或 AGENTS.md) 是唯一一个默认情况下会进入你与 agent 每一次对话 的文件。
这带来了三个重要的启示:
- 每次会话开始时,编程 agent 对你的代码库一无所知。
- 每次启动会话时,你都必须告诉 agent 所有关于代码库的重要信息。
CLAUDE.md是做这件事的最佳方式。
用 CLAUDE.md 帮助 Claude 熟悉你的代码库
由于 Claude 在每次会话开始时对你的代码库一无所知,你应该使用 CLAUDE.md 来引导它熟悉你的代码库。从高层次来看,这应该包括:
- WHAT (是什么):告诉 Claude 技术栈、项目结构。给 Claude 一份代码库的地图。这在 monorepo 中尤其重要!告诉 Claude 有哪些应用,哪些是共享包,各自的用途是什么,这样它才知道去哪里找东西。
- WHY (为什么):告诉 Claude 项目的目的以及仓库里每个部分的作用。项目中不同部分的宗旨和功能是什么?
- HOW (怎么做):告诉 Claude 它应该如何在这个项目上工作。例如,你用
bun而不是node吗?你需要包含所有它能真正开展有意义工作所需的信息。Claude 如何验证自己的修改?它如何运行测试、类型检查和编译步骤?
但你做这件事的方式很重要!不要试图把 Claude 可能需要运行的每一个命令都塞进你的 CLAUDE.md 文件里——这样做的结果并不会太好。
Claude 常常会忽略 CLAUDE.md
无论你用的是哪个模型,你可能都会注意到 Claude 经常忽略你 CLAUDE.md 文件里的内容。
你可以自己验证这一点,方法是使用 ANTHROPIC_BASE_URL 在 Claude Code CLI 和 Anthropic API 之间放一个日志代理。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>
结果就是,如果 Claude 认为 CLAUDE.md 的内容与当前任务无关,它就会忽略这些内容。你在文件中放的那些不具有普遍适用性的信息越多,Claude 就越有可能忽略你在文件中给出的指令。
为什么 Anthropic 要加上这个? 很难说得准,但我们可以推测一下。我们见过的大多数 CLAUDE.md 文件都包含一堆并不普适的指令。很多用户把这个文件当作一种“热修复”手段,通过追加大量不一定普适的指令来修正他们不喜欢的行为。
我们只能猜测,Claude Code 团队发现,通过告诉 Claude 忽略那些不好的指令,整个工具框架实际上能产生更好的结果。
创建一个好的 CLAUDE.md 文件
以下部分将根据上下文工程最佳实践提供一些关于如何写好 CLAUDE.md 文件的建议。
效果因人而异。 并非所有这些规则都适用于每一种情况。和其他事情一样,你可以随时打破规则,只要……
- 你明白何时以及为何可以打破它们
- 你有一个充分的理由这样做
少即是多(指令越少越好)
把 Claude 可能需要运行的每一个命令,以及你的代码标准和风格指南都塞进 CLAUDE.md,这很诱人。但我们不建议这样做。
虽然这个话题还没有经过非常严谨的研究,但已有的一些研究表明:
- 前沿的“会思考的” LLM 大约能以合理的稳定性遵循 150-200 条指令。 小模型能关注的指令比大模型少,“不会思考的”模型比“会思考的”模型能关注的更少。
- 小模型的性能下降得更快、更严重。具体来说,随着指令数量的增加,小模型在遵循指令方面的表现倾向于呈指数级衰减,而更大型的前沿“会思考的”模型则呈线性衰减(见下图)。因此,我们不建议在多步骤任务或复杂的实施计划中使用小模型。
- LLM 倾向于关注提示词两端的指令:最开始的部分(Claude Code 系统消息和
CLAUDE.md),以及最末尾的部分(最近的用户消息)。 - 随着指令数量增加,遵循指令的质量会统一下降。这意味着,当你给 LLM 更多指令时,它不只是忽略新的(“在文件更下方”的)指令——它会开始统一地忽略所有指令。

我们对 Claude Code 工具框架的分析表明,Claude Code 的系统提示词本身就包含了约 50 条独立指令。这取决于你使用的模型,但这已经占了你的 agent 能可靠遵循的指令数量的近三分之一——而这还没算上规则、插件、技能或用户消息。
这意味着你的 CLAUDE.md 文件应该包含尽可能少的指令——理想情况下,只包含那些对你的任务普遍适用的指令。
CLAUDE.md 的长度与适用性
在其他条件相同的情况下,当 LLM 的上下文窗口充满了专注、相关的上下文时(包括示例、相关文件、工具调用和工具结果),它在任务上的表现会更好,而不是当它的上下文窗口里有很多无关上下文的时候。
因为 CLAUDE.md 会进入每一次会话,你应该确保其内容尽可能地普遍适用。
例如,避免包含关于如何构建新数据库模式的指令——当你处理其他不相关的事情时,这不仅无关紧要,还会分散模型的注意力!
在长度方面,“少即是多”的原则同样适用。虽然 Anthropic 没有官方建议你的 CLAUDE.md 文件应该有多长,但普遍的共识是少于 300 行是最好的,而且越短越好。
在 HumanLayer,我们的根 CLAUDE.md 文件不到六十行。
渐进式披露
写一个简洁的 CLAUDE.md 文件,又要涵盖你想让 Claude 知道的一切,这可能很有挑战性,尤其是在大型项目中。
为了解决这个问题,我们可以利用渐进式披露(Progressive Disclosure)的原则,来确保 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
然后,在你的 CLAUDE.md 文件里,你可以列出这些文件并附上简短的描述,然后指示 Claude 自己决定哪些文件是相关的(如果有的话),并在开始工作前阅读它们。或者,你也可以让 Claude 先把它想读的文件列出来给你批准,然后再去读。
优先使用指针,而不是复制内容。如果可能,不要在这些文件中包含代码片段——它们很快就会过时。相反,应该使用 file:line 这样的引用,来引导 Claude 去查看权威的上下文。
从概念上讲,这与 Claude Skills 的工作方式非常相似,尽管 skills 更侧重于工具的使用而不是指令。
Claude 不是一个昂贵的 Linter
我们看到人们放在 CLAUDE.md 文件里最常见的东西之一就是代码风格指南。永远不要派一个 LLM 去做 linter 的工作。与传统的 linter 和格式化工具相比,LLM 相对昂贵且极其缓慢。我们认为,只要有可能,你永远都应该使用确定性的工具。
代码风格指南不可避免地会给你的上下文窗口增加一堆指令和大多无关的代码片段,这会降低 LLM 的性能和指令遵循能力,并消耗你的上下文窗口空间。
LLM 是在上下文中学习的!如果你的代码遵循一套特定的风格指南或模式,你会发现,只要让 agent 在你的代码库里搜索几下(或者给它一份好的研究文档!),它就会倾向于遵循现有的代码模式和惯例,而无需你明确告知。
如果你对此非常执着,你甚至可以考虑设置一个 Claude Code 的 Stop 钩子,运行你的格式化工具和 linter,然后把错误呈现给 Claude 让它去修复。不要让 Claude 自己去发现格式问题。
加分项:使用一个能自动修复问题的 linter(我们喜欢用 Biome),并仔细调整你的规则,明确哪些问题可以安全地自动修复,以实现最大化(且安全)的覆盖范围。
你也可以创建一个斜杠命令 (Slash Command),其中包含你的代码指南,并让它指向版本控制中的变更,或者你的 git status 之类的。这样,你就可以把实现和格式化分开处理。最终,两者都能取得更好的结果。
不要使用 /init 或自动生成你的 CLAUDE.md
无论是 Claude Code 还是其他使用 OpenCode 的框架,都提供了自动生成 CLAUDE.md (或 AGENTS.md) 文件的方法。
因为 CLAUDE.md 会进入与 Claude Code 的每一次会话,所以它是整个工具框架中杠杆作用最高的点之一——无论好坏,都取决于你如何使用它。
一行烂代码就是一行烂代码。实施计划中一行烂指令可能会制造出大量烂代码。研究中一行对系统理解错误的描述,可能会导致计划中出现大量烂指令,并因此产生更多更多的烂代码。
但是 CLAUDE.md 文件会影响你工作流的每一个阶段以及它产出的每一件东西。因此,我们认为你应该花些时间,非常仔细地思考进入这个文件的每一行内容:

## 总结
CLAUDE.md用于帮助 Claude 熟悉你的代码库。它应该定义你项目的 WHY(为什么)、WHAT(是什么) 和 HOW(怎么做)。- 少即是多(指令越少越好)。虽然你不应该省略必要的指令,但你应该在文件中包含尽可能少的指令。
- 保持你的
CLAUDE.md内容简洁且普遍适用。 - 使用渐进式披露——不要告诉 Claude 你可能希望它知道的所有信息。相反,告诉它如何找到重要信息,这样它可以在需要时查找和使用,从而避免臃肿你的上下文窗口或增加指令数量。
- Claude 不是 linter。使用 linter 和代码格式化工具,并在必要时使用像 Hooks 和 Slash Commands 这样的其他功能。
CLAUDE.md是整个工具框架中杠杆作用最高的点,所以要避免自动生成它。你应该精心打造其内容以获得最佳效果。