☰
深入理解 Claude Code 的记忆系统:从 CLAUDE.md 到 Auto Memory 的配置与验证
2026/10/2 13:54:37 网站建设 项目流程

1. 为什么你的 Claude Code 每次会话都像“失忆”

如果你用 Claude Code 写过几天代码,大概率遇到过这种场景:昨天刚跟它强调过“这个项目所有接口必须做参数校验”,今天新开一个会话,它又给你生成了一段裸奔的 controller;上周纠正过它“别用 moment.js,我们统一用 dayjs”,这周它又默默 import 了 moment。每次会话都从零开始解释项目规范,时间全花在重复沟通上。

这不是模型变笨了,而是 AI 编程助手的一个天然短板——会话之间没有持久记忆。每次启动,它看到的只有当前工作目录的代码和你在本次对话里说过的话。你昨天说的、上周纠正的,全都不在上下文里。

Claude Code 用一套分层记忆系统来解决这个问题。这套系统由两大部分组成:你主动写给 Claude 的指令记忆(CLAUDE.md 体系),和 Claude 自己写给自己的自动记忆(Auto Memory)。前者是“你告诉它该怎么做”,后者是“它自己记下做过什么、踩过什么坑”。

这篇文章面向需要长期维护上下文一致性的开发者,目标很明确:把记忆配置落到可复制的 settings.json 骨架和CLAUDE.md 模板里,并给出验证记忆是否真的生效的具体动作。不是概念科普,是能直接抄进项目的操作手册。

先给一个全局认知:Claude Code 的记忆不是“一个文件”,而是五层作用域 + 两类记忆源的组合。理解这个分层,你才知道一条规则该写在哪、为什么有时候写了却不生效。

五层作用域从“管得最宽”到“管得最细”依次是:

层级位置作用范围谁能改
托管策略系统级路径(如/etc/claude-code/CLAUDE.md)整台机器所有用户IT 统一下发,无法排除
用户记忆~/.claude/CLAUDE.md你本人的所有项目你自己
项目记忆<项目根>/CLAUDE.md或<项目根>/.claude/CLAUDE.md随仓库提交,全团队共享团队
本地记忆<项目根>/CLAUDE.local.md只属于你、只在本项目你自己(应加 .gitignore)
子目录记忆<子目录>/CLAUDE.md按需懒加载对应模块负责人

加载机制是向上遍历 + 拼接。假设你在D:\projects\my-app\backend启动 Claude Code,它会从当前目录一路向上遍历到文件系统根,把沿途所有CLAUDE.md/CLAUDE.local.md收集起来,按“根 → 当前目录”的顺序拼接进上下文。注意是拼接,不是覆盖——所有指令都会被模型看到并综合权衡。

这里有个很多人误解的点:没有硬性的“后加载覆盖先加载”规则。LLM 的上下文不像 CSS 那样有明确的层叠优先级。Claude Code 确实故意把离工作目录更近(更具体)的文件排在后面加载,位置靠后、离当前对话更近的内容在注意力上通常权重略高,所以项目规则倾向于压过用户全局规则——但这只是软倾向,不是保证。官方文档明确警告:如果两条指令真的互相矛盾,Claude 可能任选其一,行为不可预测。

所以正确的做法不是依赖“后写的赢”,而是定期审查各层文件,主动消除冲突。这也是后面排查章节要重点讲的内容。

2. TaoToken 前置:把 Base URL、Key、Model ID 三件套配好

在深入记忆配置之前,得先把 Claude Code 的接入环境搭好。因为记忆系统的验证动作(比如让它读文件、执行命令、观察是否遵守规则)都需要一个能正常工作的模型端点。我用的是 TaoToken 的接入方式,它兼容 Anthropic 的 API 协议,配置起来比较直接。

Claude Code 的接入核心是三个东西:Base URL、API Key、Model ID。这三件套缺一不可,而且必须写对位置。很多人配完发现报 401 或者local proxy failed,八成是这三个里有一个没对上。

