Claude Code 进阶 约 6 分钟

CLAUDE.md 与规则文件:让 Claude Code 记住项目约定

用项目级 CLAUDE.md 和带 paths 的 .claude/rules 规则组织长期指导,检查实际加载了哪些文件,并分清“上下文建议”和“硬权限”的边界。

本页目录

目标:把重复交代变成可维护的项目文件

每次开新会话都重新说明“用 pnpm”“测试命令是什么”“不要动 generated 目录”,既浪费上下文,也容易漏。Claude Code 用 CLAUDE.md 和 .claude/rules/ 承载这类长期指导:启动时加载,之后作为上下文参与回答。

但“写进 CLAUDE.md”不等于“系统会强制执行”。它本质上仍是提示词的一部分。本文先建立一个小仓库的指导文件,再检查它们是否真的被加载,最后说明哪些要求应该放进权限设置而不是记忆文件。

前置条件

  • 已安装并登录 Claude Code。
  • 一个练习仓库,至少包含 src/ 和一份测试配置。
  • 知道项目使用的包管理器和测试命令;不要凭习惯写进文件。
  • 愿意把项目约定提交到版本库;个人偏好放在本地文件,不要混进团队共享内容。

第一步:建立最小项目记忆

在仓库根目录创建 CLAUDE.md:

## 项目约定

- 包管理器:pnpm,不要生成 package-lock.json。
- 测试:`pnpm test`;提交前必须通过。
- 源码在 `src/`,生成代码在 `generated/`,不要手改。
- 详细架构说明见 @docs/architecture.md。

## 回答要求

- 先给结论,再给文件路径和验证命令。
- 不确定的接口先读代码,不要猜。

@docs/architecture.md 是导入语法,会把另一个文件的内容带进上下文;导入有层数上限,别把所有文档串成一张网。CLAUDE.md 应保持短小,官方建议控制在 200 行左右;超过 4 MiB 的文件会被跳过。长文档拆到按需加载的规则或普通文档里,比堆在一个文件里更可持续。

个人偏好可以放在 CLAUDE.local.md,并确保它不被提交。团队共享的约定则放在 CLAUDE.md 或 .claude/CLAUDE.md,两者选一个作为项目入口,不要同时维护两份互相矛盾的副本。

第二步:用 paths 把规则限定到目录

创建 .claude/rules/testing.md:

---
paths:
  - "src/**/*.test.ts"
  - "tests/**/*.ts"
---

## 测试规则

- 使用项目现有的测试工具,不新增测试框架。
- 每个测试只验证一个行为,名称描述可观察结果。
- 不修改快照来让测试通过;先解释差异。

没有 paths 的规则会在每次会话加载;带 paths 的规则只在处理匹配文件时进入上下文。这样既能让测试文件附近的会话看到专门约定,又不会让主会话被无关规则占满。规则文件只会读取 paths 字段;其他字段即使写进去也不会生效,拼错更是如此。

第三步:检查实际加载了什么

启动会话后执行:

/context all

预期结果(示意):输出中会出现 Memory files 区域,列出当前加载的 CLAUDE.md、规则文件或导入文件。若你刚改过文件,可以退出重进,或在会话中执行 /memory 查看和编辑记忆文件。较新版本还提供 /doctor prompt-audit,用于检查提示词和记忆的装配情况;具体可用性以本机帮助为准。

加载顺序是从宽到窄:系统级策略、用户级 ~/.claude/CLAUDE.md、项目级、本地项目文件。它们会合并,而不是后者覆盖前者;祖先目录的文件在启动时加载,子目录里的文件在访问到相关路径时按需加载。这也解释了为什么“我写了但没生效”有时只是还没读到那个目录。

Windows 上系统级路径与 Linux/WSL 不同,例如托管策略可能位于 C:\Program Files\ClaudeCode\CLAUDE.md,而 Linux/WSL 是 /etc/claude-code/CLAUDE.md。不要跨平台复制这些路径;先确认当前环境。

