你有没有这样的经历:每次新开Claude Code会话,都要重复说"我是后端工程师"、“这个项目用Bun构建”、“不要用mock测试数据库”?

没有记忆的AI就像金鱼——每次对话都从零开始。今天咱们聊聊Claude Code的跨会话记忆系统,看AI如何"长记性"。

六层记忆架构

Claude Code的记忆系统有六个层次,从高频增量到低频全局:

层级核心文件频率职责
Memdirmemdir/memdir.ts每次会话MEMORY.md索引+主题文件,注入系统提示词
Extract MemoriesextractMemories.ts每轮结束Fork agent自动提取记忆
Session MemorysessionMemory.ts定期触发滚动会话摘要,用于压缩
TranscriptsessionStorage.ts每消息JSONL会话记录存储与恢复
Agent MemoryagentMemory.tsAgent生命周期子Agent持久化+VCS快照
Auto-DreamautoDream.ts每日夜间记忆整合与修剪

这就像人类记忆的层次:

  • Memdir:长期记忆库
  • Extract Memories:短期记忆编码
  • Session Memory:工作记忆摘要
  • Transcript:完整记忆备份
  • Agent Memory:专业技能记忆
  • Auto-Dream:睡眠记忆整理

Memdir:记忆的存储层

记忆目录位置

三级优先链决定记忆存储位置:

  1. CLAUDE_COWORK_MEMORY_PATH_OVERRIDE环境变量
  2. autoMemoryDirectory设置(排除projectSettings防恶意重定向)
  3. 默认:~/.claude/projects/<git-root>/memory/

所有worktree共享同一个记忆目录——记忆是关于项目的,不是关于工作目录的。

MEMORY.md索引

MEMORY.md是记忆系统的入口点,每行指向一个主题文件:

- [编码规范](coding-style.md) - 项目TypeScript编码规范
- [数据库配置](database.md) - PostgreSQL连接信息
- [API文档](api-reference.md) - REST API端点列表

双重截断防止膨胀

  • 最多200行
  • 最多25KB

截断时追加WARNING消息,提示模型将详细内容移到主题文件——自修复机制。

主题文件格式

每个记忆是独立Markdown文件,YAML frontmatter标注元数据:

---
name: 编码规范
description: TypeScript项目代码风格指南
type: project
---

- 使用2空格缩进
-  prefer `const` over `let`
-  ...

四种类型:

  • user:用户角色、偏好、知识水平
  • feedback:用户对Agent行为的纠正和指导
  • project:正在进行的工作、目标、截止日期
  • reference:外部系统的指针(Linear、Grafana等)

KAIROS日志模式

KAIROS长期运行模式下,记忆写入策略变为追加到每日日志文件:

memory/logs/2026/04/2026-04-03.md

Append-only策略避免频繁重写,蒸馏交给夜间Auto-Dream处理。

Extract Memories:自动记忆提取

触发机制

每轮查询结束时,fork agent静默分析对话并提取值得持久化的信息。

触发条件:

  • 仅主Agent(排除子Agent)
  • Fire-and-forget(不阻塞下一轮)

节流与互斥

节流tengu_bramble_lintel flag控制频率(默认每轮运行)

互斥:当主Agent自己写了记忆文件,fork agent跳过本轮提取。避免两个agent同时写入同一文件的冲突。

权限隔离

fork agent的权限被严格限制:

  • 允许:Read/Grep/Glob(只读)
  • 允许:Bash(仅lsfindgrepcat等只读命令)
  • 允许:Edit/Write(仅memoryDir内路径)
  • 拒绝:所有其他工具(MCP、Agent、写入式Bash等)

高效操作策略

提取agent的提示词明确指示:

第1轮:并行读取所有可能要更新的文件
第2轮:并行执行所有写入/编辑操作

最大轮次限制为5,防止陷入验证循环。

Session Memory:滚动会话摘要

Session Memory解决的是会话内的信息保留。当上下文接近饱和时,为压缩系统提供"什么是重要的"信号。

三重阈值保护

{
  minimumMessageTokensToInit: 10000,  // 首次触发:10K token
  minimumTokensBetweenUpdate: 5000,   // 更新间隔:5K token
  toolCallsBetweenUpdates: 3          // 最低工具调用数:3
}

触发条件:

  • token阈值(5K)必须满足
  • 加上:(a) 工具调用数≥3,或(b) 最后一个assistant轮次没有工具调用(自然对话断点)