先说 Base URL。TaoToken 的 API 端点是:

https://taotoken.net/api

注意这里不加任何 UTM 参数,就是干净的 API 地址。Claude Code 会往这个地址发 Anthropic 格式的请求。

然后是 API Key。你需要去控制台生成一个:

https://taotoken.net/console

生成后复制那串sk-开头的密钥,妥善保存——它只显示一次。

最后是 Model ID。Claude Code 默认会用 Anthropic 的模型名,但通过 TaoToken 接入时,你需要确认可用的模型标识。可以在模型对话页面先试一下:

https://taotoken.net/model-chat

在对话界面里选一个模型发条消息,确认能正常返回,再把这个 Model ID 填进配置。

三件套的配置位置有两个选择:环境变量,或者 Claude Code 的 settings.json。环境变量适合临时测试,settings.json 适合长期使用。我建议直接用 settings.json,因为记忆系统的很多配置(比如autoMemoryEnabled、claudeMdExcludes)也在这个文件里,集中管理更清晰。

一个最小的 settings.json 骨架长这样:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的密钥", "ANTHROPIC_MODEL": "你的模型ID" }, "autoMemoryEnabled": true }

这个文件放在~/.claude/settings.json(用户级)或<项目根>/.claude/settings.json(项目级)。项目级的会覆盖用户级的同名配置。

如果你更习惯用环境变量,在 shell 里这样写:

export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的密钥" export ANTHROPIC_MODEL="你的模型ID"

Windows PowerShell 用:

$env:ANTHROPIC_BASE_URL="https://taotoken.net/api" $env:ANTHROPIC_API_KEY="sk-你的密钥" $env:ANTHROPIC_MODEL="你的模型ID"

配完之后,先别急着搞记忆系统,跑一个最简单的验证:启动 Claude Code,问它一句“你现在用的是什么模型”。如果它能正常回答,说明三件套通了。如果报错,对照第 5 节的排查表处理。

这里要强调一点:记忆系统的所有验证动作都依赖模型端点正常工作。如果 Base URL 或 Key 配错了,你看到的“Claude 不遵守 CLAUDE.md”可能根本不是记忆问题,而是请求压根没发出去。所以先把接入层跑通,再谈记忆。

另外,如果你打算长期用 Claude Code 做编码和 Agent 任务,可以考虑 Coding Plan,它在连续编码场景下的额度更划算:

https://taotoken.net/coding-plan

接入文档在这里,遇到配置细节可以查:

https://taotoken.net/doc

3. 可复制配置:settings.json 骨架与 CLAUDE.md 模板

这一节是全文的核心,直接给你能抄的配置。分三块:settings.json 完整骨架、CLAUDE.md 项目模板、以及.claude/rules/的路径作用域规则。

3.1 settings.json 完整骨架

