Skip to content

05.6 CLAUDE.md 项目记忆

一次配置,长期收益。CLAUDE.md 是让 Claude Code "懂你项目"的核心机制。

读完你能做什么:写出一份既被遵守又不浪费上下文的项目记忆,并诊断"它为什么不听 CLAUDE.md"。


一、两套记忆系统

Claude Code 有两个互补的记忆机制,都在每次会话开头加载:

CLAUDE.md 文件Auto Memory(自动记忆)
谁写的Claude
内容指令和规则学到的经验和模式
作用编码规范、工作流、架构构建命令、调试洞察、你的偏好
加载每次会话全量每次会话(前 200 行 / 25KB)

分工:你想主动指导它 → 写 CLAUDE.md;让它从你的纠正中自己学 → 靠 Auto Memory。


二、CLAUDE.md 的位置与加载顺序

多个位置,从广到窄,按顺序加载(后加载的更靠近当前工作,权重更高):

范围位置用途
管理策略系统级路径(IT 下发)组织级强制规范
用户~/.claude/CLAUDE.md你个人所有项目的偏好
项目./CLAUDE.md./.claude/CLAUDE.md团队共享(提交到 git)
本地./CLAUDE.local.md个人项目偏好(加 .gitignore)

2.1 加载机制的三个关键点

  1. 向上遍历目录树 —— 在 foo/bar/ 启动,会加载 foo/bar/CLAUDE.mdfoo/CLAUDE.md 及沿途的 CLAUDE.local.md
  2. 子目录的 CLAUDE.md 按需加载 —— 不在启动时加载,而是当 Claude 读该子目录的文件时才载入。
  3. 拼接而非覆盖 —— 所有找到的文件拼在一起,从根到工作目录排序,越近的越靠后(权重越高)。

2.2 验证到底加载了什么

text
> /context

Memory files 这一节,确认你的 CLAUDE.md 真的被加载了。如果它不在那里,Claude 就看不见它。

text
> /memory

浏览和编辑所有记忆文件。


三、怎么写一份好的 CLAUDE.md

3.1 该写什么

✅ 该写❌ 不该写
构建/测试命令Claude 自己能从代码推断的(目录结构、依赖列表)
与工具默认行为不同的约定通用的编程常识
项目特有的坑和陷阱冗长的架构叙述
"永远做 X" / "永远不做 Y" 规则只对一个子目录成立的规则(用 rules)
重要决策及其理由多步操作流程(用 Skill)

3.2 一份高质量的示例

markdown
# 支付网关

