AI Blog
← 返回首页
AI · Claude Code · 记忆系统 · 知识图谱

claude-mem 深度解析:如何为 Claude Code 构建跨会话记忆系统

仓库:github.com/thedotmack/claude-mem · v13.0.1 · TypeScript · Bun · Apache-2.0

一、引言:Claude Code 的记忆困境

Claude Code 是一个强大的 AI 编程助手,但它有一个根本性问题:每次会话都是从零开始的。当你关闭一个终端窗口,下次再打开时,Claude Code 完全不记得之前讨论过什么、做过什么决策、遇到了什么问题。

这意味着你每次都要重复解释项目背景、重新描述架构决策、反复说明之前的坑。对于长期项目来说,这种"失忆"严重降低了协作效率。

claude-mem 正是为了解决这个问题而生的。它通过一套精巧的架构,让 Claude Code 拥有了跨会话的持久记忆,并且能够自动从历史交互中构建知识图谱

二、整体架构概览

claude-mem 的架构可以分为四层:

┌─────────────────────────────────────────────────────┐
│                    Claude Code                       │
│         (Hooks 系统 · 会话生命周期管理)                │
└──────────────────────┬──────────────────────────────┘
                       │ 每个生命周期事件触发 bash 脚本
                       ▼
┌─────────────────────────────────────────────────────┐
│              Hook 路由层 (hooks.json)                 │
│    Setup / SessionStart / UserPromptSubmit /         │
│    PreToolUse / PostToolUse / Stop                   │
└──────────────────────┬──────────────────────────────┘
                       │ node bun-runner.js worker-service.js
                       ▼
┌─────────────────────────────────────────────────────┐
│            Worker 服务 (后台常驻进程)                   │
│  ┌──────────┐ ┌───────────┐ ┌──────────────────┐    │
│  │ HTTP     │ │ Session   │ │ Knowledge        │    │
│  │ Server   │ │ Manager   │ │ Agent            │    │
│  ├──────────┤ ├───────────┤ ├──────────────────┤    │
│  │ Search   │ │ Database  │ │ Transcript       │    │
│  │ Routes   │ │ Manager   │ │ Watcher          │    │
│  └──────────┘ └───────────┘ └──────────────────┘    │
│  ┌──────────────────────────────────────────┐       │
│  │  AI Providers: Claude / Gemini / OpenRouter│      │
│  └──────────────────────────────────────────┘       │
└──────────────────────┬──────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────┐
│              SQLite 数据库 (bun:sqlite)               │
│  Sessions · Observations · Summaries · Prompts       │
│  Entities · Relations · Timeline · Corpus            │
└─────────────────────────────────────────────────────┘

这种分层设计的核心思想是:Claude Code 本身不需要任何修改,所有记忆功能都通过 Hooks 机制"外挂"上去,实现了零侵入集成。

三、Hook 机制:事件驱动的生命周期拦截

3.1 Claude Code Hooks 系统

Claude Code 提供了一套 Hook 系统,允许插件在特定生命周期事件发生时执行自定义脚本。claude-mem 的 hooks.json 定义了 6 个 Hook,覆盖了完整生命周期:

Hook 名称触发时机执行动作
SetupClaude Code 进程启动版本检查(version-check.js
SessionStart新会话 / 清空 / 压缩启动 Worker 守护进程 + 注入上下文
UserPromptSubmit用户提交 prompt注入会话初始化指令
PreToolUse工具调用前(Read)注入文件上下文指令
PostToolUse工具调用完成后注入观察记录指令
Stop会话结束注入摘要生成指令

3.2 Hook 的执行流程

每个 Hook 本质上是一段 bash 脚本,核心任务有三个:

SessionStart Hook 为例,其 bash 脚本的核心逻辑是:

# 1. 设置 PATH 环境变量
export PATH="$HOME/.nvm/versions/node/v.../bin:$HOME/.local/bin:..."

# 2. 定位插件目录
_CLAUDE_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
_PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-}}"

# 3. 查找包含 bun-runner.js 和 worker-service.js 的目录
for _R in "$_PLUGIN_ROOT" ...; do
  [ -d "$_R/plugin/scripts" ] && _Q="$_R/plugin" || _Q="$_R"
  [ -f "$_Q/scripts/bun-runner.js" ] && \
  [ -f "$_Q/scripts/worker-service.cjs" ] && \
  { printf '%s\n' "$_Q"; break; }
done

# 4. 启动 Worker 守护进程
node "$_P/scripts/bun-runner.js" "$_P/scripts/worker-service.cjs" start

# 5. 注入上下文指令
echo '{"continue":true,"suppressOutput":true}'

