Claude-Mem 深度实战:56K+ Star 的 Claude Code 持久记忆插件——从 Hook 生命周期架构到渐进式检索的全链路解析
当你的 AI 编程助手每天跟你对话,却始终像个失忆症患者——每次开会都从零开始,上次的决策、踩过的坑、架构选择一概不记得。这不是 AI 的能力问题,是记忆问题。Claude-Mem 用一套精巧的 Hook 生命周期架构,给 Claude Code 装上了"长期记忆"。
一、背景:AI 编程助手的"失忆症"
1.1 上下文窗口的天花板
当前 AI 编程助手面临一个根本性矛盾:模型能力越来越强,但上下文窗口始终有限。Claude Code 在一次会话中可能做出上百次工具调用——读文件、写代码、执行命令、修复 Bug——但会话一结束,这些上下文就烟消云散。
下次开会,你告诉 Claude"继续上次的工作",它只会茫然地看着你。你不得不重新描述项目结构、重新解释架构决策、重新警告它上次踩过的坑。这不是效率问题,是体验灾难。
1.2 现有方案的局限
CLAUDE.md 方案:Claude Code 原生支持通过 CLAUDE.md 文件持久化项目规则和约定,但这只是静态文档,无法自动捕获动态的编码过程。
auto memory 方案:Claude Code 的自动记忆功能会把纠正和偏好写入 memory/ 目录,但覆盖面太窄,只有主动纠正才会被记录,大量的技术决策、Bug 修复过程、探索路径全部丢失。
外部笔记方案:手动维护开发日志?别逗了,程序员的文档惰性是业界公认的。
1.3 Claude-Mem 的答案
Claude-Mem 的核心理念很简单:自动捕获 Claude 在编码会话中的一切行为,用 AI 压缩成语义摘要,然后在未来的会话中自动注入相关上下文。
听起来简单,但实现起来需要解决几个关键工程问题:
- 如何在不侵入 Claude Code 源码的情况下捕获所有工具调用?
- 如何在 Hook 的毫秒级时间约束内完成数据采集?
- 如何用 AI 压缩海量观测数据而不丢失关键信息?
- 如何在有限的 Token 预算内智能检索和注入上下文?
Claude-Mem 的答案是:Hook 生命周期架构 + 异步队列处理 + 渐进式披露检索。这套架构不仅解决了问题,而且优雅得让人想鼓掌。
二、核心概念:Hook 驱动的记忆系统
2.1 非侵入式设计原则
Claude-Mem 的第一条设计原则:不能修改 Claude Code 的行为,只能在旁边观察。
这不仅仅是技术选择,更是可靠性要求。如果记忆系统崩溃了,Claude Code 必须还能正常工作。这是一种"渐进增强"的哲学:
没有 Claude-Mem → Claude Code 正常工作
有了 Claude-Mem → Claude Code + 历史上下文
Claude-Mem 崩了 → 自动降级到正常工作
2.2 Hook 系统:Claude Code 的"侧信道"
Claude Code 提供了一套 Hook 机制,允许外部命令在特定生命周期事件中被调用。Claude-Mem 就是围绕这套机制构建的。
五个生命周期 Hook,形成完整的记忆闭环:
SessionStart → UserPromptSubmit → PostToolUse → Stop → SessionEnd
↓ ↓ ↓ ↓ ↓
上下文注入 会话创建 观测入队 摘要生成 会话清理
关键洞察:Hook 是非阻塞的。Claude Code 不会等 Hook 完成,而是并行执行。这意味着 Hook 必须极快返回,耗时操作必须异步处理。
2.3 数据流全景
Hook (stdin) → SQLite 队列 → Worker Service → Claude Agent SDK 压缩 → SQLite → 下次会话 Hook 注入
这是一个典型的生产者-消费者模式:
- 生产者:各种 Hook 脚本,在 Claude Code 运行时捕获数据
- 缓冲区:SQLite 的
observation_queue表 - 消费者:后台 Worker Service,用 AI SDK 异步处理
- 存储:处理后的结构化观测数据存回 SQLite
- 消费端:下次会话的 SessionStart Hook 读取并注入
2.4 观测数据的层次化结构
Claude-Mem 不是简单地存储工具调用的原始日志,而是用 AI 提取结构化的层次信息:
interface Observation {
title: string; // 简洁标题:"修复数据库连接超时"
subtitle: string; // 副标题:"添加了重试机制"
narrative: string; // 叙述性描述:发生了什么,为什么
text: string; // 完整文本内容
facts: string; // 关键事实点
concepts: string; // 概念标签:security, performance, architecture
type: ObservationType; // decision | bugfix | feature | refactor | discovery | change
files_read: string; // 读取了哪些文件
files_modified: string; // 修改了哪些文件
}
这种层次化结构让检索和展示都更加精准——你可以只看标题快速扫描,也可以深入叙述了解细节。
三、架构深度分析:从 Hook 到 Worker 的全链路
3.1 目录结构解析
claude-mem/
├── src/
│ ├── hooks/ # TypeScript Hook 实现
│ ├── sdk/ # Claude Agent SDK 集成
│ ├── services/
│ │ ├── worker-service.ts # Express HTTP + SSE Worker
│ │ ├── sync/ChromaSync.ts # Chroma 向量索引
│ │ └── sqlite/ # SQLite + FTS5 存储层
│ │ ├── SessionStore.ts # CRUD 操作
│ │ ├── SessionSearch.ts # FTS5 搜索
│ │ └── migrations.ts # 数据库迁移
│ ├── ui/viewer/ # React Web 查看器
│ └── shared/ # 共享工具
├── plugin/ # 插件分发目录
│ ├── hooks/hooks.json # Hook 注册配置
│ ├── scripts/ # 构建后的可执行脚本
│ │ ├── version-check.js # Setup 阶段版本检查
│ │ ├── bun-runner.js # Bun 运行时解析器
│ │ ├── worker-service.cjs # Worker 守护进程
│ │ ├── mcp-server.cjs # MCP 搜索服务器
│ │ └── context-generator.cjs # 上下文生成器
│ ├── skills/ # Agent 技能(mem-search 等)
│ └── ui/viewer.html # 自包含 React Bundle
└── tests/ # 测试套件
3.2 六个 Hook 脚本详解
3.2.1 Setup Hook:版本哨兵
{
"hooks": {
"Setup": [{
"hooks": [{
"type": "command",
"command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/version-check.js",
"timeout": 60
}]
}]
}
}
这个 Hook 的设计堪称教科书级:
- 亚 100ms 执行:只读取一个版本标记文件,不做任何 I/O
- 永远返回 0:即使版本不匹配也不阻塞会话
- 只写 stderr:提示用户运行
npx claude-mem repair,不污染 Claude 的上下文 - 分离关注点:实际的安装修复由
npx命令完成,Setup Hook 只负责检测
// 版本检查的核心逻辑伪代码
function versionCheck(): ExitCode {
const installedVersion = readFileSync('.install-version');
const currentVersion = readPackageJson().version;
if (installedVersion !== currentVersion) {
stderr.write('run: npx claude-mem repair');
}
return 0; // 永远成功退出
}
3.2.2 SessionStart Hook:上下文注入
这是最关键的 Hook——它让 Claude Code 在会话开始时就能"回忆"起过去。
async function contextHook(): Promise<HookOutput> {
// 1. 从当前工作目录提取项目名
const project = extractProjectName(process.cwd());
// 2. 查询最近 10 条会话摘要
const summaries = await db.getRecentSummaries(project, 10);
// 3. 查询最近 50 条观测(可配置)
const observations = await db.getRecentObservations(
project,
settings.CLAUDE_MEM_CONTEXT_OBSERVATIONS
);
// 4. 格式化为渐进式披露索引
const context = formatProgressiveDisclosure(summaries, observations);
// 5. 通过 hookSpecificOutput.additionalContext 静默注入
return {
hookSpecificOutput: {
additionalContext: context
}
};
}
注入格式——渐进式披露索引:
# [claude-mem] recent context
**Legend:** 🎯 session-request | 🔴 gotcha | 🟡 problem-solution | 🔵 info | 🟢 feature | 🟣 decision
### May 7, 2026
**General**
| ID | Time | T | Title | Tokens |
|----|------|---|-------|--------|
| #2586 | 12:58 AM | 🔴 | 数据库连接超时修复 | ~51 |
| #2587 | 01:15 AM | 🟣 | 选择 Redis 做缓存层 | ~48 |
| #2588 | 02:30 AM | 🟢 | 实现 JWT 刷新机制 | ~62 |
*Use MCP search tools to access full details*
注意这个格式:只展示 ID、类型、标题和 Token 数——完整的细节需要用 MCP 搜索工具按需获取。这就是渐进式披露的核心思想。
3.2.3 UserPromptSubmit Hook:会话初始化
async function sessionInitHook(stdin: HookInput): Promise<void> {
const { session_id, prompt } = parseInput(stdin);
// 创建会话记录
await db.createSession({
sdk_session_id: generateId(),
claude_session_id: session_id,
project: extractProjectName(process.cwd()),
user_prompt: prompt // v4.2.0+: 保存原始提示用于搜索
});
// 确保 Worker 在运行
await ensureWorkerRunning();
}
这个 Hook 的巧妙之处在于:它同时保存了用户的原始提示。这意味着你之后可以用自然语言搜索"我上次让你修复的那个数据库问题",FTS5 能直接命中。
3.2.4 PostToolUse Hook:观测入队
这是整个系统中最频繁执行的 Hook——每次工具调用都会触发,一个会话可能触发上百次。
async function saveObservationHook(stdin: HookInput): Promise<HookOutput> {
const { tool_name, tool_input, tool_output } = parseInput(stdin);
// 快速入队,不等待处理
await db.enqueueObservation({
session_id: currentSession.id,
tool_name,
tool_input,
tool_output,
created_at_epoch: Date.now()
});
// 立即返回,不阻塞
return { continue: true, suppressOutput: true };
}
Fire-and-Forget 模式:Hook 只负责把数据丢进队列,处理是 Worker 的事。这种解耦保证了 Hook 的执行时间在 20ms 以内。
入队的数据结构:
{
"session_id": "abc123",
"tool_name": "Edit",
"tool_input": {
"file_path": "/path/to/auth.ts",
"old_string": "const token = jwt.sign(payload, secret);",
"new_string": "const token = jwt.sign(payload, secret, { expiresIn: '1h' });"
},
"tool_output": {
"success": true,
"linesChanged": 1
},
"created_at_epoch": 1715053200
}
3.2.5 Stop Hook:AI 摘要生成
当 Claude 停止响应时触发(注意:不是会话结束,是一次交互完成)。
<!-- AI 生成的摘要结构 -->
<summary>
<request>用户要求添加 JWT Token 过期机制</request>
<investigated>检查了 auth.ts、middleware/jwt.ts、config/auth.ts</investigated>
<learned>原实现没有设置 expiresIn 参数,导致 Token 永不过期</learned>
<completed>在 jwt.sign 调用中添加了 expiresIn: '1h',同时添加了刷新 Token 的中间件</completed>
<next_steps>需要添加 Token 过期的错误处理和自动刷新逻辑</next_steps>
<files_read>
<file>src/auth.ts</file>
<file>src/middleware/jwt.ts</file>
</files_read>
<files_modified>
<file>src/auth.ts</file>
</files_modified>
<notes>使用了 RS256 算法替代 HS256,因为项目需要支持多服务间 Token 共享</notes>
</summary>
一个会话可以产生多个摘要——每个 Stop 事件都会触发一次,形成"检查点"而非"终章"。这样即使会话很长,也不会丢失中间过程。
3.2.6 SessionEnd Hook:优雅清理
// v3 时代的暴力方式(已废弃)
SessionEnd → DELETE /worker/session → Worker 被强制终止
// v4.1.0+ 的优雅方式
SessionEnd → UPDATE sessions SET completed_at = NOW()
Worker 检测到完成 → 处理剩余观测 → 自然退出
为什么要优雅清理?因为暴力终止会导致:
- 正在生成的摘要被中断
- 队列中的观测丢失
- 竞态条件引发数据不一致
而且注意:/clear 命令不触发 SessionEnd,这样用户清屏不会意外结束会话追踪。
3.3 Worker Service:后台大脑
3.3.1 为什么需要后台 Worker?
Hook 必须在毫秒级返回,但 AI 压缩需要 5-30 秒。这个时间差必须用异步处理来填平。
┌─────────────────────────────────────┐
│ Hook(快) │
│ 1. 读取 stdin (< 1ms) │
│ 2. 插入队列 (< 10ms) │
│ 3. 返回成功 (< 20ms 总计) │
└─────────────────────────────────────┘
↓ (队列)
┌─────────────────────────────────────┐
│ Worker(慢) │
│ 1. 每秒轮询队列 │
│ 2. 用 Claude Agent SDK 处理 (5-30s)│
│ 3. 解析并存储结果 │
│ 4. 标记观测已处理 │
└─────────────────────────────────────┘
3.3.2 技术选型
| 层级 | 技术 | 选型理由 |
|---|---|---|
| 语言 | TypeScript (ES2022) | 与 Claude Code 生态一致 |
| 运行时 | Bun ≥ 1.0 | 快启动、低内存、内置 TypeScript |
| 数据库 | SQLite + bun:sqlite | 零配置、单文件、WAL 模式并发 |
| 向量库 | Chroma(可选) | 语义搜索增强 |
| HTTP 框架 | Express.js 5 | 成熟稳定、中间件生态 |
| 实时推送 | Server-Sent Events | 单向推送、比 WebSocket 轻量 |
| AI SDK | @anthropic-ai/claude-agent-sdk | 官方 SDK、质量保证 |
| 构建工具 | esbuild | 极速打包、TypeScript 原生支持 |
3.3.3 Worker HTTP API
Worker 不仅是后台处理器,还暴露了一组 HTTP API 供搜索和查看:
// 端口计算:基于用户 UID,避免多用户冲突
const defaultPort = 37700 + (uid % 100);
// 可通过 CLAUDE_MEM_WORKER_PORT 环境变量覆盖
// 核心 API 端点
app.get('/health', healthCheck);
app.post('/sessions', createSession);
app.get('/sessions/:id', getSession);
app.patch('/sessions/:id', updateSession);
app.post('/observations', enqueueObservation);
app.get('/observations/:id', getObservation);
// 搜索 API(10 个端点)
app.get('/api/search/observations', searchObservations);
app.get('/api/search/sessions', searchSessions);
app.get('/api/search/prompts', searchPrompts);
app.get('/api/search/by-concept', searchByConcept);
app.get('/api/search/by-file', searchByFile);
app.get('/api/search/by-type', searchByType);
app.get('/api/search/recent', getRecentContext);
app.get('/api/search/advanced', advancedSearch);
app.get('/api/timeline', getTimeline);
app.get('/api/observations/:id', getObservationDetail);
// SSE 端点(实时推送)
app.get('/api/stream', streamEvents);
// Viewer UI
app.use('/', express.static(viewerPath));
3.3.4 Bun 进程管理
Worker 的生命周期由 Bun 自动管理:
# 启动(Hook 自动触发,无需手动)
npm run worker:start
# 状态检查
npm run worker:status
# 查看日志
npm run worker:logs
# 重启
npm run worker:restart
# 停止
npm run worker:stop
Bun 的优势:
- 自动重启:Worker 崩溃后自动恢复
- 快启动:冷启动 < 100ms
- 低内存:常驻内存约 30-50MB
- 跨平台:macOS、Linux、Windows 一致体验
3.4 数据库架构:SQLite + FTS5
3.4.1 核心表结构
Claude-Mem 的数据存储在 ~/.claude-mem/claude-mem.db,使用 WAL 模式支持并发读写。
sdk_sessions 表——会话追踪:
CREATE TABLE sdk_sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sdk_session_id TEXT UNIQUE NOT NULL,
claude_session_id TEXT,
project TEXT NOT NULL,
prompt_counter INTEGER DEFAULT 0,
status TEXT NOT NULL DEFAULT 'active',
created_at TEXT NOT NULL,
created_at_epoch INTEGER NOT NULL,
completed_at TEXT,
completed_at_epoch INTEGER,
last_activity_at TEXT,
last_activity_epoch INTEGER
);
-- 关键索引
CREATE INDEX idx_sdk_sessions_project ON sdk_sessions(project);
CREATE INDEX idx_sdk_sessions_status ON sdk_sessions(status);
CREATE INDEX idx_sdk_sessions_created_at ON sdk_sessions(created_at_epoch DESC);
observations 表——观测数据(核心):
CREATE TABLE observations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
sdk_session_id TEXT NOT NULL,
claude_session_id TEXT,
project TEXT NOT NULL,
prompt_number INTEGER,
tool_name TEXT NOT NULL,
correlation_id TEXT,
-- 层次化字段
title TEXT,
subtitle TEXT,
narrative TEXT,
text TEXT,
facts TEXT,
concepts TEXT,
type TEXT, -- decision | bugfix | feature | refactor | discovery | change
files_read TEXT,
files_modified TEXT,
created_at TEXT NOT NULL,
created_at_epoch INTEGER NOT NULL,
FOREIGN KEY (sdk_session_id) REFERENCES sdk_sessions(sdk_session_id)
);
session_summaries 表——AI 生成的会话摘要:
CREATE TABLE session_summaries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sdk_session_id TEXT NOT NULL,
claude_session_id TEXT,
project TEXT NOT NULL,
prompt_number INTEGER,
request TEXT, -- 用户原始请求
investigated TEXT, -- 检查了什么
learned TEXT, -- 发现了什么
completed TEXT, -- 完成了什么
next_steps TEXT, -- 后续步骤
notes TEXT, -- 额外备注
created_at TEXT NOT NULL,
created_at_epoch INTEGER NOT NULL
);
user_prompts 表——用户提示全文(v4.2.0+):
CREATE TABLE user_prompts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sdk_session_id TEXT NOT NULL,
claude_session_id TEXT,
project TEXT NOT NULL,
prompt_number INTEGER,
prompt_text TEXT NOT NULL,
created_at TEXT NOT NULL,
created_at_epoch INTEGER NOT NULL
);
3.4.2 FTS5 全文搜索引擎
Claude-Mem 为每个核心表创建了 FTS5 虚拟表,实现毫秒级全文检索:
-- 观测全文搜索
CREATE VIRTUAL TABLE observations_fts USING fts5(
title, subtitle, narrative, text, facts, concepts,
content='observations', content_rowid='id'
);
-- 摘要全文搜索
CREATE VIRTUAL TABLE session_summaries_fts USING fts5(
request, investigated, learned, completed, next_steps, notes,
content='session_summaries', content_rowid='id'
);
-- 用户提示全文搜索
CREATE VIRTUAL TABLE user_prompts_fts USING fts5(
prompt_text,
content='user_prompts', content_rowid='id'
);
自动同步触发器——保证 FTS 索引与源表一致:
-- 插入触发器
CREATE TRIGGER observations_ai AFTER INSERT ON observations BEGIN
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
END;
-- 更新触发器(先删旧索引,再插新索引)
CREATE TRIGGER observations_au AFTER UPDATE ON observations BEGIN
INSERT INTO observations_fts(observations_fts, rowid, title, subtitle, narrative, text, facts, concepts)
VALUES('delete', old.id, old.title, old.subtitle, old.narrative, old.text, old.facts, old.concepts);
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
END;
-- 删除触发器
CREATE TRIGGER observations_ad AFTER DELETE ON observations BEGIN
INSERT INTO observations_fts(observations_fts, rowid, title, subtitle, narrative, text, facts, concepts)
VALUES('delete', old.id, old.title, old.subtitle, old.narrative, old.text, old.facts, old.concepts);
END;
FTS5 的查询语法支持丰富:
-- 简单搜索
SELECT * FROM observations_fts WHERE observations_fts MATCH 'authentication';
-- AND/OR/NOT
SELECT * FROM observations_fts WHERE observations_fts MATCH 'error AND database';
SELECT * FROM observations_fts WHERE observations_fts MATCH 'bug OR fix';
SELECT * FROM observations_fts WHERE observations_fts MATCH 'security NOT deprecated';
-- 精确短语
SELECT * FROM observations_fts WHERE observations_fts MATCH '"database migration"';
-- 列限定搜索
SELECT * FROM observations_fts WHERE observations_fts MATCH 'title:authentication';
SELECT * FROM observations_fts WHERE observations_fts MATCH 'concepts:security';
-- 组合查询
SELECT * FROM observations_fts WHERE observations_fts MATCH '"user auth" AND (JWT OR session) NOT deprecated';
安全防护(v4.2.3+):所有 FTS5 查询都经过转义,防止 SQL 注入:
function escapeFTSQuery(query: string): string {
return query.replace(/"/g, '""');
}
// 332 个注入攻击测试用例覆盖
3.4.3 数据库迁移策略
Claude-Mem 使用渐进式迁移管理 schema 演进:
Migration 001: 初始 schema(sessions, memories, overviews)
Migration 002: 层次化记忆字段(title, subtitle, facts, concepts)
Migration 003: SDK 会话和观测
Migration 004: 会话摘要
Migration 005: 多提示会话(prompt_counter, prompt_number)
Migration 006: FTS5 虚拟表和触发器
Migration 007-010: 各种改进和用户提示表
3.5 搜索架构:渐进式披露的哲学
3.5.1 为什么不能"一次全拉"?
传统 RAG 方案的做法:检索所有相关文档,一股脑塞进上下文窗口。这在记忆系统中行不通:
- 20 条完整观测 = 10,000-20,000 Token
- 其中只有 10% 真正相关
- 浪费了 18,000 Token 在不相关的内容上
- 还挤占了 Claude 处理实际任务的 Token 空间
3.5.2 三层检索工作流
Claude-Mem 的解决方案是"渐进式披露"(Progressive Disclosure),分三层逐步获取信息:
第一层:Search(索引)
// 获取轻量级索引
search(query: "authentication bug", type: "bugfix", limit: 10)
// 返回:ID + 标题 + 时间 + 类型,每条约 50-100 Token
第二层:Timeline(上下文)
// 获取某个时间点前后的上下文
timeline(anchor: 12345, depth_before: 3, depth_after: 3)
// 或基于查询自动定位
timeline(query: "authentication", depth_before: 2, depth_after: 2)
// 返回:时间线视图,每条约 100-200 Token
第三层:Get Observations(完整详情)
// 只获取筛选后的关键观测的完整信息
get_observations(ids: [123, 456, 789])
// 返回:完整叙述、事实、文件列表、概念标签,每条约 500-1000 Token
Token 节省效果:
| 方法 | Token 消耗 | 相关性 |
|---|---|---|
| 全量拉取 20 条 | 10,000-20,000 | ~10% |
| 三层检索 | 3,000-4,000 | ~100% |
| 节省 | 70-80% | 10x 提升 |
3.5.3 MCP 搜索工具
Claude-Mem 通过 4 个 MCP 工具暴露搜索能力:
__IMPORTANT:工作流文档,自动展示,提示 Claude 如何使用三层检索search:搜索记忆索引,支持 FTS5 完整语法timeline:获取时间线上下文get_observations:按 ID 批量获取完整观测
同时提供 mem-search Skill(v5.4.0+),通过 HTTP API 直接调用,比 MCP 更省 Token:
- Skill 前置信息:约 250 Token(会话启动时加载)
- 完整指令:约 2,500 Token(按需加载)
- 比 MCP 方式每会话节省约 2,250 Token
3.5.4 混合搜索:FTS5 + Chroma 向量
Claude-Mem 的搜索不是单纯的全文检索,而是混合搜索:
- FTS5:精确关键词匹配,速度快,确定性高
- Chroma 向量搜索:语义相似度匹配,能理解"认证"和"鉴权"是同一概念
// ChromaSync:可选的向量索引同步
class ChromaSync {
async syncObservation(observation: Observation): Promise<void> {
// 将观测的 embedding 存入 Chroma
const embedding = await this.generateEmbedding(observation.narrative);
await this.chroma.upsert({
id: observation.id.toString(),
embedding,
metadata: {
type: observation.type,
project: observation.project,
concepts: observation.concepts
}
});
}
}
Chroma 是可选组件,不安装也能用 FTS5 正常搜索。但有了它,语义搜索能力显著增强。
四、代码实战:从安装到生产部署
4.1 快速安装
# 方式一:npx 一键安装(推荐)
npx claude-mem install
# 方式二:插件市场安装
# 在 Claude Code 终端中执行:
/plugin marketplace add thedotmack/claude-mem
/plugin install claude-mem
# 方式三:OpenClaw 一键安装
curl -fsSL https://install.cmem.ai/openclaw.sh | bash
安装过程做了什么:
- 检测并安装 Bun 运行时(如果缺失)
- 检测并安装 uv Python 包管理器(向量搜索需要)
- 在插件缓存目录执行
bun install - 写入
.install-version标记文件 - 注册 Hook 脚本到 Claude Code 的
settings.json
4.2 验证安装
# 检查 Worker 是否运行
curl http://localhost:37777/health
# 打开 Web 查看器
open http://localhost:37777
# 在 Claude Code 中查看插件状态
/plugin list
4.3 配置详解
配置文件位置:~/.claude-mem/settings.json
{
"CLAUDE_MEM_MODE": "code--zh",
"CLAUDE_MEM_CONTEXT_OBSERVATIONS": 50,
"CLAUDE_MEM_WORKER_PORT": 37777,
"CLAUDE_MEM_DATA_DIR": "~/.claude-mem",
"CLAUDE_MEM_LOG_LEVEL": "info"
}
工作模式:
| 模式 | 语言 | 描述 |
|---|---|---|
code | English | 默认英文模式 |
code--zh | 简体中文 | 中文模式,生成的观测用中文 |
code--ja | 日本語 | 日文模式 |
模式格式为 code--[lang],其中 lang 是 ISO 639-1 语言代码。选择中文模式后,Claude-Mem 生成的观测标题、叙述、事实等都会用中文,FTS5 搜索中文也更准确。
4.4 实战场景:Debug 历史回溯
假设你两周前修过一个数据库连接的 Bug,现在类似的问题又出现了。你问 Claude Code:
"上次我们修的那个数据库连接超时的问题,当时是怎么解决的?"
Claude 会自动调用 MCP 搜索工具:
Step 1: search(query="数据库连接超时", type="bugfix", limit=10)
→ 找到 3 条相关观测:#245, #312, #489
Step 2: timeline(anchor=312, depth_before=3, depth_after=3)
→ 看到 Bug 修复前后发生了什么
Step 3: get_observations(ids=[312, 489])
→ 获取完整的修复过程:改了什么文件、为什么、有什么约束
Claude 现在不仅知道你修过这个 Bug,还知道具体的修复方案、涉及的文件、以及当时的决策理由。这就是持久记忆的价值。
4.5 实战场景:架构决策追溯
Step 1: search(query="缓存", type="decision", limit=5)
→ 找到决策观测:"选择 Redis 做缓存层"
Step 2: get_observations(ids=[2587])
→ 获取完整决策理由:
- 为什么选 Redis 不选 Memcached?
- 考虑了哪些备选方案?
- 有什么已知限制?
- 数据一致性要求是什么?
4.6 实战场景:代码考古
想了解某个文件为什么长这样:
Step 1: search(query="worker-service.ts", limit=20)
→ 找到所有涉及该文件的观测
Step 2: timeline(query="worker-service.ts refactor", depth_before=2, depth_after=2)
→ 看到重构的前因后果
Step 3: get_observations(ids=[关键里程碑])
→ 深入每次变更的实现细节
4.7 Gemini CLI 和 OpenCode 支持
Claude-Mem 不止支持 Claude Code,还能给 Gemini CLI 和 OpenCode 加记忆:
# Gemini CLI 安装
npx claude-mem install --ide gemini-cli
# OpenCode 安装
npx claude-mem install --ide opencode
底层原理一样——都是通过 Hook 机制捕获工具调用,只是注册方式和 Hook 路径不同。
4.8 隐私控制
不是所有内容都应该被记忆。Claude-Mem 提供了两层隐私控制:
标签过滤:用 <private> 标签标记的内容不会被存储
<private>
API_KEY=sk-xxxx
DATABASE_URL=postgres://admin:password@...
</private>
精细上下文配置:控制哪些内容被注入到上下文中
{
"CLAUDE_MEM_EXCLUDE_PATTERNS": [
"**/*.env",
"**/secrets/**",
"**/credentials/**"
]
}
五、性能优化:Token 效率之道
5.1 Token 是最昂贵的资源
在 AI 编程助手的场景中,Token 不只是钱的问题,更是上下文窗口的容量问题。每多注入一个 Token 的历史记忆,就少了一个 Token 用于当前任务。Claude-Mem 的每个设计决策都围绕 Token 效率展开。
5.2 Skill vs MCP:2,250 Token 的差距
v5.4.0 引入的 mem-search Skill 比 MCP 方式每会话节省约 2,250 Token:
| 方式 | 前置 Token | 按需 Token | 总计 |
|---|---|---|---|
| MCP(4 个工具) | ~2,500 | 0 | 2,500 |
| Skill | ~250 | ~2,500(按需加载) | 250-2,750 |
| 差异 | -2,250 |
MCP 方式的问题是:4 个工具的 schema 定义和描述在每次会话中都会被加载,即使你不用搜索功能。Skill 方式只在被调用时才加载完整指令,平时只占 250 Token 的轻量前置信息。
5.3 渐进式披露的数学
假设一个项目有 500 条观测,你想找"认证相关的 Bug 修复":
传统方案:
500 条完整观测 × 750 Token/条 = 375,000 Token
这根本塞不进上下文窗口。
Claude-Mem 三层方案:
第一层:search 返回 10 条索引 × 75 Token/条 = 750 Token
第二层:timeline 返回 6 条上下文 × 150 Token/条 = 900 Token
第三层:get_observations 返回 3 条详情 × 750 Token/条 = 2,250 Token
总计:3,900 Token
节省了 99% 的 Token,同时保持了 100% 的相关性。
5.4 Worker 的性能考量
队列处理延迟:Worker 每秒轮询一次队列。从 Hook 入队到 Worker 开始处理,最大延迟 1 秒。AI 压缩每条观测需要 5-30 秒,但这是异步的,不影响主会话。
数据库性能:
- SQLite WAL 模式允许并发读写
- bun:sqlite 使用同步 API,比异步 API 更快(在单线程 Bun 运行时中,异步没有优势)
- 所有外键和常用查询列都有索引
- FTS5 搜索比 LIKE 查询快 10-100 倍
内存占用:Worker 常驻内存约 30-50MB,这在现代开发环境中完全可以接受。
5.5 版本检查的亚毫秒保证
Setup Hook 是每次 Claude Code 启动都会执行的,它必须绝对不影响启动速度:
// 整个操作只有一次文件读取 + 一次字符串比较
function versionCheck() {
const marker = readFileSync('.install-version', 'utf8'); // < 1ms
const current = PACKAGE_VERSION; // 内存中
if (marker.trim() !== current) {
process.stderr.write('run: npx claude-mem repair');
}
return 0;
}
实测执行时间 < 50ms,用户完全无感知。
六、设计模式提炼:可复用的架构智慧
6.1 Fire-and-Forget Hook
// ❌ 坏:Hook 等待处理完成
async function badHook(input: HookInput) {
const observation = parseInput(input);
await processObservation(observation); // 阻塞!5-30 秒!
return success();
}
// ✅ 好:Hook 入队后立即返回
async function goodHook(input: HookInput) {
const observation = parseInput(input);
await enqueueObservation(observation); // 快速入队 < 10ms
return success(); // 立即返回
}
这个模式在任何需要"捕获但不阻塞"的场景中都适用:日志采集、指标上报、事件溯源。
6.2 队列解耦模式
Hook(捕获)→ 队列(缓冲)→ Worker(处理)
好处:
- Hook 和 Worker 可以独立失败和重试
- 并行 Hook 执行安全(每个 Hook 有自己的 stdin)
- 重试逻辑集中在一处
- 天然支持背压处理
6.3 优雅降级模式
try {
await captureObservation();
} catch (error) {
// 记录错误,但不抛出
console.error('Memory capture failed:', error);
return { continue: true, suppressOutput: true };
}
失败场景的处理策略:
- 数据库锁死 → 跳过本次观测,记录错误
- Worker 崩溃 → Bun 自动重启
- 网络问题 → 指数退避重试
- 磁盘满 → 警告用户,禁用记忆
6.4 渐进增强模式
没有记忆系统 → 正常工作
有记忆系统 → 增强版工作
记忆系统故障 → 降级到正常工作
这不是可选的,是必须的。任何扩展 Claude Code 的插件都应该遵循这个原则。
6.5 渐进式披露模式
适用于任何"信息量大但实际需求少"的场景:
- IDE 的代码导航(先看大纲,再看具体实现)
- 日志查看器(先看摘要,再看全文)
- 监控面板(先看概览,再看详情)
七、Beta 功能:Endless Mode
Claude-Mem 还有一个实验性功能叫 Endless Mode(无尽模式),采用仿生记忆架构(Biomimetic Memory Architecture),旨在突破单次会话的上下文限制。
核心思想:人类的记忆不是"全部记住然后全部回忆",而是有一个"工作记忆"(短期)和"长期记忆"的分层系统。Endless Mode 模拟了这种分层:
- 工作记忆:当前活跃的观测,完整保留
- 短期记忆:最近的观测,压缩但可检索
- 长期记忆:历史观测,高度压缩,只保留核心概念
在 Web 查看器(http://localhost:37777)的 Settings 中可以切换 stable/beta 版本。
八、架构演进史:从 v3 到 v5
Claude-Mem 的架构经历了三个大版本的演进,每一版都在解决上一版的痛点:
v3 时代:简单直接
- 直接在 Hook 中处理观测(阻塞!)
- Worker 通过 DELETE 命令管理(暴力!)
- 简单的 memories 表存储压缩块
- 没有层次化结构,搜索靠 LIKE
v4 时代:异步化 + 结构化
- 引入 observation_queue 队列表
- Worker 异步处理,Hook 不再阻塞
- 层次化观测字段(title, subtitle, narrative...)
- FTS5 全文搜索
- 用户提示全文保存
- 多摘要检查点(而非单次终局摘要)
- 优雅会话清理
v5 时代:效率优化
- mem-search Skill 替代纯 MCP 工具
- 渐进式披露索引(索引→时间线→详情)
- Chroma 向量搜索(可选)
- Web 查看器(React + SSE 实时推送)
- Beta Channel 和 Endless Mode
- 多 IDE 支持(Claude Code + Gemini CLI + OpenCode)
每一次演进都在回答同一个问题:如何在有限的 Token 预算内,让 AI 记住更多有用的东西?
九、竞品对比与定位
| 特性 | Claude-Mem | CLAUDE.md | auto memory | 外部 RAG |
|---|---|---|---|---|
| 自动捕获 | ✅ 全自动 | ❌ 手写 | 🟡 部分自动 | ❌ 需要自建 |
| AI 压缩 | ✅ Agent SDK | ❌ | ❌ | 🟡 看实现 |
| 全文搜索 | ✅ FTS5 | ❌ | ❌ | 🟡 看实现 |
| 语义搜索 | ✅ Chroma | ❌ | ❌ | 🟡 看实现 |
| 渐进式披露 | ✅ 三层 | ❌ | ❌ | ❌ |
| 非侵入式 | ✅ | ✅ | ✅ | 🟡 |
| 多 IDE 支持 | ✅ | ❌ | ❌ | ❌ |
| Web 查看器 | ✅ | ❌ | ❌ | ❌ |
| 实时推送 | ✅ SSE | ❌ | ❌ | ❌ |
Claude-Mem 的核心优势:全自动 + AI 压缩 + 渐进式检索。你不需要做任何额外工作,它就像你的记忆一样,在后台默默工作。
十、总结与展望
10.1 Claude-Mem 解决了什么问题?
Claude-Mem 解决的是 AI 编程助手的"失忆症"——通过 Hook 生命周期架构自动捕获编码过程,通过 AI 压缩提炼关键信息,通过渐进式披露在有限 Token 预算内智能检索和注入上下文。
10.2 架构的精妙之处
- 非侵入式:不修改 Claude Code,只通过 Hook 观察
- 异步解耦:Hook 毫秒级返回,Worker 异步处理
- 渐进式披露:三层检索,10x Token 节省
- 优雅降级:记忆系统故障不影响 Claude Code
- 层次化存储:从标题到叙述,从索引到全文
10.3 适用场景
- 长期项目维护:跨会话保持项目上下文
- Bug 排查:回溯历史修复过程
- 架构决策:追溯技术选型的理由
- 团队协作:新人快速了解项目历史
- 代码考古:理解代码演化的来龙去脉
10.4 未来展望
随着 AI 编程助手越来越强,记忆系统只会越来越重要。Claude-Mem 目前的方向:
- 跨项目记忆:在项目间共享通用的编码模式
- 团队记忆:团队成员共享项目知识库
- 更智能的压缩:利用更小的模型本地压缩,降低 API 成本
- Endless Mode 正式版:突破单次会话上下文限制
- 多模态记忆:不只记忆文本,还记忆图表、截图
一句话总结:Claude-Mem 不只是一个插件,它是一种"AI 记忆系统"的参考架构——Hook 生命周期 + 异步队列 + AI 压缩 + 渐进式检索。如果你正在构建任何需要"让 AI 记住东西"的系统,这套架构值得深入研究。
项目地址:github.com/thedotmack/claude-mem | Star 数:56K+ | 许可证:AGPL-3.0 | 官方文档:docs.claude-mem.ai