跳到主要内容

claude-mem 是什么 · 全景与阅读地图

30 秒导读: claude-mem 是给 Claude Code 的跨会话持久记忆插件。它在后台盯着你和 Claude 的每一次工具调用, 派第二个 Claude(Agent SDK 起的观察者会话)把这些调用压成一小段结构化 XML「观察」,存进本地 SQLite + 向量库;下次你新开一个会话,它自动把相关历史注入进去。终端关了,上下文不再清零。 本章只做全景 + 路由:先讲清「是什么」,再给一张顶层图,把主线走一遍,最后告诉你 01–05 章各讲什么、按什么顺序读。


1. 这是什么(零基础也能懂)

一句话定义。 claude-mem 是一个 Claude Code 插件,给这个终端里的 AI 编码助手 补上一块「长期记忆」——自动记录、压缩、并在未来会话里召回你项目的历史。

它解决谁的什么痛点。 Claude Code 是跑在终端里的 AI:你让它读代码、改文件、跑命令,它在一个上下文窗口里干活。 问题是——

  • 上下文窗口是易失的:窗口填满被压缩、或你关掉终端、或会话 /clear,之前查明的结论、踩过的坑、改过的决定全丢
  • 下次重来,你得重新解释一遍项目背景。Claude 不记得昨天为什么这么改。

claude-mem 就是补这块记忆:给谁用——任何用 Claude Code(以及 Gemini CLI / OpenCode / Cursor 等,见适配器)做项目的人。

装完什么样。 一条命令安装,然后重启,历史会自动出现,你几乎察觉不到它在工作:

npx claude-mem install # 装插件、注册钩子、准备 worker 服务
# 重启 Claude Code —— 之后每次新会话开头会自动带上「上次干了啥」

安装说明见 README.md:131-160;npm install -g claude-mem 只装 SDK 库、不注册钩子,必须走 npx claude-mem install/plugin

它能做什么(功能一览)。

