Memdir

Memdir 模块实现 Claude Code 的 AI 记忆系统(MEMORY.md 生态),包含 8 个文件。核心能力包括:记忆文件扫描与元数据提取(memoryScan)、基于 AI 的相关记忆智能召回(findRelevantMemories,使用 Sonnet 模型从记忆清单中选择最相关的 5 条)、记忆提示词构建(buildMemoryPrompt)、记忆新鲜度管理(memoryAge)、团队记忆路径与提示词(teamMemPaths、teamMemPrompts)。它让 AI 拥有跨会话的持久记忆,而非每次对话都从零开始。

职责与设计理念

职责说明

AI 记忆系统,管理持久化记忆文件的存储、检索与智能召回

设计理念

记忆即文件——用最朴素的文件系统(Markdown 文件 + 目录结构)实现 AI 的长期记忆。智能召回不是关键词匹配,而是用 AI 理解 AI 需要什么记忆。

架构决策

为什么用 AI 召回记忆而不是向量搜索?

使用 Sonnet 模型做记忆选择,而非 embedding + 向量相似度

记忆文件数量通常 < 100,向量搜索的基础设施开销(embedding 模型、向量数据库)远超收益。Sonnet 模型能理解记忆的语义关联(如"这个工具有已知 bug"),这是纯向量相似度做不到的。

⚖️ 每次召回需要一次 API 调用(约 0.5s),但记忆召回只在会话开始时执行一次,不影响对话体验。

为什么记忆是 Markdown 文件而不是数据库?

文件系统即数据库

Markdown 文件可以用 git 版本控制、用文本编辑器查看修改、用 grep 搜索。数据库需要额外的运行时依赖和迁移脚本。对于 < 100 个记忆文件的规模,文件系统的性能完全足够。

文件清单

文件名 用途
findRelevantMemories.ts 智能记忆召回,用 Sonnet 模型从记忆清单中选择最相关的记忆
memdir.ts 记忆提示词构建,将记忆文件内容组装为系统提示词片段
memoryScan.ts 记忆文件扫描,提取文件名、描述、修改时间等元数据
memoryAge.ts 记忆新鲜度管理,计算记忆的时间衰减权重
memoryTypes.ts 记忆类型定义,区分用户记忆、自动记忆、团队记忆
paths.ts 记忆目录路径解析,定位 ~/.claude/memory/ 等目录
teamMemPaths.ts 团队记忆路径,管理团队共享记忆的存储位置
teamMemPrompts.ts 团队记忆提示词,构建团队级记忆的注入格式

使用场景

新会话开始时

findRelevantMemories() 自动扫描记忆目录,选择与当前项目相关的记忆注入系统提示词

会话初始化 → memoryScan() → findRelevantMemories() → buildMemoryPrompt() → 注入系统提示词

AI 自动保存记忆

对话中发现的重要信息(如项目约定、已知 bug)自动写入 MEMORY.md

团队共享记忆

团队成员的记忆通过 teamMemPaths 共享,新成员自动继承团队知识

依赖关系

  • Bootstrap — 全局状态容器与会话生命周期管理,维护运行时的单一真相源

关键代码片段

AI 驱动的记忆召回

const SELECT_MEMORIES_SYSTEM_PROMPT = `You are selecting memories
that will be useful to Claude Code. Return up to 5 filenames.
Only include memories you are certain will be helpful.
If recently-used tools are provided, do NOT select their
reference docs (already in context), but DO select warnings
and known issues about those tools.`

async function findRelevantMemories(
  query: string, memoryDir: string, signal: AbortSignal,
  recentTools: readonly string[] = [],
): Promise<RelevantMemory[]> {
  const memories = await scanMemoryFiles(memoryDir, signal)
  const manifest = formatMemoryManifest(memories)
  const selected = await sideQuery({
    model: getDefaultSonnetModel(),
    system: SELECT_MEMORIES_SYSTEM_PROMPT,
    messages: [{ role: 'user', content: manifest }],
  })
  return parsed.selected_memories
}

用 AI(Sonnet)理解用户查询,从记忆清单中智能选择最相关的 5 条记忆

技术笔记

performance

记忆新鲜度衰减

memoryAge 计算记忆的时间衰减权重,最近修改的记忆优先级更高。超过 90 天未更新的记忆在召回时降权。

edge-case

工具引用文档排除

如果最近使用了某个工具,其参考文档已在上下文中,findRelevantMemories 会自动排除该工具的文档类记忆,避免重复注入。