Claude-Code-实践指南(二):编写操作规范
当把 Claude Code 用到一个新项目时,期待满满地让它帮忙写代码,结果发现我们可能反复在和它强调一些无聊的问题,比如写代码用什么规范,和后端怎么通信,写完代码要加测试用例。强调完,它当时记住了,但很快又会再犯。上下文一压缩,很多要求都会忘记。
一个下午,感觉用 Claude Code 写代码,还不如自己动手写。
其实,是因为你少做了一件事:把规矩写下来,写进 CLAUDE.md。
每天都要重新培训的米其林大厨
想象你后厨的米其林大厨有个怪毛病:每天早上醒来,他对厨房的一切都丧失记忆。不知道调料架在哪,不知道你们家不吃辣,甚至连刀在哪都得你重新指一遍。
幸运的是,你可以准备一份”厨房操作规范”。每天大厨到岗,先读完规范再干活。规范里写了口味偏好、食材禁忌、操作规矩等。写一次,天天生效。
CLAUDE.md,就是这份规范。它是一个普通的 Markdown 文件,你可以像写便签一样用中文(或英文)写下你想让 Claude 记住的所有规则。
虽然 CLAUDE.md 写一次就永久生效,但写得不准反而会误导 Claude,所以写得精比写得多更重要。
为什么需要 CLAUDE.md
Claude Code 的每次会话都是无状态的。你敲下 claude 回车的那一刻,是一个全新的”空白大脑”在等你。你之前教过它什么?统统不记得了。
CLAUDE.md 会在每次会话启动时自动加载到系统提示词(System Prompt) 中。这就好比大厨每天到岗第一件事就是读你的厨房规范,不读不开火。
这里有一个很容易被忽视的关键机制:即使在会话中使用了 /compact 压缩上下文,CLAUDE.md 也会从磁盘重新读取并重新注入。也就是说,它里面的规则永远不会因为上下文压缩而丢失。
对比一下就明白了:你在对话中口头告诉 Claude “我们项目用 2 空格缩进”,一旦上下文被压缩,这条规则可能就没了。但如果你把它写进 CLAUDE.md,压缩之后它会自动回来。
口头指令是沙上建塔,CLAUDE.md 才是刻石为碑。
不过,CLAUDE.md 只能记住静态规则,你在上一轮会话中讨论过的设计决策、踩过的坑,它会忘记。
社区有一个叫 claude-mem 的工具,用 Hooks 和向量数据库把跨会话的对话记忆持久化下来,算是从另一个角度补了这个缺口。第六篇会简单介绍。
Claude 怎么找到你的厨房规范:层级发现系统
Claude Code 会从当前目录向上查找,并合并加载 多个位置的 CLAUDE.md。这就好比你家厨房有一份总规范,每个灶台还能贴自己的小纸条,大厨会把所有纸条都看一遍,然后综合执行。
| 层级 | 文件路径 | 是否提交 Git | 用途 |
|---|---|---|---|
| 全局 | ~/.claude/CLAUDE.md | 不提交 | 个人偏好约定 |
| 项目根目录 | ./CLAUDE.md | 提交 | 团队共享的项目核心规则 |
| 本地覆盖 | ./CLAUDE.local.md | 自动 ignore | 个人的覆盖或调试配置 |
| 父目录 | 从 cwd 向上查找到 / | 不推荐 | Monorepo 场景下根目录与子包同时生效 |
| 子目录 | ./subdir/CLAUDE.md | 按需 | 当 Claude 访问该子目录文件时才加载 |
所谓 Monorepo,就是单个代码仓库包含多个独立项目,比如一个仓库里有 frontend/、backend/、shared/。在这种结构下,向上查找机制可以让根目录的规则对所有子包生效,而每个子包又可以有自己的补充规则。
还有一个细节值得注意:子目录的 CLAUDE.md 是按需加载 的。只有当 Claude 实际读取某个子目录下的文件时,才会加载该目录中的 CLAUDE.md。这个设计挺聪明,省 Token。
用 /init 快速生成第一版规范
如果你面对的是一个已有项目,不想从零写起,可以在项目根目录运行 /init(进入 Claude 会话后输入即可)。Claude 会自动扫描你的代码库,然后生成一份初始 CLAUDE.md,通常包含:
- 项目概述(从 README 或 package.json 推测)
- 常用构建和测试命令
- 明显的代码规范线索
不过,自动生成的东西难免有不准确的地方。生成之后一定要手动编辑,删掉猜错的,补上遗漏的。/init 给你的是毛坯房,精装修得自己来。
如果已经有一份 CLAUDE.md 想重新生成,可以用 /init --force 覆盖现有版本。
怎样写出一份真正有用的 CLAUDE.md
首先是硬约束:保持 200 行以内 。太长了 Claude 会忽略尾部内容,这不是偷懒,是注意力机制的问题,就像你给大厨贴了一百条纸条,他大概率只记得前二十条。
其次是内容选择:只放对工作流有持续影响 的信息。API 文档、教程之类的参考材料不要放进去,那是在浪费每一条都会被读到的宝贵行数。
最后是结构:用清晰的 Markdown 标题分层。
一个 Python 项目的 CLAUDE.md 大概长这样:
1 | # Project: FastAPI Backend |
虽然模板看着整齐,但实际写的时候不必追求面面俱到,后边使用 Claude 中最常出错的环节,才是最值得写进备注的。如果你发现自己反复纠正 Claude 同一个问题,那这个问题就该进 CLAUDE.md 了。
菜谱太长怎么办:.claude/rules/ 目录拆分
当项目规模增长,CLAUDE.md 变得臃肿,200 行装不下怎么办?可以把规则拆分到 .claude/rules/ 目录下。
这个目录下可以放多个 Markdown 文件,分为两种:
普通规则文件 (没有 path: 字段):会话启动时加载,效果等同于写在 CLAUDE.md 里。
路径限定规则文件 (包含 path: YAML 字段):只有当 Claude 读取匹配路径的文件时才加载。这是省 Token 的大杀器,前端规则只在读前端代码时才生效,后端规则只在读后端代码时才生效。
比如你可以在 .claude/rules/frontend.md 里这样写:
1 | path: src/frontend/** |
path: 字段和正文之间用 --- 分隔。上面那行声明了这条规则只在 src/frontend/ 目录下生效,下面的正文就是规则本身。简洁,克制,该出场时再出场。
CLAUDE.md 里的隐藏语法
到现在为止,我们一直把 CLAUDE.md 当成纯文本在用,写什么就注入什么。但其实它有几条不算显眼的专属语法,知道了能省不少事。
用 @ 导入其他文件
CLAUDE.md 里可以写 @path/to/file,Claude Code 在加载时会把这个文件的内容展开并注入。就像你在菜谱里夹了一张纸条:”详细步骤见附录 A”,大厨会自动翻到附录 A 去看。
1 | # 项目规范 |
几个要点:路径可以是相对路径(相对于写 @ 的那个文件所在目录),也可以是绝对路径;导入可以嵌套,但最多 5 层,防止无限递归。
一个容易踩的坑:@ 导入并不能省 Token。被导入的文件内容照样会完整注入上下文,所以它解决的是组织问题,不是成本问题。你把 500 行的 API 文档 @ 进来,大厨照样得逐字读完。
HTML 注释是给人看的,不是给 Claude 看的
如果你在 CLAUDE.md 里写了 HTML 注释,比如 <!-- 这段是给人看的维护笔记 -->,Claude Code 在注入上下文之前会把这些注释剥掉。也就是说,注释里的内容 Claude 永远看不到,也不消耗 Token。
所以,你可以在 CLAUDE.md 里留下为什么这么写的备忘给自己看,而不浪费 Claude 的注意力。不过要注意,注释写在代码块里面是不会被剥掉的,因为代码块里的内容是字面量。
.claude/rules/ 的路径限定字段
前面已经讲了 path: 字段的基本用法,再补充一个细节:path: 支持多个 glob 模式,用 YAML 列表写法。
1 | --- |
当 Claude 读取匹配这些路径的文件时,这条规则才会被加载。不匹配就不加载,一分 Token 都不多花。
CLAUDE.md 的加载顺序
所有这些语法背后,有一个加载顺序值得了解。Claude Code 从当前目录向上遍历,把沿途找到的 CLAUDE.md 全部拼接注入,根目录的在前、工作目录的在后。所以离你最近的那份 CLAUDE.md 是最后被读到的,权重也最高。
同一目录下,CLAUDE.local.md 排在 CLAUDE.md 后面,所以你个人的覆盖配置总是比团队共享的优先。子目录的 CLAUDE.md 是按需加载的,只有 Claude 实际访问了那个目录的文件,才会读取。
还有一个关键细节:使用 /compact 压缩上下文之后,只有项目根目录的 CLAUDE.md 会从磁盘重新读取并重新注入,子目录的不会。所以那些最不能丢的规则,一定要放在根目录的 CLAUDE.md 里。
CLAUDE.md 和 AGENTS.md 是什么关系
如果你在 GitHub 上逛过开源项目,可能见过一个叫 AGENTS.md 的文件。它和 CLAUDE.md 长得像、用途像,但不是一个东西。
AGENTS.md 是 GitHub 定义的规范,给 GitHub Copilot 的 Agent 用的;CLAUDE.md 是 Anthropic 定义的规范,给 Claude Code 用的。两家的 Agent 都需要一份”操作规范”,但各自只认自家的文件名。
它们都是放在仓库里的 Markdown 文件,都是给 AI Agent 注入项目上下文和规则的。
AGENTS.md 正在演变成通用的 AI Agent 配置文件标准,不只是 Copilot,Cursor、Codex 等 AI Agent 也开始支持,它也成为 Linux 基金会开始支持的标准。
不过,如果你只用 Claude Code,使用 CLAUDE.md 更值得推荐,它有更强大的专属内置指令。
两个都有的仓库怎么办
如果你的团队既用 Claude Code 又用 Copilot,两份规范维护起来会头疼吗?倒也不必。推荐的做法是用 CLAUDE.md 导入 AGENTS.md:
1 | @AGENTS.md |
这样,两份规范共享同一份基础内容(写在 AGENTS.md 里),Claude Code 特有的规则追加在后面。Copilot 只读 AGENTS.md,Claude Code 先读 AGENTS.md 再读追加部分,互不干扰,也不用维护两份重复的规范。
如果你只用 Claude Code,直接写 CLAUDE.md 就好,不必创建 AGENTS.md。反过来,只用 Copilot 的话写 AGENTS.md 即可。只有两边都用的时候,才需要考虑这个桥接方案。
另外,你也可能看到过 CONTEXT.md,project-context.md 一类的工程文件,它们本质上具有相同的功能,只是用于不同的 agent。
希望将来这些大佬们能把这些协议性的东西规范一下,避免大家理解上的差异。
还有一点:运行 /init 时,如果仓库里已经有 AGENTS.md(或者 .cursorrules、.windsurfrules),Claude Code 会读取这些文件,把相关内容整合进生成的 CLAUDE.md。所以即便你忘了手动桥接,/init 也能帮你兜个底。
几个实用命令
/context—— 查看当前上下文中已加载的全部 CLAUDE.md 内容。如果怀疑某条规则没生效,先看这个。/init --force—— 重新生成 CLAUDE.md,覆盖现有版本。/cost—— 查看加载 CLAUDE.md 消耗了多少 Token,通常很少,大约 200-500,不用太担心。
常见问题
CLAUDE.md 会泄露我的秘密吗?
如果你把项目级 CLAUDE.md 提交到公开仓库,那里面写的所有内容都会被看到。所以,不要在项目级 CLAUDE.md 里放 API Key、内部域名或敏感路径。这类信息应该放在 CLAUDE.local.md 里,并加入 .gitignore 避免泄露。
Monorepo 中如何配置?
在根目录放一份通用规则,在每个子包中放自己特定的规则。Claude Code 的向上查找机制会让根目录的规则对所有子包生效,而子包的规则又可以对根目录的规则做补充或覆盖。
CLAUDE.md 里可以用中文吗?
可以,Claude 完全理解中文。不过推荐命令和路径用英文,避免编码问题。
Windows 路径有问题吗?
Claude Code 会自动转换路径分隔符,这方面不用操心。
写在最后
CLAUDE.md 这东西,说到底就是一个 Markdown 文件,没什么技术门槛。但正是这种看似简单的机制,解决了一个根本性的问题:如何让一个无状态的 AI 助手保持对项目的持久记忆。
不过,记忆只是第一步。如果你想让大厨不只记住你家不吃香菜,还能按标准流程做出一整套招牌菜,比如”按公司规范做安全审查”或”自动生成周报”,光靠备注可不够。下一篇文章,我们看看怎么用 Skills 给 Claude 教一套完整的烹饪套路。
封面图片来自豆包 AI。
本文同步发布在知乎账号下:Claude-Code-实践指南(二):编写操作规范