这样不会在短对话中触发,也不会在密集工具调用中间打断工作流。

与自动压缩的关系

Session Memory注册为post-sampling hook。但初始化门控检查isAutoCompactEnabled()——如果自动压缩被禁用,Session Memory也不运行。

Session Memory的主要消费者就是压缩系统。摘要文件summary.md在压缩时被注入。

与Extract Memories的区别

维度Session MemoryExtract Memories
持久化范围会话内跨会话
存储位置~/.claude/projects/<root>/<session-id>/session-memory/~/.claude/projects/<root>/memory/
触发时机token阈值+工具调用阈值每轮查询结束
消费者压缩系统下次会话的系统提示词
内容结构固定章节模板自由格式主题文件

两者并行运行,互不干扰。

Transcript Persistence:完整会话记录

sessionStorage.ts(5105行,最大单文件之一)负责将会话记录持久化为JSONL格式。

JSONL格式

每条消息序列化为一行JSON,追加到会话文件:

{"type":"user","content":"帮我重构这个模块","timestamp":"2026-04-03T10:00:00Z"}
{"type":"assistant","content":"好的,让我先理解代码结构","tool_uses":[{"name":"Read","input":{"file_path":"/src/app.ts"}}]}

JSONL的选择是出于性能——增量追加只需appendFile,不需要解析和重写整个文件。

特殊条目类型

除了标准user/assistant消息,还包含:

  • file_history_snapshot:文件历史快照,用于压缩后恢复文件状态
  • attribution_snapshot:归因快照,记录文件修改来源
  • context_collapse_snapshot:压缩边界标记
  • content_replacement:内容替换记录,用于REPL模式输出截断

会话恢复

claude --resume时:

  1. 解析所有JSONL条目
  2. 根据uuid/parentUuid重建消息树
  3. 应用context_collapse_snapshot,恢复到压缩后的状态
  4. 重建文件历史快照,确保模型对文件状态的理解与磁盘一致

这使得跨会话"续写"成为可能。

Agent Memory:子Agent持久化

子Agent有自己的记忆需求:

  • 代码审查agent需要记住团队代码风格偏好
  • 测试agent需要记住项目测试框架配置

三作用域模型

作用域路径可提交到VCS用途
user~/.claude/agent-memory/<agentType>/跨项目的用户级偏好
project<cwd>/.claude/agent-memory/<agentType>/团队共享的项目知识
local<cwd>/.claude/agent-memory-local/<agentType>/本机特定的项目配置

每个作用域独立维护MEMORY.md索引和主题文件。

VCS快照同步

project作用域的记忆应该通过Git在团队间共享,但.claude/agent-memory/.gitignore中。

解决方案是单独的快照目录.claude/agent-memory-snapshot/,通过snapshot.json中的updatedAt时间戳追踪版本。

三种策略:

  • none:无快照
  • initialize:复制快照到本地
  • prompt-update:提示模型合并(不自动覆盖)

Auto-Dream:夜间记忆整合

Auto-Dream是记忆系统的"睡眠阶段"——后台整合任务,需要同时满足时间门控(默认24小时)和会话门控(默认5个新会话)。

四层门控系统

第一层:Master Gate

if (getKairosActive()) return false      // KAIROS模式用自己的dream skill
if (getIsRemoteMode()) return false      // 远程模式存储不可靠
if (!isAutoMemoryEnabled()) return false
return isAutoDreamEnabled()

第二层:Time Gate

  • 距上次整合至少24小时
  • 时间信息通过锁文件的mtime获取

第三层:Session Gate

  • 上次整合以来至少有5个新会话被修改
  • 扫描有10分钟冷却期

第四层:Lock Gate

  • 获取并发锁
  • 如果另一进程正在整合,当前进程放弃

PID锁机制

锁文件.consolidate-lock承载双重语义:

  • mtime = lastConsolidatedAt(上次整合时间)
  • 文件内容 = 持有者PID

获取锁的流程:

  1. stat + readFile获取mtime和PID
  2. 如果mtime在1小时内且PID存活 → 被占用
  3. 如果PID已死或mtime过期 → 回收锁
  4. 写入自己的PID
  5. 重新读取验证(防止竞态条件)

四阶段整合

整合agent收到结构化提示词:

Phase 1 - Orient:浏览记忆目录、读MEMORY.md、浏览主题文件

Phase 2 - Gather:搜索日志和会话记录寻找新信号

