为什么我的 Claude Code 老是不按我说的做?如何写出让 Agent 准确执行的「共识协议」 概览: CLAUDE.md 是你和 AI Agent 的共识协议。本文从加载机制、优先级、文件组织到常见反模式手把手教你写出让 Claude Code 准确执行的项目指令附完整配置示例和踩坑记录keywords: [CLAUDE.md, Claude Code, AI编程, Agent指令, 共识协议, prompt engineering]上周有人在群里问了一句「为什么我的 Claude Code 老是不按我说的做明明 CLAUDE.md 里写得很清楚了。」我点开他的 CLAUDE.md 一看——482 行从项目介绍到编码规范到 Git 提交格式到部署流程事无巨细恨不得把公司 wiki 搬进去。问题出在哪不是写多了而是写的全是 Claude 自己能从代码里推断出来的东西。真正需要写的——那些它猜不到的构建命令、那些违反默认习惯的项目规范——反而淹没在信息噪声里了。CLAUDE.md 不是文档不是 README不是给人看的。它是你和 AI Agent 之间的共识协议——就像分布式系统里节点之间约定好的通信规范写对了所有 Agent 按同一套规则执行写错了每次对话都在重复纠正同样的错误。这篇文章是我自己折腾 CLAUDE.md 之后总结的实战指南。从加载机制讲到文件组织从该写什么讲到千万别写什么最后给一套可以直接抄的模板。先搞清楚 CLAUDE.md 是怎么被加载的写 CLAUDE.md 之前必须理解它的加载机制。不然你不知道为什么某些指令生效了某些没有。Claude Code 启动时会从四个层级收集指令优先级从高到低claude-md-loading-hierarchy第一层企业策略Managed Policy。这是组织管理员通过/etc/claude/下发的全局策略个人开发者一般用不到。优先级最高会覆盖所有其他配置。第二层项目级Project。就是你项目根目录下的CLAUDE.md文件。这是最常用的也是本文的重点。它随代码提交团队成员共享同一份。第三层用户级User。放在~/.claude/CLAUDE.md只对你自己生效。适合写个人偏好——比如你喜欢用中文回复、喜欢简短风格这类东西。第四层本地覆盖Local Override。放在项目根目录下的.claude/CLAUDE.md注意有个.claude目录通常加入.gitignore不提交。适合写本地特有的环境变量路径、调试配置。关键点来了Claude Code 会沿目录树向上递归收集所有 CLAUDE.md。什么意思如果你的项目结构是这样的my-monorepo/ ├── CLAUDE.md # 顶层通用规范 ├── backend/ │ ├── CLAUDE.md # 后端子项目规范 │ └── src/ └── frontend/ ├── CLAUDE.md # 前端子项目规范 └── src/当 Claude Code 在backend/目录下工作时它会同时加载backend/CLAUDE.md和顶层的CLAUDE.md然后拼接在一起送入 context。这个机制和分布式系统里的配置层叠覆盖一模一样——全局配置打底局部配置覆盖。“踩坑记录如果你在子目录和根目录的 CLAUDE.md 里写了矛盾的指令比如根目录说「用 ESLint」子目录说「用 Biome」Claude 会优先听离当前工作目录更近的那个。但如果指令只是「不同」而不是「矛盾」两者会合并生效。这个行为没有明确文档我是踩坑发现的。该写什么那些 Agent 猜不到的东西这是整篇文章最核心的部分。官方文档给了一个非常精准的判断标准写进 CLAUDE.md 的应该是 Claude 无法从代码本身推断出来的信息。具体来说有四类内容必须写1. 构建和测试命令这是最高优先级。Claude 能读懂你的代码但它猜不到你的构建系统怎么跑。## 构建命令 - 构建整个项目mvn clean install -DskipTests - 构建单个模块mvn clean install -DskipTests -pl dlm-framework/dlm-rule - 运行测试mvn test -pl dlm-framework/dlm-rule - 本地启动./scripts/dev-start.sh需要先启动 ZooKeeper 和 Redis 首次构建多模块项目时先注释掉父 POM 的 modules 段构建完成后恢复。注意最后那行踩坑提示——这种信息 Claude 绝对猜不到写进去能省掉每次手动解释的时间。2. 违反默认习惯的编码规范Claude 默认会按照业界最常见的规范写代码。如果你的项目有不同的约定必须明确告知。## 编码规范 - Java 版本Java 8不要使用 var、stream 的 toList()、records 等高版本特性 - 缩进4 空格不是 2 空格 - 测试框架JUnit 4 Mockito不是 JUnit 5 - 日志使用 Slf4j 注解不要手动创建 Logger 实例 - 异常处理业务异常用 BizException不要用 RuntimeException这里的关键是「不是什么」比「是什么」更重要。Claude 可能默认用 JUnit 5 写测试——如果你不说「用 JUnit 4」它就会按自己的判断来。3. 架构约定和模块边界Claude 能读懂单个文件但它不一定理解你项目的整体架构意图。## 架构约定 本项目采用微内核 插件架构 - dlm-framework/ 是纯框架层不允许包含任何业务逻辑 - dlm-app/ 是业务服务层每个服务遵循 api / service / web 三子模块模式 - 新增协议适配器放在 dlm-protocol/实现 IProtocolDispatcher 接口 - RPC 调用通过 Dubbo不要引入 Feign 或 RestTemplate 做服务间调用4. 工作流程和提交规范## Git 规范 - 提交信息格式type(scope): subjecttype 包括 feat/fix/refactor/docs/test - 不要用 --no-verify 跳过 pre-commit hook - PR 标题不超过 70 字符 - 每个 PR 只做一件事不要混合功能开发和代码重构千万别写什么Agent 自己能搞定的事写 CLAUDE.md 最常见的错误是信息过载。官方建议控制在500 行以内——不是因为有硬性限制而是因为每次对话启动时 CLAUDE.md 的内容都会被注入 context window写太多等于每次都在浪费 token 预算。以下内容不要写进CLAUDE.md项目目录结构说明。Claude 可以自己跑ls和find不需要你在 CLAUDE.md 里画 ASCII 目录树。语言基础知识。不需要写「Java 是一种面向对象的编程语言」或者「Spring Boot 是一个微服务框架」。Claude 知道。通用编码规范。如果你的规范和业界标准一致比如 Go 用 gofmt、Python 用 Black不需要重复写。只写不同的地方。大段解释性文本。CLAUDE.md 不是技术文档。Claude 需要的是可执行的指令不是背景介绍。比较一下# ❌ 错误示范解释性文本 我们的项目使用了微内核架构这种架构的核心思想是将系统分为核心框架和插件模块。 核心框架提供基础的运行时环境和扩展点而插件模块则通过实现这些扩展点来添加具体功能。 这种设计的好处是...后面还有 200 字 # ✅ 正确示范可执行指令 ## 架构规则 - framework/ 层不允许 import app/ 层的任何类 - 新插件必须实现 IPlugin 接口并注册到 PluginRegistry - 跨模块依赖通过 SPI 机制不要直接 newwrite-vs-not-write用.claude/rules/做路径级精准控制CLAUDE.md 是全局生效的。但有些规则只在特定文件上才有意义——比如「测试文件必须用 Given-When-Then 命名」这条规则你不希望它在改 README 的时候也蹦出来。.claude/rules/目录就是干这个的。每个.md文件可以通过 frontmatter 指定生效范围--- description: 测试文件编码规范 globs: [**/test/**/*.java, **/*Test.java] --- - 测试方法命名should*预期行为\_when*前置条件 - 每个测试方法只测一件事 - Mock 使用 Mock 注解 InjectMocks不要手动 new - 断言用 assertThat()Hamcrest不要用 assertEquals()当 Claude 编辑匹配 glob 模式的文件时这些规则会自动注入 context。编辑其他文件时这些规则不存在。这个机制的好处是精准投放节省 token。你可以这样组织.claude/ └── rules/ ├── testing.md # globs: [**/test/**] ├── api-design.md # globs: [**/controller/**, **/api/**] ├── database.md # globs: [**/mapper/**, **/repository/**] └── frontend.md # globs: [src/components/**/*.tsx]“踩坑记录如果一个 rule 文件没有globs字段或者globs为空它会始终生效等价于写在 CLAUDE.md 里。用这个特性可以把一些「总是需要但又不想塞进 CLAUDE.md」的规则外置。import语法CLAUDE.md 的模块化当项目规模大到 CLAUDE.md 超过 200 行时拆分是唯一的出路。import语法让你可以把 CLAUDE.md 拆成多个文件# CLAUDE.md ## 通用规范 docs/coding-standards.md docs/git-conventions.md ## 构建指南 docs/build-guide.md ## 架构说明 docs/architecture-rules.md被引用的文件内容会在加载时展开效果等同于直接写在 CLAUDE.md 里。这个语法的价值在于关注点分离。编码规范变了你只需要改coding-standards.md不需要在一个巨大的 CLAUDE.md 里翻找。团队中负责不同模块的人可以各自维护自己的规则文件。但有一个需要注意的地方import 的文件也计入总 token 消耗。拆分是为了可维护性不是为了绕过长度限制。最终注入 context 的内容量是一样的。验证策略让 Agent 自证正确写 CLAUDE.md 最容易忽略的一点是光告诉 Agent「怎么做」不够还要告诉它「做完之后怎么验证自己做对了」。这就像分布式系统里的心跳检测——你不能只下发指令然后祈祷节点正确执行你需要一个反馈机制。## 验证清单 改完代码之后按顺序执行以下检查 1. mvn compile -pl 修改的模块 — 确保编译通过 2. mvn test -pl 修改的模块 — 确保测试通过 3. 检查是否有新增的编译警告 4. 如果修改了 API 接口确保 Dubbo 的 api 模块也同步更新了 DTOagent-verify-feedback-loop更高级的做法是在 CLAUDE.md 里引导 Claude 使用Plan Mode## 复杂任务处理 对于涉及 3 个以上文件的修改 1. 先进入 Plan Mode/plan列出所有要改的文件和改动点 2. 等我确认后再开始执行 3. 每改完一个文件就运行一次编译检查 4. 全部改完后跑完整测试套件这相当于在共识协议里加了一个两阶段提交2PC先 prepare列计划再 commit执行修改。如果 prepare 阶段发现计划不对abort 的成本几乎为零。多 Agent 场景下的共识问题如果你用了 Claude Code 的 Sub-agent 或 Agent Teams 功能CLAUDE.md 的作用就更关键了——它是所有 Agent 共享的唯一配置源。每个被 spawn 出来的 Sub-agent 都会独立加载当前目录的 CLAUDE.md。这意味着好处所有 Agent 天然遵守同一套规则不需要额外的同步机制。这就是分布式系统里「配置中心」的作用。风险如果 CLAUDE.md 里的指令有歧义不同 Agent 可能做出不同的解读——就像拜占庭将军问题里同一条命令被不同节点解读出不同含义。所以在多 Agent 场景下CLAUDE.md 的指令必须做到无歧义、可执行、可验证# ❌ 有歧义的指令 - 代码要写得简洁 - 变量命名要有意义 - 适当添加注释 # ✅ 无歧义的指令 - 方法体不超过 30 行超过就提取子方法 - 变量命名用 camelCase布尔变量以 is/has/can 开头 - 只在「为什么这样做」不明显时添加注释不要注释「做了什么」如果你还配置了自定义 Sub-agent放在.claude/agents/目录每个 agent 可以有自己的 system prompt 和工具白名单。但它们仍然会继承 CLAUDE.md 的全局规则。层级关系是CLAUDE.md全局共识 └── .claude/agents/reviewer.mdagent 专属指令 └── 运行时 context当前任务 对话历史“[技术配图架构图 - 多 Agent 配置继承关系]Excalidraw 文件images/claude-md-writing-guide-consensus-protocol/multi-agent-config-inheritance.excalidraw渲染后替换为![多 Agent 配置继承关系](images/claude-md-writing-guide-consensus-protocol/multi-agent-config-inheritance.png)五个常见反模式以及怎么修Anthropic 官方文档里列出了几个高频踩坑模式加上我自己的经验总结如下反模式 1厨房水槽式Kitchen Sink症状CLAUDE.md 超过 500 行啥都往里塞。后果context window 被大量低价值信息占用真正重要的指令被稀释。修法砍到 200 行以内。用「如果我删掉这行Claude 会做错吗」来判断每一行的去留。不会做错的就删。反模式 2过度指定Over-Specified症状把 Claude 能自己推断的东西也写进去。比如在一个 TypeScript 项目里写「使用 TypeScript 开发」。后果噪声而且容易和实际代码脱节——你 CLAUDE.md 里写的规范可能和代码库实际用的不一致。修法只写差异项。问自己「一个熟悉这个技术栈的高级工程师看到代码后还需要被告知什么」需要被告知的那些才值得写。反模式 3反复纠正不记录Correct-and-Forget症状每次 Claude 犯同样的错误你都在对话里纠正它但从来不更新 CLAUDE.md。后果下次新对话又犯。因为 CLAUDE.md 是跨对话持久化的对话内的纠正不是。修法**第二次纠正同一个问题时立刻写进 CLAUDE.md 或.claude/rules/**。这是一条铁律。反模式 4信任-验证缺口Trust-then-Verify Gap症状在 CLAUDE.md 里写了详细的指令但没有写验证步骤。Claude 执行完了你才发现不对。后果返工。尤其在多文件修改场景下返工成本很高。修法每个关键指令后面跟一条验证命令。参考上面「验证策略」章节。反模式 5无限探索Infinite Exploration症状没有告诉 Claude 项目的边界在哪里它花大量 token 去读无关的文件。后果token 浪费执行慢还可能被无关信息误导。修法在 CLAUDE.md 里明确标注「不需要关注」的目录## 项目边界 - 忽略 legacy/ 目录这是已弃用的旧代码 - 忽略 vendor/ 和 node_modules/ - 只关注 src/main/java/ 下的业务代码和 src/test/ 下的测试代码一个可以直接抄的模板把上面所有实践汇总一个 CLAUDE.md 的推荐结构长这样# CLAUDE.md ## 构建命令 [必须构建、测试、启动命令含前置条件和踩坑提示] ## 编码规范 [只写和默认不同的约定越具体越好] ## 架构规则 [模块边界、依赖方向、禁止的做法] ## Git 规范 [提交格式、分支策略、PR 要求] ## 验证清单 [改完代码后的自动检查步骤] ## 项目边界 [哪些目录要关注哪些要忽略]配合.claude/rules/做路径级细化.claude/ ├── CLAUDE.md # 本地覆盖不提交 ├── agents/ │ └── reviewer.md # 代码审查专用 agent └── rules/ ├── testing.md # 测试文件专用规则 ├── api-design.md # API 层专用规则 └── database.md # 数据访问层专用规则常见问题QCLAUDE.md 和 AGENTS.md 是什么关系AGENTS.md 是行业通用的 agent 指令文件名多家 AI 编程工具都支持。Claude Code 同时读取 CLAUDE.md 和 AGENTS.md两者内容会合并。如果你的项目要兼容多个 AI 工具比如同时用 Claude Code 和 Cursor可以把通用规范放 AGENTS.mdClaude 专属配置放 CLAUDE.md。QCLAUDE.md 写多长合适官方建议是保持精简大致在 200 行以内。更重要的是信噪比——100 行全是高价值指令比 500 行注水内容好得多。如果实在需要更多内容用import拆分或者用.claude/rules/按路径分发。Q团队里每个人的习惯不一样怎么办项目级 CLAUDE.md 写团队共识构建命令、架构规则、代码规范个人偏好放~/.claude/CLAUDE.md回复语言、交互风格或者项目下的.claude/CLAUDE.md本地环境配置加入 .gitignore 不提交。Q怎么调试 CLAUDE.md 是否生效最直接的方法在对话里问 Claude「你当前加载的 CLAUDE.md 内容是什么」它会把已加载的指令列出来。如果某条规则没出现检查文件路径和 glob 模式是否正确。QCLAUDE.md 和 Claude Code 的 Memory 系统有什么区别CLAUDE.md 是声明式的静态配置每次对话都加载适合项目级规范。Memory~/.claude/projects/project/memory/是动态积累的上下文跨对话持久化适合记录用户偏好、项目进展这类随时间变化的信息。两者互补不冲突。我的判断CLAUDE.md 本质上是一个人机共识协议的序列化格式。它的设计哲学和分布式系统的配置管理如出一辙层叠覆盖、最小化传输、精确投放。写好 CLAUDE.md 的核心原则只有一条只写 Agent 猜不到的东西。其他的全删。随着 Claude Code 的 Agent 能力越来越强——Sub-agents、Agent Teams、自定义 agents——CLAUDE.md 作为「共识层」的角色只会更重要。它不再只是一个配置文件而是你和一个智能团队之间的沟通契约。合同写得好团队才能高效运转。下次你打开 CLAUDE.md 准备加点什么的时候先停下来问自己一个问题「如果我不写这行Claude 会做错吗」如果答案是「不会」那就别写。