一、为什么会混淆这两个文件
用 Claude Code 一段时间之后,几乎每个人都会踩到同一个坑:在 CLAUDE.md 里塞进大量临时经验,在 MEMORY.md 里写死了项目规范,然后发现 AI 的行为越来越难预期。
这不是偶然。两个文件的名字都跟"记忆"有关,都是 Markdown 格式,都在会话开始时被加载------但它们在设计层面解决的是两个完全不同的问题。把它们搞混,就像把公司员工手册和个人工作日志存在同一个文件里:混乱是必然的。
二、一张表说清本质区别
| 对比维度 | CLAUDE.md | MEMORY.md(Auto Memory) |
|---|---|---|
| 谁来写 | 开发者手动编写 | Claude 自动生成与更新 |
| 写什么 | 项目规范、架构约束、命令说明 | 从对话中总结的经验、偏好 |
| 存放位置 | 项目根目录(或 ~/.claude/) |
~/.claude/projects/<project>/memory/ |
| 生命周期 | 静态,需要人工维护 | 动态,随项目进展持续积累 |
| 加载方式 | 每次会话完整加载(目标 200 行以内) | 前 200 行或 25KB,超出按需读取 |
| 适合存放 | 编码标准、目录结构、禁止事项 | 构建命令踩坑、调试发现、个人偏好 |
| 直观类比 | 📋 项目说明书 / 员工入职手册 | 📓 Claude 的工作日志 |
三、CLAUDE.md:你写给 AI 看的说明书
它解决什么问题
每次开启一个新会话,Claude 对你的项目一无所知。没有人会在每次对话开始时把架构说明、技术栈、代码规范重新讲一遍------CLAUDE.md 就是解决这个问题的。它是开发者主动写给 AI 的持久化上下文,相当于给新来的程序员准备的入职文档。
加载层级与覆盖规则
Claude Code 采用多层叠加 的方式加载 CLAUDE.md,启动时从当前工作目录向上遍历整个目录树,把沿途发现的所有文件全部加载并合并:
系统托管级(组织 IT 控制)
↓
用户全局级 ~/.claude/CLAUDE.md
↓
项目根目录 ./CLAUDE.md 或 ./.claude/CLAUDE.md
↓
本地个人级 ./CLAUDE.local.md(加入 .gitignore,不提交)
↓
子目录按需 当 Claude 读取该目录文件时自动加载
这意味着在 Monorepo 中,可以为前端、后端、工具脚本分别维护一套规范,只有 Claude 真正涉及那部分代码时,对应的配置才会进入上下文------既精准又省 token。
一份好的 CLAUDE.md 写什么
参考 Andrej Karpathy 等人的实践,高质量的 CLAUDE.md 通常包含以下几类内容:
- 项目概述 --- 这是什么系统,核心技术栈是什么
- 目录结构 --- 关键路径各放什么,命名约定是什么
- 常用命令 --- 如何启动、测试、构建、部署
- 代码规范 --- 命名风格、注释要求、禁止使用的模式
- 已知踩坑 --- 避免 AI 重蹈覆辙的特殊说明
关键约束:控制在 200 行以内。 Claude Code 创始人 Boris Cherny 明确提过,超过 200 行后 Claude 会开始选择性忽略。不是因为 AI "偷懒",而是上下文窗口的成本促使模型做优先级排序------越精简,越可靠。
@ 语法引用外部文档
当规范内容较多时,可以在 CLAUDE.md 里用 @路径 语法引用外部文件,避免单文件膨胀:
markdown
## 设计规范
@docs/api-design-guide.md
@docs/database-conventions.md
Claude 读取时会自动展开引用内容,递归深度最多 4 跳。注意:引用并不会减少 token 消耗,它只是改善了文件的组织结构。
四、MEMORY.md:Claude 写给自己的工作日志
自动记忆机制的工作原理
自 Claude Code v2.1.59 引入自动记忆功能后,每次对话结束时,Claude 会评估这次交互中产生了哪些值得保留的经验,然后决定是否写入记忆文件。这个过程的核心链路是:
对话结束 → executeExtractMemories() → 分析对话内容
→ 提取值得保留的信息
→ 写入 ~/.claude/projects/<project>/memory/MEMORY.md
Claude 不会每次对话都写东西。它有自己的判断:构建命令踩坑、架构决策的原因、用户反复纠正的偏好......这些跨会话仍然有价值的内容才值得写进记忆。一句"把这个变量名改一下"不值得持久化。
存储结构
记忆目录按 Git 仓库维度组织,同一仓库的所有 worktrees 和子目录共享一份记忆:
~/.claude/projects/<project-slug>/memory/
├── MEMORY.md ← 核心索引,每次会话加载前 200 行
├── debugging.md ← 调试经验细节
├── api-conventions.md ← API 设计决策记录
└── ... ← Claude 按需创建的主题文件
MEMORY.md 是个索引,详细内容被拆分到主题文件里。主题文件不在启动时加载,Claude 在需要时才按需读取------这是一个精心设计的分层懒加载机制。
如何手动干预
不必被动等待 Claude 自己归纳。直接在对话里告诉它:
- "记住,这个项目永远用 pnpm,不用 npm" → Claude 会写入自动记忆
- "把这条规则加到 CLAUDE.md" → 明确指定存储位置
- 运行
/memory命令 → 查看、切换、浏览所有记忆文件
五、两者的协作关系
正确的使用姿势不是"二选一",而是分工明确地同时使用:
CLAUDE.md 负责"标准":项目应该怎么做,团队约定是什么,这些内容是主动设计的,不应该等 AI 自己去猜。
MEMORY.md 负责"经验":实际协作中发现的技巧、踩过的坑、个人习惯的积累,这些内容随着项目推进自然生长。
两者都在每次会话开始时注入上下文,共同构成 Claude 对这个项目的"背景知识"。
一个实战建议:当你发现自己在对话里重复告诉 Claude 同一件事时------
- 如果是项目规范,把它写进
CLAUDE.md - 如果是踩过的坑或偏好,告诉 Claude "记住这个",让自动记忆来处理
六、常见问题
Q:CLAUDE.md 超过 200 行会怎样?
不会报错,但 Claude 遵守度会下降。解决方案是用 @ 引用拆分到多个文件,或使用 .claude/rules/ 目录按路径配置规则。
Q:MEMORY.md 可以手动编辑吗?
可以。它是纯 Markdown 文件,在 ~/.claude/projects/<project>/memory/ 目录下,可以直接打开编辑。但手动编辑的内容下次对话时 Claude 也会读到,注意保持格式整洁。
Q:团队项目里如何处理个人偏好和团队规范的冲突?
个人偏好放 CLAUDE.local.md(加入 .gitignore 不提交),团队规范放 CLAUDE.md(提交 Git 共享)。两者都会被加载,本地文件在后,优先级更高。
Q:如果想强制 Claude 执行某个操作,写在 CLAUDE.md 里够吗?
不够。CLAUDE.md 是行为引导,不是硬性约束。如果需要强制拦截或触发某些操作,应该使用 Claude Code 的 Hooks 机制(PreToolUse hook),那才是真正的约束层。
七、总结
用一句话概括两者的本质差异:
两轨并行,各司其职。理解这个区别之后,AI 配置的混乱感会减少大半------不再是一个黑盒,而是两个有明确边界的协作文件。