跳转到内容

CLAUDE.md 编写哲学

Claude Code 像一个刚入职的新同事。他很聪明,读过很多书,但对你这个项目一无所知——他不知道文件放哪、命名怎么约定、什么时候该提交代码、什么时候该收工写日报。

CLAUDE.md 就是你给这位新同事的入职手册。写得好,他第一天就能干活。写得不好,他天天犯低级错误,你天天给他擦屁股。

这篇文章不教你 CLAUDE.md 的语法怎么写(那部分参考配置文档),而是讲一个更根本的问题:怎么让这本入职手册越写越好,而不是写一次就落灰

很多人第一次用 Claude Code 时写了一个 CLAUDE.md,然后从此不再碰它。几周后 Claude 开始犯奇怪的错误,用户抱怨“Claude 怎么越来越笨了”,其实不是 Claude 变笨了,是入职手册过时了。

把 CLAUDE.md 想象成一个活文档,而不是一个写完就归档的规范书。它的底线原则只有一条:

Claude 每犯一次错,就往 CLAUDE.md 里加一条规则。

这个模式来自 Boris Cherny(Claude Code 团队的核心成员)。他在一次访谈中说过:他自己项目的 CLAUDE.md 里每一条规则,背后都是一次真实的翻车。Claude 做了不该做的事,他就加上一句话让它以后别再做。

这个心智模型之所以管用,是因为它完全改变了你写规则的方式:

  • 不是在“我想让 Claude 怎么干活”,而是在“上次它怎么搞砸了,这次把它堵上”
  • 规则不需要完美覆盖所有情况,只需要覆盖已经发生过的真实错误
  • 每一条规则都有明确的“案发现场”,删掉它就等于放那个 bug 回来

来看一个真实的 CLAUDE.md 片段。下面这些规则来自 Jason(零基础编程学习者)在持续数月的 intern-journal 项目中逐步积累,每条规则背后都是一次具体的翻车事件。

错误场景:Claude 被要求写一篇学习笔记。它没检查 learnings/ 目录,直接新建了一个文件。写完后用户发现同一个主题已经有一篇笔记了。

规则

不重复创建已有学习笔记 → 处理请求前先 grep learnings/ problems/

这条规则很短,但它做了一件事:把一个“检查已有文件”的动作变成了 Claude 的强制习惯。加了这条之后,Claude 再也没有创建过重复笔记。

错误场景:Jason 发现自己在终端里读 markdown 文件很痛苦——没有格式高亮、没有目录导航、长文件要不停翻页。

规则

用户阅读优先开 html(open path/foo.html);agent 自己读 md

这条规则改变了 Claude 的交付方式:每当用户想看一个文件,Claude 不是展示 md 原文,而是渲染成 HTML 在浏览器里打开。看起来只是简单一行,但它解决了“终端里读文档难受”这个根本体验问题。

错误场景:用户让 Claude 做一次涉及多个文件的架构重构。Claude 直接动手,改到一半发现方向错了,前面几个小时的工作全废。

规则

多文件改动 / 架构级重构 → 必须先 EnterPlanMode

这条规则的“堵口”效果很明显:以后任何涉及多文件的大改动,Claude 都会先出计划,用户确认后再动手。一次返工就能让这条规则稳如磐石。

错误场景:Claude 在优化一篇笔记的格式时,“顺便”改动了正文内容。用户发现曾经用自己的话写下的理解被 Claude 重写了,丢失了原始的表达。

规则

绝不修改已有 learnings/ 笔记正文;front-matter / 链接 / 结构可改

这条规则划了一条清晰的线:哪些可以改(元数据、链接、结构),哪些绝对不能碰(正文内容)。边界越清晰,Claude 越不容易越界。

案例 5:不要只改 HTML 不更新 Markdown

Section titled “案例 5:不要只改 HTML 不更新 Markdown”

错误场景:Claude 在 HTML 渲染结果里直接修改了内容,但对应的 markdown 源文件没动。下次重新渲染时,修改全丢了。

规则

绝不 在 html 改完后让 md "对齐";md 是源真相