先给一个覆盖记忆系统关键配置的 settings.json。放在<项目根>/.claude/settings.json:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的密钥", "ANTHROPIC_MODEL": "你的模型ID" }, "autoMemoryEnabled": true, "autoMemoryDirectory": "~/.claude/projects/my-app-memory", "claudeMdExcludes": [ "**/monorepo/other-team/CLAUDE.md", "**/monorepo/legacy/.claude/rules/**" ] }

逐个字段说明:

autoMemoryEnabled控制自动记忆开关,默认是true。如果你想临时关掉,改成false,或者用环境变量CLAUDE_CODE_DISABLE_AUTO_MEMORY=1。

autoMemoryDirectory自定义自动记忆的存储位置。必须是绝对路径或~/开头。不写的话默认在~/.claude/projects/<项目标识>/memory/。写在项目级 settings 时,需要先通过工作区信任确认。

claudeMdExcludes用 glob 模式排除不需要加载的 CLAUDE.md。这个在 monorepo 场景特别有用——当你在team-b/frontend/工作时,向上遍历会把仓库根、甚至中间层其他团队的 CLAUDE.md 全加载进来,白白消耗上下文还可能引入矛盾指令。注意托管策略层的 CLAUDE.md 无法被排除,这是唯一的例外。

如果你用 Claude Code 的本地配置(不进 git),可以再建一个.claude/settings.local.json,把个人偏好放进去:

{ "autoMemoryDirectory": "~/my-personal-memory" }

3.2 CLAUDE.md 项目模板

项目根的 CLAUDE.md 是团队共识的沉淀地。官方建议控制在 200 行以内,写具体可验证的指令,比如“用 2 空格缩进”而不是“格式规范一点”。下面是一个可直接用的模板:

# 项目:my-app ## 技术栈 - 后端:Node.js 20 + TypeScript 5 - 前端:React 18 + Vite - 数据库:PostgreSQL 15 ## 构建与测试 - 安装依赖:`pnpm install` - 启动开发:`pnpm dev` - 跑测试:`pnpm test` - 提交前必须跑:`pnpm lint && pnpm test` ## 编码规范 - 缩进用 2 空格 - 所有接口必须做输入校验,用 zod - 日期统一用 ISO 8601 格式 - 禁止使用 moment.js,统一用 dayjs ## 架构约定 - API 层在 `src/api/`,业务逻辑在 `src/services/` - 数据库查询统一走 repository 层,不直接在 service 里写 SQL ## 工作流 - git 提交信息用 Conventional Commits - 详见 @docs/git-instructions.md <!-- 维护说明:本文件由团队共同维护,改动请提 PR -->

注意最后那行 HTML 注释——CLAUDE.md 支持 HTML 块级注释<!-- ... -->,注入上下文前会被剥离,所以可以用来写只给人看的维护说明,不占模型上下文。

@docs/git-instructions.md是@import语法,把外部文件内容“钉”进上下文。语法要点:

  • 相对路径相对于包含该导入的文件解析,不是工作目录
  • 支持绝对路径和~/家目录路径
  • 最大递归深度 4 层
  • 代码块和行内代码中的@xxx不会被解析,想字面提到路径用反引号包住:`@README`
  • 项目里首次遇到外部导入时会弹一次批准对话框

这里有个关键取舍:@import和纯文本提及路径的本质区别在于内容进不进上下文。@docs/api.md会在启动时立即注入整个文件内容,保证 Claude 看到,但每次会话都消耗 token;而纯文本写“参见 docs/api.md”只是一个字符串,零成本,但 Claude 需要自己决定去读,可能读也可能不读。

选择原则:每次会话都必须遵守的规则用 @import(保证在场);偶尔才需要的参考资料用文本路径提及(省 token,按需读取)。官方那句提醒很到位——“import 帮你组织文件,但不省 token”,它本质上等于把内容复制进了 CLAUDE.md。

3.3 .claude/rules/ 路径作用域规则

当项目规则越写越多,塞在一个 CLAUDE.md 里既难维护又浪费上下文。.claude/rules/目录允许把指令拆成模块化文件,目录下所有.md会被递归发现:

your-project/ ├── .claude/ │ ├── CLAUDE.md │ └── rules/ │ ├── code-style.md │ ├── testing.md │ └── frontend/ │ └── react.md

最有价值的能力是路径作用域规则——通过 YAML frontmatter 声明paths,让规则只在 Claude 操作匹配文件时才加载:

--- paths: - "src/api/**/*.ts" --- # API 开发规范 - 所有接口必须做输入校验 - 使用标准错误响应格式 - 每个 handler 必须有对应的单元测试

没有paths字段的规则文件则与 CLAUDE.md 一样,启动时无条件加载。个人通用规则可以放在~/.claude/rules/(先于项目规则加载,因此项目规则的实际影响力更高);跨项目共享规则可以直接用符号链接。

顺带解释一下 YAML frontmatter:指 Markdown 文件开头用两行---包起来的元数据块,内容是 YAML 格式的键值对。它给“读这个文件的程序”提供结构化信息,正文才是给人或模型看的内容。这个约定最早来自 Jekyll 等静态博客生成器,如今已是 Markdown 生态的通用惯例。Claude Code 生态里多处用到它:rules 文件的paths、技能文件(SKILL.md)的name/description、子代理定义的模型与工具声明,以及自动记忆文件的元信息。