能力白话
自动捕获每次工具调用(读文件、改代码、跑命令…)后台被记录,无需手动
语义压缩用第二个 Claude 把原始调用压成带标题/事实/概念的 XML「观察」
开场注入新会话 SessionStart 时自动把相关历史塞进上下文
记忆检索提供 MCP 工具(search / timeline / get_observations)按需查历史
本地存储全部落在本机 ~/.claude-mem/(SQLite + Chroma 向量库),隐私可控
实时查看本地 Web 查看器,实时看记忆流(README 记为 http://localhost:37777)

2. 一句话直觉 / 类比

把整个系统想成一台带磁盘的电脑,再配一个书记员:

  • 上下文窗口 = 内存(RAM):快、但一断电就清空。
  • SQLite + Chroma 向量库 = 磁盘:慢一点,但持久
  • 第二个 Claude(观察者)= 书记员:它不参与你的主对话,只在旁边看着主会话干了什么, 把值得记的事写成卡片归档到磁盘;你下次开工,它先把相关卡片摆回你桌上(内存)

一句话:把上下文窗口当内存、SQLite/向量库当磁盘,再派第二个 Claude 当书记员。


3. 顶层全景图

怎么读这张图: 左边是你正在用的主会话;它触发 6 个生命周期钩子;钩子把事件交给本地的 worker 守护进程;worker 维护一个常驻的第二个 Claude(观察者)把事件压成 XML;结果落进 SQLite + Chroma;虚线是回路——新会话开场时,历史又从存储被注入回主会话。

你 + 主会话 Claude Code
│ 每个生命周期动作触发一个钩子

┌─────────────────────────────┐
│ ① 6 个生命周期钩子 (接入层) │ hooks.json → CLI: `hook claude-code <event>`
│ SessionStart / UserPrompt │ 纯函数 handler,严守 Hook IO 纪律
│ PostToolUse / Stop / … │
└───────────────┬─────────────┘
│ 走 HTTP 到本地 worker(默认端口见 §5)

┌─────────────────────────────┐ ┌───────────────────────────┐
│ ② worker 守护进程 (心脏) │──派生──▶│ ③ 持久观察者会话 │
│ HTTP API + 会话/队列管理 │ │ Agent SDK query() 起的 │
│ SessionManager 缓冲+去重 │◀──XML──│ 「第二个 Claude」,可 resume │
└───────────────┬─────────────┘ └───────────────────────────┘
│ 解析 XML → 结构化观察

┌─────────────────────────────┐
│ ④ 存储层 │ SQLite: memory_items + FTS5 全文
│ SQLite(磁盘) + Chroma(向量) │ Chroma: 语义向量镜像
└───────────────┬─────────────┘
│ ← ← ← ← ← 回路 ← ← ← ← ←

┌─────────────────────────────┐
│ ⑤ 召回 │ SessionStart 注入 / MCP 三层检索
│ 开场自动注入 + 按需搜索 │ search → timeline → get_observations
└───────────────┬─────────────┘
│ 历史回到主会话上下文
▲────────────── (闭环)

图里的编号对应下面 §5 的职责表;每个部件的代码细节留给对应章节。


4. 主线走一遍(高层,不进代码)

两条真实路径就能讲清整个系统怎么转——一条「记进去」,一条「拿回来」。

路径 A:一次工具调用如何变成一条可检索记忆

  1. 主会话里 Claude 调了个工具(比如 ReadEdit),Claude Code 触发 PostToolUse 钩子。
  2. 钩子跑到 CLI 的 observationHandler,把工具名/入参/出参打包,HTTP POST 给本地 worker (src/cli/handlers/observation.ts:14 dispatchToWorker)。
  3. worker 的 SessionManager 把这条事件入队并去重,挂到该会话的缓冲上 (src/services/worker/SessionManager.ts:151 queueObservation)。
  4. 该会话的常驻观察者(第二个 Claude)从队列取出事件,用一段 XML 骨架 Prompt 要求它「把这次工具调用压成 <observation>」(src/sdk/prompts.ts:121 buildObservationPrompt)。
  5. 观察者吐回 XML,被解析成结构化字段(标题、事实、概念、读/改的文件) (src/sdk/parser.ts:41 parseAgentXml),再落进 SQLite memory_items(触发器同步进 FTS5)并镜像进 Chroma

一条持久记忆就此诞生。全程你无感,主会话不被打断。

路径 B:新会话开场如何自动拿回历史

  1. 你新开(或 /clear / compact 后)一个会话,Claude Code 触发 SessionStart 钩子。
  2. SessionStart 做两件事:先确保 worker 起着(worker-service.cjs start),再调 contextHandler 拉本项目的历史(src/cli/handlers/context.ts:55)。
  3. contextHandler 向 worker 要 /api/context/inject,worker 用检索层挑出相关观察、拼成一段文本。
  4. 这段文本作为 hookSpecificOutput.additionalContext 返回,Claude Code 把它注入进新会话的上下文—— 于是新会话开局就「记得」上次的进展。
  5. 会话进行中,Claude 还能主动用 MCP 三层检索(search → timeline → get_observations, src/servers/mcp-server.ts:437 起的 tools)按需翻更多历史,靠先索引后取详情省 ~10x token。

5. 部件一句话职责表

#部件一句话职责关键文件 · 符号
钩子清单声明哪些生命周期事件触发什么命令plugin/hooks/hooks.json
CLI 分发hook <ide> <event> 路由到对应 handlersrc/cli/hook-command.ts;src/cli/handlers/index.ts
observation handlerPostToolUse → 打包工具调用发给 workersrc/cli/handlers/observation.ts:41 observationHandler
context handlerSessionStart → 拉历史、返回 additionalContextsrc/cli/handlers/context.ts:55 contextHandler
worker 守护进程常驻本地 HTTP 服务 + Web 查看器,统管会话/队列/存储src/services/worker-service.ts
SessionManager每会话的观察缓冲、去重、认领/确认队列src/services/worker/SessionManager.ts:9
ClaudeProvider用 Agent SDK query() 起并 resume 持久观察者会话src/services/worker/ClaudeProvider.ts:241 query({...})
prompts组装 init / observation / summary / continuation 的 XML 骨架src/sdk/prompts.ts buildObservationPrompt
parser把观察者的 XML 文本解析成结构化观察 / 摘要src/sdk/parser.ts:41 parseAgentXml
ResponseProcessor处理观察者回复:去重、落库、广播src/services/worker/agents/ResponseProcessor.ts:22 processAgentResponse
SQLite 存储memory_items 表 + memory_items_fts(FTS5)+ 同步触发器src/storage/sqlite/schema.ts:85:171
Chroma 镜像把观察同步进本地向量库,供语义检索src/services/sync/ChromaSync.tsChromaMcpManager.ts
SearchManager混合检索:Chroma 语义 + FTS5 关键词,带降级src/services/worker/SearchManager.ts:35
MCP server对主会话暴露 search/timeline/get_observations 等工具src/servers/mcp-server.ts:437 tools

端口说明(务实): README/文档把 Web 查看器写成 http://localhost:37777。代码里默认端口其实是 按 uid 计算的 37700 + (uid % 100)(src/shared/SettingsDefaultsManager.ts:94 CLAUDE_MEM_WORKER_PORT), 可用设置覆盖。把 37777 当「文档里的代表值」理解即可。


6. 巧妙之处速览 与 阅读地图

六个「值得带走」的设计(细节在各章)

  1. 第二个 Claude 当书记员。 压缩不写死规则,而是再起一个 Agent SDK 会话去理解工具调用—— 语义压缩交给模型自己(§02 / §03)。
  2. 常驻 + resume。 观察者会话用 memorySessionId 续接(ClaudeProvider.ts:252),同一主会话内多次观察 共享上下文,不用每次从零解释(§02)。
  3. XML 骨架当协议。 Prompt 给出固定 <observation> 骨架,输出用正则解析;非 XML 文本一律丢弃—— 一种「穷人版结构化输出」(§03)。
  4. 超长字段头尾截断 + <elided> 标记。 单个巨大工具结果不会撑爆观察者上下文,还显式告诉模型「这里被删了别瞎编」 (src/sdk/prompts.ts:107 truncateObservationField)(§03)。
  5. FTS5 触发器自动同步。memory_items 时触发器自动维护全文索引,检索层再叠一层 Chroma 语义召回(§04)。
  6. 三层检索省 token。 search(轻索引)→ timeline(前后文)→ get_observations(仅取筛过的 ID 详情), 「先筛后取」省约 10x token(src/servers/mcp-server.ts:437)(§05)。

建议阅读顺序

从「怎么进来」到「怎么出去」,顺着数据流读最省力:

顺序章节讲什么什么时候读
101-hooks-and-cli.md接入层:hooks.json、CLI 分发、Hook IO 纪律想知道事件怎么从 Claude Code 进入本系统
202-worker-and-observer.md心脏:worker 守护进程、持久观察者会话、队列想理解「第二个 Claude」怎么被起、被喂、被 resume
303-compression-prompts-and-parsing.md压缩管线:XML 骨架 Prompt、Modes、解析、落库想看一条工具调用具体怎么变成结构化观察
404-storage-sqlite-and-chroma.md存储层:SQLite schema + FTS5 + Chroma 镜像想知道记忆存成什么、怎么被索引
505-retrieval-context-and-search.md回路:SessionStart 注入 + MCP 三层检索想理解历史怎么被召回并送回主会话

本 index 只做低成本相关性判断与路由。任何单一子系统的真实代码走读,请跳到对应章节——那里才有密集的 file:line + 符号引用。