第四步:验证一条约定是否真的影响行为

先让 Claude 读取一个真实命中 paths 的文件,再提一个会触发约定的问题:

先读取 src/format.test.ts,然后回答:新增一个工具函数时,应该把测试放在哪里?需要改 generated/ 吗?

把 src/format.test.ts 换成你仓库里真实存在的测试文件;没有就先建一个,因为路径规则只在 Read/Write/Edit 命中匹配文件(或 cat/head 这类单文件读取)时才加载,不读就不会生效。

预期回答(示意):应引用 src/**/*.test.ts 规则,并说明 generated/ 不手改。若回答没有提到这些内容,不要继续加更多文字;先回到 /context all 确认文件是否加载,再检查规则是否匹配当前文件路径。

第五步:把“必须阻止”的要求移出记忆

假设项目要求“绝不读取 .env”。把这句话写进 CLAUDE.md 只是建议,模型仍可能读取。真正的硬约束应放进权限设置,例如在 .claude/settings.json 中拒绝读取该文件,并对通过 Bash 读取的路径也做限制。权限规则按工具和参数匹配,和自然语言记忆是两套机制。

同理,“提交前必须运行测试”如果必须每次都发生,应使用钩子或 CI,而不是只写一句“请记得测试”。记忆适合表达偏好、背景和判断标准;权限适合阻止动作;钩子适合绑定生命周期。混用会让团队误以为某条要求已经被强制执行。

常见失败与诊断

1. 写了 CLAUDE.md,但回答完全不提。 先 /context all 看文件是否在列表里。项目文件必须位于启动目录或其祖先目录,也就是要从项目根或项目内子目录启动;从项目根的上级启动不会向下加载。若是按需规则,确认当前操作的文件匹配 paths。

2. 规则文件没有生效。 检查 frontmatter 是否从第一行 --- 开始、YAML 是否合法、paths 的 glob 是否匹配实际路径。claude --debug 会报告规则解析问题;不要靠猜缩进。规则只在 .claude/rules/ 下按约定加载,放到普通目录不会自动变成规则。

3. 同时存在 AGENTS.md 和 CLAUDE.md。 当前版本在没有上层 CLAUDE.md 时也会读取 AGENTS.md;两者同时存在时,加载策略可通过 /config 的 Project instructions 选项查看。不要为了“只留一个”直接删除另一个,先确认团队实际依赖哪一个。

4. 文件太大或被跳过。 检查行数和体积;超过上限的文件不会进入上下文。把架构背景拆成独立文档,用 @ 导入或按路径规则加载;不要用压缩工具把内容塞成一行。

5. 以为写了“禁止”就不会发生。 这是最常见也最危险的误解。把关键限制迁移到权限 deny 规则,或加钩子/CI 检查;然后在一次无害操作上验证拒绝确实发生。记忆文件不是安全边界。

验收清单

  • 项目根有且只有一个主要 CLAUDE.md 入口,内容控制在可维护长度。
  • 目录专属规则使用 paths,没有让所有会话加载无关内容。
  • /context all 能看到预期文件,导入文件没有断链。
  • 一条项目约定在提问中得到体现,而不只是“文件存在”。
  • 硬性禁止项已放进权限或钩子,而不是只写在记忆里。
  • 没有把密钥、个人路径或不该共享的内容写进团队记忆。

接下来

记忆文件只是上下文,真正的动作边界在 Claude Code 权限。想把“读代码—改代码—验证”固化成日常流程,读 Claude Code 工作流。如果你同时使用 Codex,可以对照 项目上下文 看两种工具的加载差异。

参考来源

核验范围(2026-11-14):加载顺序、文件位置、paths 规则、导入上限和 /context all 行为依据官方页面核对。具体字段与命令随版本变化;执行前用 /memory、/context all 和 claude --help 确认本机版本。