4. 验证请求:确认记忆真的生效了

配置写完不代表生效。这一节给你一套可执行的验证动作,从接入层到记忆层逐级确认。

4.1 第一步:确认模型端点通

启动 Claude Code,先跑一个不依赖记忆的基础请求:

claude "用一句话说明你现在能做什么"

如果正常返回,说明 Base URL、Key、Model ID 三件套没问题。如果报 401,看第 5 节。

4.2 第二步:用 /memory 查看加载了哪些记忆

这是排查记忆问题的第一命令。在 Claude Code 会话里输入:

/memory

它会列出当前会话到底加载了哪些记忆文件。你应该能看到:

  • 用户级~/.claude/CLAUDE.md(如果存在)
  • 项目级<项目根>/CLAUDE.md
  • 本地级<项目根>/CLAUDE.local.md(如果存在)
  • 自动记忆的MEMORY.md索引

如果某个你期望的文件没出现在列表里,说明它没被加载——可能是路径不对,或者被claudeMdExcludes排除了。

4.3 第三步:验证 CLAUDE.md 指令被遵守

在 CLAUDE.md 里写一条可验证的具体规则,比如:

## 编码规范 - 所有新建的 TypeScript 文件必须包含文件头注释 `// @file: <文件名>`

然后让 Claude 创建一个新文件:

claude "在 src/utils/ 下新建一个 formatDate.ts,导出一个格式化日期的函数"

打开生成的文件,看开头有没有// @file: formatDate.ts。有,说明项目记忆生效了;没有,说明 CLAUDE.md 没被加载或指令不够具体。

4.4 第四步:验证自动记忆在工作

自动记忆的验证看界面提示。当 Claude 在会话中读写记忆时,界面会出现“Writing memory”或“Recalled memory”提示。

你可以主动触发一次:在会话里纠正它一个习惯,比如“以后这个项目里所有日期都用 dayjs,不要用原生 Date”。然后观察是否出现 “Writing memory” 提示。如果有,说明 Claude 把这条经验记下来了。

再验证读取:新开一个会话,问它“这个项目里日期处理用什么库”。如果它回答 dayjs,说明自动记忆被成功召回。

你也可以直接去看存储目录:

ls ~/.claude/projects/<项目标识>/memory/

应该能看到MEMORY.md和若干主题文件(如debugging.md、api-conventions.md)。全是纯 Markdown,随时可以打开审查、编辑或删除。

4.5 第五步:验证路径作用域规则

在.claude/rules/下建一个带paths的规则文件,比如api-rules.md,声明paths: ["src/api/**/*.ts"],里面写一条“所有 API handler 必须返回{ code, data, message }结构”。

然后让 Claude 在src/api/下改一个文件,观察它是否遵守这条规则。再让它在src/services/下改文件,观察这条规则是否不生效(因为路径不匹配)。如果两次行为符合预期,说明路径作用域规则工作正常。

4.6 第六步:验证 @import 生效

在 CLAUDE.md 里写@docs/api-conventions.md,然后在那个文件里写一条独特规则。新开会话,用/memory确认该文件被加载,再让 Claude 执行一个相关任务,看它是否遵守。

如果@import没生效,检查:路径是否相对于包含导入的文件、递归深度是否超过 4 层、是否在代码块里被反引号包住了。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth

这一节对照真实报错,逐个给排查路径。这些错误我在配置过程中基本都踩过一遍。

5.1 401 Unauthorized

现象:启动 Claude Code 后任何请求都返回 401。

原因:API Key 不对,或者 Base URL 配错导致请求发到了错误的端点。

