【无标题】

Claude Code Memory 系统深度解析

本文基于 Claude Code 源代码(src/目录)深入分析其 Memory 机制的设计与实现。


一、Memory 系统总览

Claude Code 的 Memory 系统是一个多层次、多类型的持久化知识管理体系。它解决的核心问题是:如何让 AI 助手在不同会话之间保留有价值的上下文信息,同时避免信息污染

系统分为两大层:

  1. 指令型记忆(Instruction Memory)CLAUDE.md 文件体系,存储用户/团队对 AI 行为的持久指令
  2. 事实型记忆(Fact Memory):AutoMem/MEMORY.md 体系,AI 自动从对话中提炼并持久化的知识点

二、记忆类型体系

2.1 文件层面的 Memory 类型(MemoryType)

源码:src/utils/memory/types.tssrc/utils/claudemd.ts

类型 文件路径 说明
Managed /etc/claude-code/CLAUDE.md 机构级全局策略,对所有用户生效
User ~/.claude/CLAUDE.md + ~/.claude/rules/*.md 用户私有全局指令,适用于所有项目
Project CLAUDE.md.claude/CLAUDE.md.claude/rules/*.md 项目级指令,提交到代码仓库
Local CLAUDE.local.md 用户私有的项目级指令,不提交仓库
AutoMem ~/.claude/projects/<repo-hash>/memory/MEMORY.md AI 自动提炼的跨会话记忆索引
TeamMem 团队共享目录(feature-gated) 团队同步记忆(实验特性)

加载优先级(越后加载优先级越高,模型更关注):

复制代码
Managed → User → Project(根目录→CWD) → Local → AutoMem → TeamMem

2.2 知识点层面的 Memory 类型

源码:src/memdir/memoryTypes.ts

AI 在 AutoMem 目录中写入的每个记忆文件,通过 frontmatter 的 type 字段声明知识类型:

类型 作用域 描述
user 私有 用户画像:角色、目标、经验背景、偏好
feedback 私有/团队 行为反馈:用户的纠正指令或确认的做法
project 团队优先 项目上下文:进行中的工作、目标、决策、截止日期
reference 团队优先 外部系统指针:Linear、Grafana、Slack 等外部资源的位置

不应写入记忆的内容

  • 可从代码推导出的信息(架构、代码模式、文件路径)
  • Git 历史、近期变更
  • 调试方案和修复记录(代码本身就是记录)
  • 临时状态、当前会话上下文
  • 已在 CLAUDE.md 中记录的内容

三、核心数据结构

MemoryFileInfo(内存中的记忆文件表示)

typescript 复制代码
// src/utils/claudemd.ts
type MemoryFileInfo = {
  path: string           // 文件绝对路径
  type: MemoryType       // 记忆类型(见2.1)
  content: string        // 处理后的内容(去除HTML注释、frontmatter、截断)
  parent?: string        // 通过 @include 引入时,父文件路径
  globs?: string[]       // 条件规则:适用的文件 glob 模式
  contentDiffersFromDisk?: boolean  // 内容是否与磁盘不同(被截断或处理过)
  rawContent?: string    // 磁盘原始内容(当 contentDiffersFromDisk=true 时)
}

MemoryHeader(目录扫描时的记忆文件元数据)

typescript 复制代码
// src/memdir/memoryScan.ts
type MemoryHeader = {
  filename: string          // 相对路径
  filePath: string          // 绝对路径
  mtimeMs: number           // 修改时间(用于排序)
  description: string | null // frontmatter 中的 description 字段
  type: MemoryType | undefined // frontmatter 中的 type 字段
}

四、文件发现与加载机制

4.1 CLAUDE.md 文件发现流程

源码:src/utils/claudemd.tsgetMemoryFiles()

复制代码
getMemoryFiles()
│
├─ 1. 加载 Managed:/etc/claude-code/CLAUDE.md + /etc/claude-code/.claude/rules/
│
├─ 2. 加载 User(若启用):~/.claude/CLAUDE.md + ~/.claude/rules/
│
├─ 3. 目录向上遍历(CWD → 根目录),每层加载:
│   ├─ Project: ./CLAUDE.md
│   ├─ Project: ./.claude/CLAUDE.md
│   ├─ Project: ./.claude/rules/*.md(无条件规则)
│   └─ Local:   ./CLAUDE.local.md
│
├─ 4. 附加目录(--add-dir):同 Project 逻辑
│
├─ 5. AutoMem 入口:~/.claude/projects/<repo>/memory/MEMORY.md
│
└─ 6. TeamMem 入口(若启用)

关键设计

  • 越靠近 CWD 的文件越后加载,模型更关注(优先级越高)
  • 使用 memoize 缓存结果,会话内只读一次磁盘
  • @include 指令:支持在 CLAUDE.md 中通过 @path 引入其他文件(最深5层)
  • 支持 frontmatter paths: 字段做条件规则(仅对特定文件路径生效)

4.2 @include 指令解析

markdown 复制代码
# 在 CLAUDE.md 中可以这样引用其他文件:
@./common-rules.md
@~/shared-config/coding-standards.md
@/absolute/path/to/rules.md

通过 marked 库的词法分析器提取文本节点中的 @path 模式,排除代码块内容,递归处理最多 5 层。

4.3 内容处理流程

每个 CLAUDE.md 文件加载后经过:

  1. Frontmatter 解析 :提取 paths: 等控制字段,保留正文
  2. HTML 注释剥离 :移除 <!-- --> 注释(仅块级,不影响代码块内的注释)
  3. 截断处理:AutoMem/TeamMem 的 MEMORY.md 限制 200 行 / 25KB

五、AutoMem 自动记忆系统

这是最核心的"跨会话记忆"机制。

5.1 存储路径

源码:src/memdir/paths.ts

复制代码
~/.claude/projects/<sanitized-git-root>/memory/
├── MEMORY.md              # 索引文件(最多200行,每行一个条目)
├── user_role.md           # 用户画像记忆
├── feedback_testing.md    # 测试相关反馈记忆
├── project_deadline.md    # 项目截止日期上下文
├── reference_linear.md    # 外部系统指针
└── logs/                  # 日志模式(KAIROS 特性)
    └── 2026/04/2026-04-08.md

路径解析优先级

  1. CLAUDE_COWORK_MEMORY_PATH_OVERRIDE 环境变量(CoWork 场景)
  2. settings.json 的 autoMemoryDirectory(trusted sources only)
  3. ~/.claude/projects/<git-root-hash>/memory/

关键:使用 git 仓库的 canonical root(处理 worktree 场景),确保同一仓库的所有 worktree 共享同一个 memory 目录。

5.2 记忆文件格式

markdown 复制代码
---
name: 用户喜欢简洁回复
description: 用户偏好风格 - 直接给出结果,不做总结
type: feedback
---

不在回复末尾总结刚做的操作,用户可以看 diff 了解变化。

**Why:** 用户明确反馈不需要结尾总结。
**How to apply:** 每次回复结束后不要加"我刚才做了..."的段落。

5.3 MEMORY.md 索引格式

markdown 复制代码
- [用户偏好简洁回复](feedback_concise.md) --- 不做结尾总结,直接给结果
- [用户背景:数据科学家](user_role.md) --- 关注可观测性/日志分析
- [项目:移动端发版冻结](project_release.md) --- 2026-04-10 之前不合并非关键PR

5.4 自动记忆提取流程

源码:src/services/extractMemories/extractMemories.ts

复制代码
每次对话轮次结束(模型返回最终响应,无工具调用)
│
└─ executeExtractMemories() [fire-and-forget]
   │
   ├─ 检查:模型是否已在本轮直接写入记忆文件?
   │   └─ 是:跳过(避免重复),更新游标
   │
   ├─ 扫描现有记忆文件(scanMemoryFiles)→ 生成 manifest
   │
   ├─ 构造提取 prompt(含对话历史 + 现有记忆清单)
   │
   └─ runForkedAgent():启动独立子 Agent
       ├─ 工具权限:Read/Grep/Glob 全开,Write/Edit 仅限 memory 目录
       ├─ 最多 5 轮(防止无限循环)
       └─ 写入记忆文件 + 更新 MEMORY.md 索引

关键设计

  • 使用 forked agent(共享父对话的 prompt cache,节省 token)
  • 游标机制(lastMemoryMessageUuid),每次只处理新增消息
  • 互斥保护:同时只有一个提取 agent 运行,后续请求被 stash 等待
  • 频率控制 :通过 feature flag tengu_bramble_lintel 控制每 N 轮提取一次

六、记忆注入到对话上下文

6.1 CLAUDE.md 注入(User Context)

源码:src/context.tsgetUserContext()

typescript 复制代码
const claudeMd = getClaudeMds(filterInjectedMemoryFiles(await getMemoryFiles()))

生成的格式:

复制代码
Codebase and user instructions are shown below. Be sure to adhere to these instructions...

Contents of /project/CLAUDE.md (project instructions, checked into the codebase):

<文件内容>

Contents of ~/.claude/CLAUDE.md (user's private global instructions for all projects):

<文件内容>

6.2 AutoMem 提示注入(System Prompt)

源码:src/constants/prompts.tsgetSystemPrompt()src/memdir/memdir.tsloadMemoryPrompt()

在系统提示中注入记忆行为指导:

复制代码
# auto memory

You have a persistent, file-based memory system at `~/.claude/projects/.../memory/`. 
This directory already exists --- write to it directly...

## Types of memory
[user / feedback / project / reference 四种类型说明]

## How to save memories
Step 1: 写入独立 .md 文件(带 frontmatter)
Step 2: 在 MEMORY.md 中添加一行索引指针

## MEMORY.md
[MEMORY.md 当前内容]

七、SessionMemory(会话级记忆)

源码:src/services/SessionMemory/sessionMemory.ts

这是为**上下文压缩(auto-compact)**服务的短期记忆,与 AutoMem 不同:

  • 生命周期:单次会话内有效,用于辅助上下文压缩
  • 触发条件:context 超过阈值(token 数 + 工具调用次数)时自动提取
  • 存储位置:会话目录下的临时文件
  • 用途:在压缩时保留重要的会话状态,避免信息丢失

八、条件规则(Conditional Rules)

源码:src/utils/claudemd.tsprocessConditionedMdRules()

.claude/rules/ 目录下的 .md 文件可以通过 frontmatter 指定仅对特定文件路径生效:

markdown 复制代码
---
paths:
  - "**/*.py"
  - "src/tests/**"
