Claude Code:高效编写 CLAUDE.md

系列导航

  1. 安装与配置
  2. 入门使用
  3. 高级功能
  4. 旁门左道
  5. 高效编写 CLAUDE.md(本文)
  6. 自定义命令
  7. Hooks
  8. Agents(子代理)
  9. MCP
  10. Plan 模式
  11. Skills
  12. 头脑风暴(Superpowers)
  13. Ralph Loop 全天候运行

本文同样适用于 AGENTS.md——这是 CLAUDE.md 的开源等价物,适用于 OpenCode、Zed、Cursor 和 Codex 等 Agent。

1. 核心原则:LLM 是无状态的

LLM 本质上是无状态函数。模型权重在推理时已经冻结,不会随时间学习。模型对你代码库的了解,完全取决于你输入的 token

同样,Claude Code 这类编程 Agent 通常需要你显式管理 Agent 的记忆。CLAUDE.md(或 AGENTS.md)是唯一一个默认会注入到每次对话中的文件

这带来三个重要启示:

  1. 编程 Agent 在每次会话开始时对你的代码库一无所知
  2. 每次启动会话时,必须告诉 Agent 所有重要信息
  3. CLAUDE.md 是实现这一点的首选方式

2. CLAUDE.md 是 Claude 的”入职培训”

既然 Claude 在每次会话开始时对你的代码库一无所知,你应该用 CLAUDE.md 来让 Claude “入职”。从高层次来说,它应该涵盖:

维度 内容
WHAT(是什么) 告诉 Claude 技术栈、项目结构。给 Claude 一张代码库地图。这在 monorepo 中尤其重要!告诉 Claude 有哪些应用、哪些共享包、各自的用途
WHY(为什么) 告诉 Claude 项目的目的,仓库中各部分在做什么
HOW(怎么做) 告诉 Claude 如何在项目上工作。比如你用 bun 而不是 node?包含它完成实际工作所需的所有信息。Claude 如何验证修改?如何运行测试、类型检查和编译?

但方式很重要! 不要试图把 Claude 可能需要运行的每个命令都塞进 CLAUDE.md 文件——这会导致次优结果。

3. Claude 经常忽略 CLAUDE.md

无论你使用哪个模型,你可能会注意到 Claude 经常忽略 CLAUDE.md 文件的内容

你可以通过在 Claude Code CLI 和 Anthropic API 之间放置日志代理来自己调查。Claude Code 在用户消息中注入了以下系统提醒:

1
2
3
4
<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 忽略这些糟糕的指令,整体效果反而更好。

4. 如何编写好的 CLAUDE.md

4.1 少即是多

把所有 Claude 可能需要运行的命令、代码标准和风格指南都塞进 CLAUDE.md 很诱人。我们不建议这样做。

虽然这个话题还没有经过非常严格的研究,但一些研究表明:

  1. 前沿思维型 LLM 可以相当一致地遵循约 150-200 条指令。较小的模型能处理的指令比大模型少,非思维型模型比思维型模型能处理的更少
  2. 较小的模型退化得更快、更严重。随着指令数量增加,较小模型的指令遵循性能呈指数衰减,而较大的前沿思维型模型呈线性衰减
  3. LLM 偏向于提示词边缘的指令:最开头(Claude Code 系统消息和 CLAUDE.md)和最末尾(最近的用户消息)
  4. 随着指令数量增加,指令遵循质量均匀下降。这意味着当你给 LLM 更多指令时,它不是简单地忽略较新的指令——而是开始均匀地忽略所有指令

指令遵循研究

我们对 Claude Code 的分析表明,Claude Code 的系统提示包含约 50 条单独指令

根据你使用的模型,这已经占了 Agent 能可靠遵循的指令数量的近三分之一——这还没算 rules、plugins、skills 或用户消息。

这意味着你的 CLAUDE.md 文件应该包含尽可能少的指令——理想情况下只包含对你的任务普遍适用的指令。

4.2 文件长度和适用性

在其他条件相同的情况下,当 LLM 的上下文窗口充满聚焦、相关的上下文(包括示例、相关文件、工具调用和工具结果)时,它在任务上的表现会更好。

由于 CLAUDE.md 会进入每一个会话,你应该确保其内容尽可能具有普遍适用性。