排查:

  1. 确认ANTHROPIC_API_KEY是sk-开头且没有多余空格
  2. 确认ANTHROPIC_BASE_URL是https://taotoken.net/api,结尾没有斜杠,也没有多余路径
  3. 去控制台重新生成一个 Key 试试:https://taotoken.net/api-keys
  4. 检查是否有多个配置源冲突——环境变量和 settings.json 同时存在时,环境变量通常优先

如果 Key 是对的但还报 401,可能是 Key 被禁用或额度耗尽,去控制台确认。

5.2 local proxy failed

现象:报local proxy failed或类似的连接失败。

原因:通常是 Base URL 写错,或者本地网络无法到达端点。

排查:

  1. 用 curl 直接测端点连通性:
curl -X POST https://taotoken.net/api/v1/messages \ -H "x-api-key: sk-你的密钥" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{"model":"你的模型ID","max_tokens":100,"messages":[{"role":"user","content":"hi"}]}'

如果 curl 能通但 Claude Code 不通,说明是 Claude Code 的配置问题,检查 settings.json 的env字段是否被正确读取。

  1. 确认没有多余的代理环境变量干扰,比如HTTP_PROXY、HTTPS_PROXY指向了不可用的地址。

5.3 reading choices 相关报错

现象:报错信息里出现reading choices或响应解析失败。

原因:这通常是响应格式不匹配——请求发出去后,返回的不是 Anthropic 期望的格式。常见于 Base URL 指向了一个 OpenAI 兼容端点而非 Anthropic 兼容端点。

排查:

  1. 确认 Base URL 是https://taotoken.net/api,这个端点走的是 Anthropic 协议
  2. 确认 Model ID 是 Anthropic 系列模型,不要填成 GPT 系列的模型名
  3. 如果之前配过其他端点,检查环境变量里有没有残留的ANTHROPIC_BASE_URL覆盖了 settings.json

5.4 OAuth 相关报错

现象:提示需要 OAuth 登录,或者OAuth token expired。

原因:Claude Code 某些功能(比如 Claude Code 官方订阅)走 OAuth 流程。如果你用的是 API Key 接入,不应该触发 OAuth。

排查:

  1. 确认你没有同时启用官方 OAuth 登录和 API Key 接入,两者会冲突
  2. 检查~/.claude/下是否有残留的 OAuth 凭证文件,有的话清理掉
  3. 确认 settings.json 里没有oauth相关字段

5.5 Claude 不遵守 CLAUDE.md

这是记忆系统最典型的“软故障”,没有报错,但行为不对。

排查顺序:

  1. 跑/memory确认文件确实被加载了
  2. 检查指令是否够具体——“格式规范一点”这种模糊指令模型无法执行,改成“用 2 空格缩进”
  3. 排查多层文件之间有没有互相矛盾的规则——冲突时 Claude 可能任选其一
  4. 需要精确诊断时,用InstructionsLoadedhook 记录哪些指令文件在何时、为何被加载

5.6 /compact 之后指令丢了

现象:上下文压缩后,之前说的规则不生效了。

原因:项目根的 CLAUDE.md 会在压缩后自动重新注入,但子目录的嵌套 CLAUDE.md 不会——要等 Claude 下次读取那个目录的文件才重新加载。只在对话里口头说过的指令,压缩后就没了。

解决:重要的规则一定要落到 CLAUDE.md,不要只在对话里说。

5.7 CLAUDE.md 太大了

现象:CLAUDE.md 越写越长,启动上下文被占满。

解决:

  1. 拆成路径作用域规则,放到.claude/rules/下
  2. 删掉不是每次会话都需要的内容
  3. 注意@import拆分只改善组织结构、不减少 token——它等于把内容复制进来
  4. 用 HTML 注释<!-- ... -->写维护说明,注入前会被剥离

6. 选型与长期维护:规则给 CLAUDE.md,经验给 Auto Memory

把两类记忆放在一起对比,选型就清晰了:

维度CLAUDE.mdAuto Memory
谁来写你 / 团队Claude 自动
内容性质规则、指令、标准经验、发现、习惯
上下文成本全文加载仅索引前 200 行 / 25KB
适合放什么编码规范、架构决策、工作流构建命令、调试心得、易变信息