---

Python 文件专属规则:不要使用 unittest,始终使用 pytest...

这实现了上下文感知的记忆注入------只有在操作匹配文件时,相关规则才会被加载。


九、完整数据流图

复制代码
╔══════════════════════════════════════════════════════════════╗
║                    会话启动时                                  ║
╚══════════════════════════════════════════════════════════════╝
  getMemoryFiles()
    ↓
  [Managed] → [User] → [Project/Local(root→CWD)] → [AutoMem]
    ↓
  getClaudeMds() → userContext.claudeMd
    ↓
  loadMemoryPrompt() → systemPrompt[memory section]
    ↓
  API Call: system=[...memory prompt...], user=[claudeMd + 用户输入]

╔══════════════════════════════════════════════════════════════╗
║                    每轮对话后                                  ║
╚══════════════════════════════════════════════════════════════╝
  用户输入 → Claude 响应(无工具调用时触发)
    ↓
  executeExtractMemories() [后台 fire-and-forget]
    ↓
  scanMemoryFiles() → 已有记忆清单
    ↓
  runForkedAgent(提取prompt + 对话历史)
    ↓
  子Agent分析对话 → 写入 memory/*.md + 更新 MEMORY.md
    ↓
  下次会话时 MEMORY.md 被加载进 system prompt

十、关键设计原则

  1. 优先级即顺序:后加载的文件优先级更高(模型注意力机制的特性)
  2. 只保存不可推导的信息:代码可读到的内容不进记忆
  3. 索引+详情双层结构MEMORY.md 作为目录(200行限制),详情存独立文件
  4. 安全隔离:提取 agent 只能写 memory 目录,防止误操作
  5. 缓存共享:forked agent 共享父对话 prompt cache,降低成本
  6. 幂等设计:memoize 缓存 + cursor 机制,避免重复处理
相关推荐
小真zzz3 小时前
搜极星:你的免费“AI内容验真器”
大数据·人工智能·ai·chatgpt·seo·geo
奇思智算3 小时前
LLaMA/Bert/扩散模型微调GPU选型及租用指南
人工智能·bert·llama
QQ676580083 小时前
AI人工智能图像识别 兔子动物分类研究 宠物行业物种鉴别及畜牧业兔种监测 兔种监测识别 YOLO图像数据集 兔类物种的计算机视觉识别模型训练 第10363期
人工智能·yolo·目标检测·目标跟踪·分类·宠物·宠物行业鉴别
一见3 小时前
OpenSpec、Superpowers 和 Harness:AI 工程化开发的三层拼图
人工智能·openspec·superpowers·harness
List<String> error_P3 小时前
蓝桥杯3.8模拟赛2-5题
java·开发语言·python
lifallen3 小时前
Flink Agents:Watermark 与事件时间 (Event Time) 在 Agent 算子中的演进分析
java·大数据·人工智能·语言模型·flink
LDG_AGI3 小时前
【搜索引擎】Elasticsearch(三):基于script_score的自定义搜索排序
大数据·人工智能·深度学习·elasticsearch·机器学习·搜索引擎·推荐算法
cd_949217213 小时前
骁龙与梅赛德斯-AMG:下一个弯道之后,是更深的连接
人工智能
Likeadust3 小时前
智能会议管理系统EasyDSS构建企业视频全场景解决方案
人工智能·音视频