Phase 3 - Consolidate:合并到现有文件、消除矛盾、相对日期→绝对日期

Phase 4 - Prune & Index:保持MEMORY.md在200行/25KB内

提示词强调"合并优于创建"、“修正优于保留”,防止记忆文件无限增长。

高频增量+低频全局

Extract Memories和Auto-Dream形成互补架构:

用户对话
Query Loop结束
Extract Memories(每轮)──→ 写入主题文件 / 追加日志(KAIROS模式)
Auto-Dream(定期)────────→ 读取日志+主题文件,整合后写回
下次会话加载 ─────────────→ 系统提示词注入
维度Extract MemoriesAuto-Dream
频率每轮(可节流)每日(24h+5会话)
输入最近N条消息整个记忆目录+会话记录
操作创建/更新主题文件合并、修剪、消除矛盾
类比短期记忆→长期记忆的编码睡眠中的记忆整合

实战:管理你的记忆

管理MEMORY.md

理解200行限制是关键。如果索引超过200行,后面条目会被截断。

最佳实践

  • 最重要的条目排前面
  • 每个索引条目控制在一行150字符以内
  • 将详细内容移到主题文件

理解什么会被记住

四种类型各有最佳用途:

feedback(最有价值):

  • “不要用mock测试数据库”
  • “prefer early return over nested if”
  • 直接改变Agent行为

user

  • “我是后端工程师,不熟悉前端”
  • 帮助Agent调整沟通风格

project

  • “目标是在本周五前完成重构”
  • 有时效性,需要定期清理

reference

  • “Grafana面板:https://…”
  • 外部资源快捷方式,保持简短

控制自动记忆

# 完全禁用所有自动记忆
export CLAUDE_CODE_DISABLE_AUTO_MEMORY=1

settings.json

{
  "autoMemoryEnabled": false,    // 按项目禁用
  "autoDreamEnabled": false      // 只禁用夜间整合,保留即时提取
}

手动触发整合

使用/dream命令即时运行记忆整合:

  • 完成大型重构后,更新项目上下文
  • 团队成员切换后,整理个人偏好
  • 发现记忆文件中有过时或矛盾信息

CLAUDE.md vs 记忆系统

两者互补:

  • CLAUDE.md:存储不应被修改的指令(编码规范、架构约束、团队流程)
  • 记忆系统:存储可以演化的知识(用户偏好、项目上下文、外部引用)

如果某个信息不应该被Auto-Dream修剪或修改,放在CLAUDE.md中。

这对构建AI Agent的启示

模式1:多层记忆架构

将记忆系统分为三层:

  • 原始信号层(日志/会话记录):高频低质
  • 结构化知识层(主题文件):中频中质
  • 索引层(MEMORY.md):低频高质

模式2:后台提取via Fork Agent

  • 在查询循环结束时启动fork agent
  • 继承父对话的prompt cache降低成本
  • 严格权限隔离(只能写入记忆目录)
  • 与主agent通过互斥检查协调

模式3:文件mtime即状态

使用锁文件,其mtime即lastConsolidatedAt,内容即持有者PID。通过stat/utimes/writeFile实现读取、获取、回滚。

模式4:预算约束的记忆注入

多级截断防止记忆无限增长:

  • MEMORY.md最多200行/25KB
  • 最多200个记忆文件
  • Session Memory每节2000 token,总量12000 token

模式5:互补频率设计

双频策略:

  • 高频增量提取:捕获所有可能有价值的信号,容忍误报
  • 低频全局整合:修剪噪音、消除矛盾、合并重复,修复误报

总结

跨会话记忆是Claude Code从"无状态函数"进化为"有状态助手"的关键:

  • 六层架构:从高频增量到低频全局
  • 自动提取:每轮fork agent静默分析
  • 会话摘要:为压缩系统提供重要信号
  • 完整记录:JSONL格式支持会话恢复
  • 子Agent记忆:三作用域模型支持专业化
  • 夜间整合:Auto-Dream像睡眠一样整理记忆

这就像人类记忆的工作原理:

  • 白天:不断接收新信息(Extract Memories)
  • 晚上:睡眠中整理巩固(Auto-Dream)
  • 长期:形成结构化知识库(Memdir)

理解记忆系统,你就能:

  • 更高效地管理项目上下文
  • 让AI真正"长记性"
  • 在自己的AI Agent中实现持久学习

下篇咱们聊聊驾驭工程原则——从Claude Code学到的架构智慧。