一句话讲清楚了单向派生关系:markdown 是源头,HTML 是衍生品。永远不会发生“谁改谁”的混乱。

错误场景:Claude 读文件时喜欢用 cat 命令。但 cat 不支持图片,遇到 PDF 直接乱码,而且 cat | head 在 pipefail 模式下会报假错。

规则(全局 CLAUDE.md):

读本地文件用 Read,不用 Bash cat/head/tail

这条来自全局 CLAUDE.md,对所有项目生效。一旦写进去,所有项目的 Claude 都不会再用 cat 读文件——一劳永逸。

这些案例有一个共同点:每条规则都在说“不要做什么”,而不是“要做什么”。这是因为“要做什么”容易写得模糊,而“不要做什么”是从具体错误中总结出来,边界清晰,Claude 执行起来也更准确。

CLAUDE.md 用久了会自然变长。有些早期加的规则可能已经不再需要(项目结构变了、Claude 自己变聪明了),需要定期清理。

清理方法很简单:对每一条规则问一个问题。

如果删掉这行,Claude 会犯什么错?

如果你能立刻说出一个具体的、可复现的错误,这条规则就留着。如果你想了 10 秒还没想出来它到底在防什么,那就删掉它。

这个测试很管用,因为:

  • 防止规则腐烂:原来那条场景早就不会发生了(比如项目已经弃用了某个目录),规则却还在那占位置
  • 防止迷信规则:加进去的时候觉得很重要,但从来没问过“它真的挡过什么吗”
  • 保持 CLAUDE.md 精瘦:每一行都有成本——太长了 Claude 会“跳读”,真正重要的规则反而被淹没

实际做的时候不需要太形式化。每两周、或者每次发现 CLAUDE.md 超过 200 行的时候,花 5 分钟扫一遍,删掉答不出“防什么错”的规则就行。

最常见的失败模式长这样:

  1. 第一天用 Claude Code,兴奋地写了一个 CLAUDE.md
  2. 用了一周,Claude 犯了很多小错误
  3. 你觉得“也不算大问题,懒得改文件了”
  4. 一个月后,Claude 还在犯同样的错误,你开始觉得“Claude 不靠谱”

问题不在 Claude,在你。在当前的会话模型下,Claude 不会自动从错误中学习——它依赖你写入 CLAUDE.md 或 Memory 的显式规则。你不写进去,它永远不知道。

解决方案不需要什么自律意志力。只需要一个微小的习惯:

每次对话结束前花 2 分钟,问自己:“今天 Claude 做错了什么?”

如果有,打开 CLAUDE.md,加一行。就这么简单。两分钟,一行字,下次就不会再犯。

不是每一次对话都能加出新规则——有些日子一切顺利。但当错误真的发生时,不要想着“下次再记”然后忘记。那个 moment 是写入 CLAUDE.md 的黄金窗口——你对错误的感受最具体,知道该用什么词堵住它。

CLAUDE.md 的长短有一个“适口”区间:

行数效果
< 20 行太模糊。Claude 不知道该怎么做细节,靠猜的。
20-100 行OK 但还可以更具体。适合非常简单的项目。
100-200 行甜点区。够具体覆盖所有高频场景,又短到 Claude 会认真读完。
200-500 行偏长。Claude 可能跳读靠后的内容。考虑拆分到子文件。
> 500 行太长。Claude 几乎不会逐条执行,等于没写。

Jason 的项目级 CLAUDE.md 当前超过百行,正好在甜点区内。它覆盖了:

  • 项目身份和用户画像(10 行)
  • 目录结构与模板约定(30 行)
  • 每日循环 / 周复盘 / 反馈管理工作流(30 行)
  • HTML 渲染规则(10 行)
  • 知识复用 + 质量门禁 / pre-commit hook(15 行)
  • Skill 协作矩阵(20 行)
  • 行为准则(15 行)

每一个板块都是“不够短就分不清,不够长就说不明”的平衡点。

