llm-wiki wiki · sources 2026-05-12

claude-mem 架构与设计思路分析

2026-05-12 · 来源:claude-mem-architecture-analysis.md

agent-memoryclaude-codearchitecturellm-infra

原文:raw/claude-mem-architecture-analysis.md · 仓库:thedotmack/claude-mem · 分析版本 v13.1.0

一句话定位

claude-mem 是给 claude-code 装上"长期记忆"的开源插件——通过宿主的 6 个 Lifecycle Hook 无侵入采集工具调用,用 claude-agent-sdk 异步压缩成结构化"观察 (observation)",存进本地 SQLite + Chroma 双索引;下次开会话时自动检索相关历史并注入上下文。

核心架构(三层)

组件 职责
边缘层 bun-runner.js + 6 个 hook handler 轻量 stdin 接力,禁止做 AI 推理
后台层 Worker Service (Express daemon, 端口 37700 + uid%100) + BullMQ 异步压缩、入库、向量同步
存储层 SQLite (FTS5 全文) + Chroma (向量) 双索引

详见 event-driven-memory-pipeline

完整架构图

flowchart TB subgraph CC["CLAUDE CODE 运行时"] direction TB subgraph HOOKS["事件钩子 — plugin/hooks/hooks.json 注册的 6 个 Lifecycle 钩子"] direction LR H1["SessionStart"] H2["UserPromptSub"] H3["PreToolUse(Read)"] H4["PostToolUse"] end Bun["bun-runner.js
轻量 stdin 接力 → 派发 worker-service 子命令"] HOOKS --> Bun end subgraph WS["Worker Service — Express daemon"] direction TB WSrv["src/services/worker-service.ts
端口: 37700 + (uid % 100) · PID: ~/.claude-mem/worker.pid"] Routes["路由层 (7 组 Routes)
/api/context/* · /api/sessions/* · /api/observations
/api/search/* · /api/memory/save · /api/chroma/status · /v1/*"] Prov["Providers
Claude / Gemini / OR
(Agent SDK 调用)"] RP["ResponseProcessor
XML → Observation
事务批量入库"] CS["ChromaSync
向量同步 + watermark 回填"] WSrv --> Routes Prov --> RP --> CS end SQ["SQLite — ~/.claude-mem/.db
observations / FTS5 · sessions / prompts"] Ch["Chroma 向量库 — ~/.claude-mem/chroma
语义检索"] subgraph CONS["消费者"] direction LR Sk["mem-search Skill
3 层搜索协议
search → timeline → get_observations"] UI["Viewer UI (React)
SSE 流式渲染
时间线 / 观察列表"] end CC -- "HTTP / 进程派发" --> WS RP --> SQ CS --> Ch SQ --> Sk SQ --> UI Ch --> Sk Ch --> UI classDef cc fill:#1e3a8a,stroke:#1e40af,color:#fff classDef ws fill:#7c2d12,stroke:#9a3412,color:#fff classDef st fill:#14532d,stroke:#166534,color:#fff classDef cn fill:#5b21b6,stroke:#6d28d9,color:#fff class CC,HOOKS,H1,H2,H3,H4,Bun cc class WS,WSrv,Routes,Prov,RP,CS ws class SQ,Ch st class CONS,Sk,UI cn
原 ASCII 图
┌─────────────────────────  CLAUDE CODE 运行时  ─────────────────────────┐
│                                                                          │
│  事件钩子(plugin/hooks/hooks.json 注册的 6 个 Lifecycle 钩子)           │
│  ┌────────────┐ ┌──────────────┐ ┌────────────────┐ ┌─────────────┐    │
│  │SessionStart│ │UserPromptSub │ │PreToolUse(Read)│ │PostToolUse  │    │
│  └─────┬──────┘ └──────┬───────┘ └────────┬───────┘ └──────┬──────┘    │
│        │               │                  │                │           │
│        ▼               ▼                  ▼                ▼           │
│   bun-runner.js(轻量 stdin 接力 → 派发 worker-service 子命令)           │
└─────────────────────────────┬───────────────────────────────────────────┘
                              │ HTTP / 进程派发
                              ▼
┌────────────────────  Worker Service (Express daemon)  ────────────────────┐
│  src/services/worker-service.ts                                            │
│  端口: 37700 + (uid % 100)  •  PID: ~/.claude-mem/worker.pid               │
│                                                                            │
│  路由层(7 组 Routes)                                                     │
│   /api/context/*   /api/sessions/*   /api/observations                     │
│   /api/search/*    /api/memory/save  /api/chroma/status   /v1/*            │
│                                                                            │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────────┐    │
│  │ Providers        │  │ ResponseProcessor│  │ ChromaSync           │    │
│  │ Claude/Gemini/OR │→ │ XML→Observation  │→ │ 向量同步 + watermark │    │
│  │ (Agent SDK 调用) │  │ 事务批量入库     │  │ 回填                  │    │
│  └──────────────────┘  └────────┬─────────┘  └──────────┬───────────┘    │
└─────────────────────────────────┼────────────────────────┼────────────────┘
                                  ▼                        ▼
                       ┌────────────────────┐   ┌────────────────────┐
                       │ SQLite             │   │ Chroma 向量库      │
                       │ ~/.claude-mem/.db  │   │ ~/.claude-mem/chroma│
                       │ observations / FTS5│   │ 语义检索           │
                       │ sessions / prompts │   │                    │
                       └─────────┬──────────┘   └─────────┬──────────┘
                                 └─────────┬──────────────┘
                                           │
                          ┌────────────────┴────────────────┐
                          ▼                                 ▼
                ┌──────────────────┐               ┌──────────────────┐
                │ mem-search Skill │               │ Viewer UI (React)│
                │ 3 层搜索协议     │               │ SSE 流式渲染     │
                │ search→timeline  │               │ 时间线/观察列表  │
                │ →get_observations│               │                  │
                └──────────────────┘               └──────────────────┘

六个生命周期钩子

阶段 触发 Handler 作用
Setup 插件初始化 version-check.js 版本兼容性
SessionStart 启动/clear/compact context.ts 启 worker + 注入历史上下文
UserPromptSubmit 用户提交 prompt session-init.ts 创建 session + 触发语义搜索
PreToolUse(Read) 读文件前 file-context.ts 查当前文件相关观察
PostToolUse 任何工具调用后 observation.ts 入队等待压缩
Stop 会话结束 summarize.ts 生成会话摘要

五步闭环

  1. 捕获:Hook → bun-runner.js → worker handler → POST 给本地 worker
  2. 入队:写 outbox(Postgres)或 SQLite 暂存,BullMQ 调度
  3. AI 压缩ProviderObservationGenerator 调 Agent SDK,把 tool log 压成 XML 观察
  4. 解析存储sdk/parser.tsMemoryItem schema → 事务写入 SQLite + 异步推 Chroma
  5. 注入回流SessionStart 预检索 → system 消息;或 mem-search Skill 按需查询

六大可移植设计模式

  1. 生命周期钩子采集 — 任何有 before/after tool_use 钩子的 runtime 都能挂
  2. 边缘轻量 + 后台 AI 重活 — 用户交互路径上绝不做 AI 推理
  3. 三层搜索协议search → timeline → get_observations,详见 three-tier-search-protocol
  4. AI 作为压缩器 — 详见 ai-as-compressor
  5. session_id 双轨制contentSessionId(会话)vs memorySessionId(记忆线)
  6. Outbox + 内容哈希去重 — AI 生成非确定,必须去重;outbox 让重试不丢消息

MemoryItem Schema

{
  kind: 'observation' | 'summary' | 'prompt' | 'manual',
  type: string,
  title: string,
  narrative: string,       // 自然语言叙述
  facts: string[],         // 离散事实点
  concepts: string[],      // 抽象概念标签
  filesRead: string[],
  filesModified: string[]
}

[!note] 关键洞察
别只存"对话历史",先压缩成"事实/概念/读写文件"等可索引字段;语义搜索叠在结构化层之上。

多 Profile 隔离

export CLAUDE_MEM_DATA_DIR="$HOME/.claude-mem-work"
export CLAUDE_MEM_WORKER_PORT=37800

所有路径(DB、Chroma、日志、PID)从 env 派生,shell 级隔离。

演进信号

近 30 天最活跃:worker-service.cjs(88 次)、mcp-server.cjs(75 次)。PR #2383 把 worker 重写为 server-beta:事件管道 + Postgres + MCP + Docker + 团队审计。趋势是从「单机插件」→「团队后台服务」,但 runtime-selector.ts 保留单机 SQLite 回退。

关键文件索引

关注点 路径
钩子注册 plugin/hooks/hooks.json
Hook 派发 plugin/scripts/bun-runner.js
Worker 入口 src/services/worker-service.ts
Provider 抽象 src/sdk/{Claude,Gemini,OpenRouter}Provider.ts
XML 解析 src/sdk/parser.ts
上下文构建 src/services/context/ContextBuilder.ts
压缩 Prompt src/sdk/prompts.ts
搜索 Skill plugin/skills/mem-search/SKILL.md

最小可行落地(抄作业 5 步)

给任何 Agent 加记忆的最小套路:

  1. 采集:tool callback 里 record_event(event) 塞 SQLite outbox
  2. 压缩:cron/worker 跑 compress_batch(),喂给便宜模型(Haiku / Gemini Flash)输出 {title, narrative, facts[], concepts[]} JSON
  3. 双索引:SQLite FTS5 + 向量库
  4. 注册搜索工具search_memory(query),描述写"用户提到过去/上次时调用"
  5. 会话启动预检索:基于"项目路径 + 最近活跃概念"拼 system prompt 前缀