更广义的选型原则——记忆系统不是万能的,官方明确建议分流:

稳定的项目规则 → CLAUDE.md。目标控制在 200 行以内,写具体可验证的指令。

只对某些目录/文件生效的规则 → .claude/rules/ 路径作用域规则。用pathsfrontmatter 精准投放,不占全局上下文。

多步骤操作流程 → Skills。按需加载,不占每次启动的上下文。

必须在固定时机强制执行的动作(如每次提交前 lint)→ Hooks。这一条尤其重要:Hooks 由客户端强制执行,不依赖 Claude 的判断;而 CLAUDE.md 只是“影响行为”,不是硬约束。

经常变化的信息 → 交给自动记忆。构建命令、调试发现、你的纠正反馈,让 Claude 自己积累。

关于自动记忆的存储结构,再补充一下细节。每个项目在用户主目录下有独立目录:

~/.claude/projects/<项目标识>/memory/ ├── MEMORY.md # 索引文件(启动时加载前 200 行或前 25KB) ├── debugging.md # 主题文件(按需读取) ├── api-conventions.md # 主题文件(按需读取) └── ...

项目标识基于 git 仓库派生,同一仓库的所有 worktree 和子目录共享一份记忆;不在 git 仓库中则按项目根目录计算。记忆是本机私有的,不跨机器同步。全部是纯 Markdown,你可以随时打开审查、编辑或删除。

自动记忆的加载设计很精巧:启动时只加载MEMORY.md的前 200 行或前 25KB(先到为准),因此 Claude 会主动保持索引精简,把细节挪到主题文件;主题文件不占启动上下文,Claude 需要时才用普通文件工具按需读取。

开关控制有三种方式:/memory命令中直接切换、settings.json 里设"autoMemoryEnabled": false、环境变量CLAUDE_CODE_DISABLE_AUTO_MEMORY=1。子代理(subagent)也可以单独启用自己的持久记忆。

最后说一个日常操作技巧:#快捷键。消息以#开头,内容会被存入记忆:

# 提交前必须先跑测试

存储目标不是固定的。较早版本会弹选择器让你挑目标文件;引入自动记忆后的版本由 Claude 根据内容性质判断归属——像“规则/指令”的内容倾向写入 CLAUDE.md,像“经验/发现”的内容倾向写入自动记忆。想精确控制去向,直接在消息里说明:

# 把这条加到项目 CLAUDE.md:所有日期用 ISO 8601 格式。

还有一个/init命令值得用:分析代码库自动生成初始 CLAUDE.md(已存在则给出改进建议而非覆盖),会自动发现构建命令、测试方式和项目约定,还会读取.cursorrules、AGENTS.md、.windsurfrules等其他工具的规则文件并吸收其内容。设置环境变量CLAUDE_CODE_NEW_INIT=1可启用交互式多阶段初始化流程。

关于 AGENTS.md 这个跨工具约定,Claude Code 有两条支持路径:一是导入复用,在 CLAUDE.md 里写一行@AGENTS.MD,通用规则放 AGENTS.md 供所有工具共享,Claude 专属规则继续写在 CLAUDE.md 里;二是/init初始化时自动读取并整合其内容。团队同时用多个 AI 编程工具时,这个约定能省掉重复维护规范的麻烦。

用好记忆系统的关键不在于把所有东西都塞进去,而在于理解每类信息的正确归宿:规则给 CLAUDE.md,流程给 Skills,强制动作给 Hooks,经验交给自动记忆。当你发现自己第三次向 Claude 解释同一件事时,那就是该写入记忆的信号。

如果你还没配好接入环境,先去 API Keys 页面生成密钥:

https://taotoken.net/api-keys

配置细节查接入文档:

https://taotoken.net/doc

想先试试模型对话确认端点通不通:

https://taotoken.net/model-chat

长期做编码和 Agent 任务的话,Coding Plan 的额度更合适:

https://taotoken.net/coding-plan

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询