如果你的 CLAUDE.md 已经超过 300 行,不要删内容——考虑拆出一个 CONTRIBUTING.md 或者把详细的工作流文档放到 docs/ 目录,CLAUDE.md 里只留引用链接。这样 Claude 平时读轻量版,遇到具体场景再去查详细文档。

Claude Code 支持两层 CLAUDE.md:

  1. 全局 CLAUDE.md~/.claude/CLAUDE.md)——对所有项目生效
  2. 项目级 CLAUDE.md(项目根目录的 CLAUDE.md)——只对这个项目生效

两层同时存在时,它们合并生效,不是覆盖。

这就像你在公司有两个主管:一个是公司级别的 CTO(全局规则),制定全公司都遵守的底线;一个是你的直属经理(项目规则),管你日常的具体工作。两人同时管你,但分工不同。

  • 不适合写入每个项目的通用规则
  • 跨项目一致的偏好(语言、风格、教学节奏)
  • 工具使用的固定策略(Read vs cat、前端测试用 Preview MCP)
  • 目录地图(哪些项目在哪)

Jason 的全局 CLAUDE.md 约 90 行,覆盖教学节奏、思考方式、输出风格、工具规约、行为底线。

  • 这个项目独有的目录结构
  • 项目特有的工作流(怎么写日报、怎么提交代码)
  • 项目专用的 Skill 协作规则
  • 质量门禁(pre-commit hook、命名规范)

全局的规则不在项目级重写。intern-journal/CLAUDE.md 里明确写着:

全局 CLAUDE.md 的强约束自动适用(教学节奏 / Read vs Bash cat / 不改 learnings 正文 / 不改 md 对齐 html / Session 切换提示)。本节只列项目特有规则。

这句话本身就是一条元规则:它告诉 Claude “那些全局的你别在项目文件里再找了,直接执行”。避免了同一个规则写在两个地方、改一处忘一处的维护陷阱。

两层架构的核心价值:全局写一次,所有项目受益。项目级只聚焦差异化。 如果你同时维护 3 个项目,不用在每个项目里重复“别用 cat 读文件”。

  • CLAUDE.md 太短不够具体:只有“你是 XX 项目的助手,请用中文回答”这句话。Claude 知道要讲中文,但不知道怎么处理文件、不知道什么时候提交、不知道遇到错误时该排查还是放弃。不如不写。
  • CLAUDE.md 太长 Claude 不读:超过 500 行的 CLAUDE.md,Claude 会像人读超长邮件一样——扫个开头和结尾,中间跳过。你放在第 400 行的关键规则等于没放。
  • 规则之间互相矛盾:一处写着“每次改完代码立刻提交”,另一处写着“多文件改动必须先出计划再动手”。Claude 面对矛盾指令时会随机选一条遵守,结果不可预测。定期检查是否有新加的规则跟旧规则冲突。
  • 从不更新导致过时:项目变了(换了新框架、改了目录结构),CLAUDE.md 没变。Claude 按旧规则操作,用户觉得“Claude 怎么变笨了”,其实是手册过期了。每次项目发生结构性变化时,给 CLAUDE.md 做一次对齐。

如果你不知道从哪里开始,这个最小模板能让你在 30 秒内上手:

# 项目名 — Claude 工作指南
## 项目身份
- 用途:[一句话说明]
- 技术栈:[列出关键技术]
## 行为准则
- [最重要的规则1]
- [最重要的规则2]
## 目录结构
- `src/` — 源代码
- `docs/` — 文档

先填上项目名和两条规则就够了。剩下的让错误来教你——Claude 每犯一次错,加一条规则,自然就长出一份好的 CLAUDE.md。

打开你自己的 CLAUDE.md,做两件事:

  1. 回想最近一周 Claude 犯过的错误,挑一个加一条规则。不用想这条规则是不是“完美”,先写上去。下次这个错误再发生时再迭代。
  2. 用“删掉这行 Claude 会犯什么错?”测试每一条已有规则。答不上来的,删掉。

如果你还没有 CLAUDE.md,现在就新建一个。不需要一开始就完美——先写你的项目叫什么、目录怎么组织的。规则可以在使用中慢慢长出来。