例如,避免包含关于如何构建新数据库 schema 的指令——当你在做不相关的事情时,这无关紧要,反而会分散模型注意力!

长度方面,少即是多原则同样适用。虽然 Anthropic 没有官方建议 CLAUDE.md 文件应该多长,但普遍共识是少于 300 行最好,越短越好

在 HumanLayer,我们的根 CLAUDE.md 文件不到 60 行

4.3 渐进式披露

编写一个涵盖所有你希望 Claude 知道的内容的简洁 CLAUDE.md 文件可能很有挑战性,尤其是在大型项目中。

为了解决这个问题,我们可以利用渐进式披露原则,确保 Claude 只在需要时才看到特定于任务或项目的指令。

与其把所有关于构建项目、运行测试、代码规范或其他重要上下文的指令都放在 CLAUDE.md 文件中,我们建议把特定任务的指令保存在项目中某处的独立 markdown 文件中,使用自描述的名称。

例如:

1
2
3
4
5
6
7
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 决定哪些(如果有的话)是相关的,在开始工作前阅读它们。

优先使用指针而非复制。如果可能,不要在这些文件中包含代码片段——它们会很快过时。相反,包含 file:line 引用来指向 Claude 获取权威上下文。

从概念上讲,这与 Claude Skills 的工作方式非常相似,尽管 skills 更专注于工具使用而非指令。

4.4 Claude 不是 Linter

我们看到人们在 CLAUDE.md 文件中最常放的东西之一是代码风格指南。永远不要派 LLM 去做 linter 的工作。与传统的 linter 和格式化工具相比,LLM 相对昂贵且极其缓慢。我们认为你应该尽可能使用确定性工具

代码风格指南不可避免地会在你的上下文窗口中添加一堆指令和大部分不相关的代码片段,降低 LLM 的性能和指令遵循能力,并占用你的上下文窗口。

LLM 是上下文学习者!如果你的代码遵循某套风格指南或模式,你会发现有了对代码库的几次搜索(或一份好的研究文档!),你的 Agent 应该倾向于遵循现有的代码模式和规范,而无需被告知。

如果你对此感觉非常强烈,你甚至可以考虑设置一个 Claude Code Stop hook,运行你的格式化工具和 linter,并把错误呈现给 Claude 来修复。不要让 Claude 自己去找格式问题。

加分项:使用可以自动修复问题的 linter(我们喜欢 Biome),并仔细调整关于什么可以安全自动修复的规则,以获得最大(安全)覆盖率。

你也可以创建一个 Slash Command,包含你的代码指南,并指向版本控制中的更改、或你的 git status 等。这样,你可以分开处理实现和格式化。两者的结果都会更好

4.5 不要使用 /init 或自动生成 CLAUDE.md

Claude Code 和其他带 OpenCode 的工具都提供了自动生成 CLAUDE.md 文件(或 AGENTS.md)的方式。

因为 CLAUDE.md 会进入每一个与 Claude Code 的会话,它是整个工具链中杠杆最高的点之一——无论好坏,取决于你如何使用它。

一行糟糕的代码就是一行糟糕的代码。实现计划中一行糟糕的内容有可能创造大量糟糕的代码。研究中一行误解系统工作方式的内容有可能导致计划中大量糟糕的行,因此导致更多糟糕的代码。

CLAUDE.md 文件影响你工作流程的每一个阶段以及由此产生的每一个产出物。因此,我们认为你应该花时间仔细思考其中的每一行

杠杆效应

5. 总结

  1. CLAUDE.md 是用来让 Claude “入职”你的代码库的。它应该定义项目的 WHYWHATHOW
  2. 少即是多。虽然不应该省略必要的指令,但应该在文件中包含尽可能少的指令
  3. 保持 CLAUDE.md 的内容简洁且普遍适用
  4. 使用渐进式披露——不要告诉 Claude 所有你可能希望它知道的信息。相反,告诉它如何找到重要信息,这样它可以在需要时找到并使用,避免膨胀你的上下文窗口或指令数量
  5. Claude 不是 linter。使用 linter 和代码格式化工具,并根据需要使用 HooksSlash Commands 等其他功能
  6. CLAUDE.md 是整个工具链中杠杆最高的点,所以避免自动生成它。你应该仔细打造其内容以获得最佳结果