注意最后一步返回的 JSON:{"continue":true,"suppressOutput":true}。这是 Claude Code Hook 协议的标准返回格式,告诉 Claude Code"继续执行,不要把 Hook 的输出显示给用户"。

3.3 Hook 注入的"指令"是什么?

5 个 Hook 除了启动 Worker 外,还会向 Claude Code 注入一段隐式指令,格式为:

hook claude-code <context|session-init|file-context|observation|summary>

这些指令会被 Claude Code 当作系统消息处理,触发 Worker 执行相应的后台任务:

四、Worker 服务:后台常驻的核心引擎

4.1 启动与生命周期管理

Worker 是一个基于 Bun 运行时的 HTTP 服务器,通过 PID 文件实现进程管理:

// 写入 PID 文件
writePidFile({
  pid: process.pid,
  port,
  startedAt: new Date().toISOString()
});

// 注册到 Supervisor
getSupervisor().registerProcess('worker', {
  pid: process.pid,
  type: 'worker',
  startedAt: new Date().toISOString()
});

Worker 使用端口自动分配机制(getWorkerPort()),避免端口冲突。启动后,它会:

4.2 HTTP API 层

路由组功能
ViewerRoutes前端 Viewer 的数据接口
SessionRoutes会话管理(创建、查询、删除)
DataRoutes数据导出与统计
SearchRoutes跨会话搜索
SettingsRoutes配置管理
MemoryRoutes手动记忆保存
CorpRoutes语料库管理
ChromeRoutesChrome 浏览器数据同步

4.3 多 Provider 支持

Worker 内置了三个 AI Provider,用于执行记忆压缩和摘要任务:

KnowledgeAgent 在调用 AI 时会禁用大量工具,只保留纯对话能力:

const DISALLOWED_TOOLS = [
  'Bash',      // 防止无限循环
  'Read',      // 不读文件
  'Write',     // 不写文件
  'Edit',      // 不编辑文件
  'Grep',      // 不搜索代码
  'Glob',      // 不匹配文件
  'WebFetch',  // 不抓取网页
  'WebSearch', // 不搜索网页
  'Task',      // 不生成子 Agent
  'NotebookEdit',
  'AskUserQuestion',
  'TodoWrite'
];

这确保了知识图谱构建过程是纯推理的,不会触发副作用。

五、数据存储层:SQLite 的深度运用

5.1 存储选型

claude-mem 选择 SQLite(通过 bun:sqlite)作为核心存储,而非向量数据库或文件系统:

5.2 核心数据模型

SessionStore(95KB,最大的模块):存储所有会话的完整数据,包括消息、工具调用、观察记录等。不仅是一个存储层,还包含复杂的查询逻辑、分页支持和 Hydration(从 JSONL 转录文件重建会话)。

Observations(观察记录):每次工具调用后记录的结构化数据:

interface Observation {
  type: string;           // 'discovery' | 'file_read' | 'code_change' | ...
  title: string;          // 简短标题
  subtitle?: string;      // 副标题
  narrative?: string;     // 详细叙述
  facts: string[];        // 关键事实列表
  concepts: string[];     // 概念标签
  files_read: string[];   // 读取的文件
  files_modified: string[]; // 修改的文件
  project: string;        // 所属项目
  created_at: string;     // 创建时间
  created_at_epoch: number; // 时间戳(毫秒)
}

5.3 PendingMessageStore:消息队列

一个精巧的设计:当 Claude Code 触发一个 Hook 时,Worker 可能还在处理上一个任务。PendingMessageStore 作为消息队列,确保所有事件都不会丢失。GeneratorExitHandler 展示了优雅的处理逻辑:

if (pendingCount === 0) {
  // 没有待处理消息,正常完成
  session.restartGuard?.recordSuccess();
  session.consecutiveRestarts = 0;
  await terminateSession('Natural completion', false);
  return;
}

// 还有待处理消息,需要重启 Generator
const restartAllowed = session.restartGuard?.recordRestart();
if (!restartAllowed) {
  await terminateSession('Restart guard', true);
  return;
}

// 指数退避重启
const backoffMs = Math.min(
  1000 * Math.pow(2, session.consecutiveRestarts - 1), 8000
);
session.respawnTimer = setTimeout(() => {
  restartGenerator(session, 'pending-work-restart');
}, backoffMs);

这里有一个 RestartGuard 机制:如果同一个会话在短时间内重启次数过多(超过 maxRestarts),系统会放弃处理,防止无限循环。

六、知识图谱构建:从观察到知识

6.1 观察(Observation)的产生

知识图谱的原始数据来自工具调用的观察。每当 Claude Code 执行一个工具(读文件、写代码、搜索等),PostToolUse Hook 会触发 Worker 记录一条观察。观察记录包含:

6.2 CorpusBuilder:语料库构建

CorpusBuilder 负责将分散的观察记录聚合为结构化的语料库(Corpus)

async build(name, description, filter): Promise<CorpusFile> {
  // 1. 根据过滤条件搜索观察记录
  const searchResult = await this.searchOrchestrator.search(searchArgs);
  // 2. 提取观察 ID 列表
  const observationIds = searchResult.results.observations.map(obs => obs.id);
  // 3. 从数据库中获取完整的观察记录
  const observationRows = this.sessionStore.getObservationsByIds(observationIds);
  // 4. 映射为语料库格式 + 计算统计信息
  // 5. 生成 system prompt + 估算 token 数量
  // 6. 持久化存储
  this.corpusStore.write(corpus);
}

6.3 KnowledgeAgent:知识图谱 Agent

KnowledgeAgent 是整个知识图谱系统中最核心的组件。它的工作原理是:用一个受限的 Claude Agent 实例,从语料库中推理并提取知识。关键设计:

async prime(corpus: CorpusFile): Promise<string> {
  const renderedCorpus = this.renderer.renderCorpus(corpus);
  const primePrompt = [
    corpus.system_prompt,
    '',
    'Here is your complete knowledge base:',
    '',
    renderedCorpus,
    '',
    'Acknowledge what you\'ve received.',
    'Summarize the key themes and topics you can answer questions about.'
  ].join('\n');

  // 使用受限的 Agent SDK 调用 — 禁用所有副作用工具
  const queryResult = query({
    prompt: primePrompt,
    options: {
      model: this.getModelId(),
      disallowedTools: DISALLOWED_TOOLS,
      ...
    }
  });
}

七、搜索系统:多策略检索

7.1 SearchOrchestrator

搜索系统采用策略模式SearchOrchestrator 作为编排器,根据查询参数选择合适的搜索策略:

src/services/worker/search/
├── SearchOrchestrator.ts   ← 搜索编排器
├── ResultFormatter.ts      ← 结果格式化
├── TimelineBuilder.ts      ← 时间线构建
├── types.ts                ← 类型定义
├── errors.ts               ← 错误处理
├── strategies/             ← 搜索策略
└── filters/                ← 过滤器

搜索支持的过滤维度:projecttypeconceptsfilesquery(全文关键词)、date_start / date_end(时间范围)、limit

7.2 SQLite FTS5 全文搜索

底层搜索使用 SQLite 的 FTS5(Full-Text Search 5)扩展。SessionSearch 模块(20KB)实现了中英文分词、相关性排序、高亮匹配、多字段联合搜索。

八、转录监控:TranscriptWatcher

Claude Code 会将每次会话的完整对话记录保存为 JSONL 文件(位于 ~/.claude/projects/ 下)。TranscriptWatcher 组件监控这些文件的变化:

这是 claude-mem 能够"看到"所有历史会话的关键机制。

九、多语言与 MCP 集成

plugin/modes/ 目录下有 20+ 个语言配置文件(code--zh.jsoncode--ja.jsoncode--fr.json 等),每个文件定义了该语言下的 prompt 模板、行为配置和输出格式偏好。

claude-mem 通过 MCP(Model Context Protocol)向 Claude Code 暴露搜索工具:search(跨会话搜索)、timeline(查看时间线)、corpus(管理语料库)。此外,ChromeSync 组件可以与 Chrome 浏览器扩展配合,将浏览器操作也纳入记忆系统。

十、与其他记忆方案的对比

维度claude-memOpenClaw MEMORY.mdMem0Letta (MemGPT)
集成方式Claude Code Hooks文件系统API 服务API 服务
存储SQLiteMarkdown 文件向量数据库SQLite + 向量
知识表示观察 + 知识图谱纯文本向量嵌入分层记忆
搜索FTS5 全文搜索语义搜索向量相似度混合搜索
自动化全自动(Hook 驱动)手动/半自动API 调用API 调用
适用场景Claude Code 专属通用 Agent通用通用

十一、总结

通过 Claude Code 的 Hooks 机制零侵入地拦截会话事件,用后台 Worker 异步处理观察记录,存入 SQLite 数据库,并用受限的 AI Agent 实例从观察中构建知识图谱,最终通过 MCP 工具和 Hook 注入实现跨会话记忆的自动检索与注入。

它的精妙之处在于:

当然,它也有局限性——强绑定 Claude Code 生态、依赖 Bun 运行时、知识图谱质量取决于底层模型能力。但对于 Claude Code 用户来说,这可能是目前最成熟的跨会话记忆解决方案。