## 构建与测试
- 构建:`make build`
- 测试:`make test`(需要本地 Redis,先 `make redis-up`
- 单个测试:`go test ./internal/reconcile -run TestXxx`

## 绝对规则
- 金额一律用 `decimal.Decimal`,禁止 float64
- 不修改 `internal/legacy/` 下任何文件(等迁移完再动)
- `IPaymentCallback` 接口签名不能改(3 个外部系统依赖)

## 约定
- 错误用 `fmt.Errorf("...: %w", err)` 包装,保留错误链
- 新渠道适配器放 `internal/channels/<name>/`,实现 `Channel` 接口
- 数据库迁移用 `migrate`,不要手写 SQL 改 schema

## 已知坑
- 支付宝 SDK 的 client 非线程安全,不要缓存在 package 级变量
- 测试环境的银联 mock 经常挂,跑集成测试前先 `curl localhost:8081/health`

<!-- 维护者注释:这段 HTML 注释会被剥离,不占 Claude 的上下文 -->

## 提醒
再次强调:金额禁止使用浮点类型。

3.3 三条硬性原则

原则数值理由
控制长度目标 < 200 行越长越占上下文,且遵守率越低
具体可验证"用 2 空格缩进" 而非 "格式规范"模糊指令等于没指令
无内部矛盾定期清理矛盾时 Claude 会随机选一条

四、用 rules 拆分大项目

CLAUDE.md 要写的东西超过 200 行,用 .claude/rules/ 拆分:

text
your-project/
├── .claude/
│   ├── CLAUDE.md           # 主指令(精简)
│   └── rules/
│       ├── code-style.md   # 编码风格
│       ├── testing.md      # 测试约定
│       └── api-design.md   # API 设计

4.1 路径作用域规则(关键特性)

用 frontmatter 的 paths 字段,让规则只在处理匹配文件时加载

markdown
---
paths:
  - "src/api/**/*.ts"
---

# API 开发规则

- 所有 endpoint 必须做输入校验
- 用统一的错误响应格式
- 加 OpenAPI 文档注释

这条规则只在 Claude 读 src/api/ 下的 .ts 文件时才进上下文。其他时候零成本。

支持多模式和 brace 展开:

markdown
---
paths:
  - "src/**/*.{ts,tsx}"
  - "tests/**/*.test.ts"
---

没有 paths 的 rules 无条件加载,优先级同 .claude/CLAUDE.md

4.2 rules vs CLAUDE.md vs Skill

text
每次都要遵守的事实          →  CLAUDE.md
只对部分文件成立的规范       →  .claude/rules/(带 paths)
按需触发的多步流程          →  Skill

08.5 四种扩展机制怎么选


五、Auto Memory

Claude 会自己记录跨会话有用的东西:构建命令、调试经验、你的偏好。

5.1 存储位置

text
~/.claude/projects/<project>/memory/
├── MEMORY.md          # 索引,每次会话加载前 200 行 / 25KB
├── debugging.md       # 详细笔记,按需读
└── ...

MEMORY.md 是索引;详细内容在主题文件里。注意 200 行 / 25KB 上限 —— 超出部分下次加载会被丢弃,所以要保持 MEMORY.md 精简。

5.2 开关与管理

json
// 项目级关闭
{ "autoMemoryEnabled": false }
bash
# 环境变量关闭
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 claude
text
> /memory     # 查看、编辑、开关

5.3 主动喂给它

text
> 记住:这个项目的集成测试需要先启动本地 Redis

它会存到 auto memory。想存进 CLAUDE.md 而非 auto memory,明确说:

text
> 把"金额禁止用浮点"这条加到 CLAUDE.md 的绝对规则里

六、导入其他文件

CLAUDE.md 可以用 @path 语法导入:

markdown
See @README for overview and @package.json for available commands.

# 额外指令
- git 工作流 @docs/git-instructions.md
  • 相对路径基于文件所在位置
  • 最多 4 层递归
  • 想提到路径但导入,用反引号包起来:`@README`

跨 worktree 共享个人偏好,从 home 目录导入:

markdown
# 个人偏好
- @~/.claude/my-project-instructions.md

(首次遇到项目内的外部导入会弹确认对话框,防止别人往共享项目里塞恶意导入。)

6.1 兼容 AGENTS.md

如果你的仓库用 AGENTS.md(其他 AI 工具的标准),Claude Code 只读 CLAUDE.md。让它也读 AGENTS.md:

markdown
@AGENTS.md

## Claude Code 专属
在 src/billing/ 下的改动用 plan 模式。

七、诊断"它不听 CLAUDE.md"

这是最常见的困惑。按顺序排查:

7.1 它到底加载了吗

text
> /context

Memory files 里没有你的文件 = 位置不对或没被发现。用 /memory 打开确认。

7.2 指令够具体吗

text
❌ "格式化代码"      →  改成
✅ "用 gofmt 格式化,导入分组:标准库、第三方、本项目"

7.3 有矛盾吗

检查用户级、项目级、.claude/rules/ 之间有没有打架的指令。矛盾时 Claude 会随机选。

7.4 它本质上是"上下文"不是"配置"

关键认知CLAUDE.md 作为系统提示词之后的用户消息递送,不是系统提示词本身。Claude 会读它、尽力遵守,但不保证严格合规

因此:

text
"倾向性"规则(风格、偏好)        →  CLAUDE.md 够用
"必须 100% 执行"的规则(安全门禁) →  用 hook,不要指望 CLAUDE.md

比如"每次提交前必须跑测试",写在 CLAUDE.md 里是概率性的;写成 PreToolUse hook 匹配 Bash(git commit *) 才是确定性的。见 06.5

7.5 /compact 后指令丢了

项目根目录的 CLAUDE.md/compact 后会重新从磁盘注入。但子目录的嵌套 CLAUDE.md 不会自动重注入,要等下次读该目录文件时。如果一条指令压缩后消失,它可能只是在对话里说过(没进 CLAUDE.md),或者在还没重新加载的嵌套文件里。


八、用 /doctor 精简

v2.1.206+ 的 /doctor 会主动为已提交的 CLAUDE.md 提精简建议:

text
> /doctor

它会砍掉 Claude 能从代码库自己推导的内容(目录布局、依赖列表、架构概览),保留它推导不出来的(坑、决策理由、与默认不同的约定)。


九、一份可复制的起步模板

markdown
# <项目名>

## 构建与测试
- 构建:`<命令>`
- 测试:`<命令>`(<前置条件>)
- 单测:`<命令>`

## 绝对规则
- <永远/禁止 X>
- <永远/禁止 Y>

## 约定
- <命名/结构约定>
- <错误处理约定>

## 已知坑
- <坑 1 及规避方法>

## 提醒
<最重要的一条规则,在此重申>

延伸阅读

基于 VitePress 构建 · 内容采用原作者授权