简介:目前的 AI 编程助手通常只有“短期记忆”,一旦关闭当前的对话窗口,之前的项目背景、架构约定等上下文就会丢失。本文介绍了 Claude-mem 在 Claude code 流程中关键节点使用钩子的设计方法,完成不修改Claude code 的源码,实现持久化长期记忆。这个方法为我们在设计其他 Agent 框架增加记忆提供了有益的借鉴。

1. Claude-mem 简介

Claude-mem 由社区开发者(@thedotmack)专门为 Claude Code 打造的第三方开源记忆插件。主要解决了 Claude Code 在跨天或跨会话时“失忆”的痛点。

目前的 AI 编程助手通常只有“短期记忆”,一旦关闭当前的对话窗口,之前的项目背景、架构约定等上下文就会丢失。Claude-Mem 的作用就是给 Claude Code 装上跨会话的持久化长期记忆。

Claude-Mem 通过自动捕捉工具使用观察、生成语义摘要,无缝保存了会话间的上下文;这些信息可以被后续的会话所利用。这使得 Claude 即使在对话结束或重新连接后,仍能保持项目知识的连续性。

  • Claude-mem 的工作原理如下:

    • 隐形捕获:它通过监听 Claude Code 的生命周期(比如你提交问题、工具调用完成、会话结束时),自动捕获有价值的操作记录(例如改了哪些文件、执行了什么命令),将其转化为结构化的“观察记录”。
    • 本地混合存储:所有数据都存储在你本地的 ~/.claude-mem/ 目录下,不会上传到云端,对隐私非常友好。它结合了 SQLite(用于结构化数据和全文检索)和 Chroma 向量库(用于语义检索)。
    • 按需注入:当你开启新会话时,它会根据当前的上下文,通过三层渐进式检索,自动把相关的历史记忆“喂”给 Claude,而不需要你把所有旧聊天记录重新复制一遍。
  • 带来的实际收益

    • 大幅节省 Token:常规场景下可以节省约 90% 的 Token 消耗,因为不需要在每次对话中重复解释项目背景。
    • 工作流程不中断:即使隔了好几天再回来继续做架构或写代码,Claude 也能迅速接上之前的思路,不需要你“人肉补档”。

2. Claude-mem 的工作流程

在这里插入图片描述

  • Claude-mem 工作流程
  1. 智能安装预钩子

    • 检查依赖(已缓存),仅在版本变更时运行
    • 非生命周期钩子——在上下文钩子启动前运行
  2. 会话开始 → 上下文钩子触发

    • 按需启动 Bun 工作进程
    • 注入来自之前会话的上下文(可配置的观测次数)
  3. 用户输入提示 → 用户提示提交钩子触发

    • 在数据库中创建会话
    • 保存原始用户提示以供 FTS5 使用
  4. Claude 使用工具 → 工具使用后钩子触发(100+ 次)

    • 捕获工具执行记录
    • 发送给工作进程进行 AI 压缩
  5. 工作进程处理 → Claude Agent SDK 分析

    • 通过迭代式 AI 处理提取结构化学习内容
  6. Claude 停止 → 摘要钩子触发

    • 生成包含请求、完成情况、学习内容的最终摘要
  7. 会话结束 → 清理钩子触发

    • 将会话标记为完成(优雅处理,非删除),以备下次会话上下文使用
    • 遇到 /clear 命令时跳过,以保留进行中的会话

3. 基于钩子的设计

Claude-Mem 核心原则:从外部观察主 Claude Code 会话,在后台处理观察,并在合适的时间注入上下文。

基于这个原则的主要原因是:对Claude Code 的非侵入性要求

  • 无法修改 Claude 代码 :它是闭源二进制文件
  • 必须快 :不能使原来的运行速度放慢
  • 必须可靠 :Claude 运行时必须保持运行可靠
  • 必须简单 :可在任何项目中无需配置即可运行

基于这些原因的要求,Claude-mem 引入了钩子系统。

  • 解决方案: 通过 settings.json 配置的外部命令钩子

3.1. Claude-Mem 使用的钩子

┌─────────────────────────────────────────────────────────┐
│              CLAUDE CODE SESSION                        │
│  (Main session - user interacting with Claude)          │
│                                                         │
│  SessionStart → UserPromptSubmit → Tool Use → Stop      │
│     ↓ ↓ ↓            ↓               ↓          ↓       │
│  [3 Hooks]        [Hook]          [Hook]     [Hook]     │
└─────────────────────────────────────────────────────────┘
    ↓ ↓ ↓             ↓               ↓          ↓
┌─────────────────────────────────────────────────────────┐
│                  CLAUDE-MEM SYSTEM                      │
│                                                         │
│  Smart      Worker      Context    New        Obs       │
│  Install    Start       Inject     Session    Capture   │
└─────────────────────────────────────────────────────────┘

3.2. 预挂钩:智能安装(SessionStart 前)

  • 目的:
    智能管理依赖并启动 worker 服务。 这不是生命周期钩子。它是通过命令链执行的预钩脚本,在上下文钩子运行前执行。

  • 触发点:Claude 代码启动(启动、清除或压缩)

  • 它的作用:

    • 检查依赖是否需要安装(版本标记)
    • 只有在必要时才运行 npm 安装 :
      • 首次安装
      • 版本在 package.json 中更改
    • 提供 Windows 特定的错误信息
    • 启动 Bun 工作进程
  • 触发点:Claude 代码启动、清除或压缩;

  • 主要代码:scripts/smart-install.js

3.2.1. 配置

{
  "hooks": {
    "SessionStart": [{
      "matcher": "startup|clear|compact",
      "hooks": [{
        "type": "command",
        "command": "node \"${CLAUDE_PLUGIN_ROOT}/../scripts/smart-install.js\" && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js",
        "timeout": 300
      }]
    }]
  }
}

3.3. 钩子 1:SessionStart - 上下文注入

  • 目的:
    注入之前的会话中相关的背景。

  • 触发点::Claude 代码启动(在智能安装预挂钩后运行)

  • 它的作用:

    • 从当前工作目录中提取项目名称
    • 查询 SQLite,用于最近 10 次会话摘要
    • 查询 SQLite 的最新观测值(可配置,默认 50)
    • 作为渐进披露指数的格式
    • 输出到标准输出(自动注入上下文)
  • 主要代码:src/hooks/context-hook.ts

3.3.1. 注入输出格式:

# [claude-mem] recent context

**Legend:** 🎯 session-request | 🔴 gotcha | 🟡 problem-solution ...

### Oct 26, 2025

**General**
| ID    | Time     | T   | Title                   | Tokens |
| ----- | -------- | --- | ----------------------- | ------ |
| #2586 | 12:58 AM | 🔵   | Context hook file empty | ~51    |

*Use MCP search tools to access full details*

3.4. 钩子 2:UserPromptSubmit - 保存用户提示词

  • 目的: 用户提交提示词时初始化会话跟踪
  • 触发点: 在 Claude 处理用户消息之前
  • 它的作用:
    • 读取 stdin 中的用户提示词和会话 ID
    • 在 SQLite 中创建新的会话记录
    • 保存原始用户提示词以进行全文搜索
    • 自动启动 Bun 工作进程
    • 立即返回(非阻塞)
  • 主要代码:src/hooks/new-hook.ts

3.4.1. 配置

{
  "hooks": {
    "UserPromptSubmit": [{
      "hooks": [{
        "type": "command",
        "command": "${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js"
      }]
    }]
  }
}

3.4.2. 数据库操作

INSERT INTO sdk_sessions (claude_session_id, project, user_prompt, ...)
VALUES (?, ?, ?, ...)

INSERT INTO user_prompts (session_id, prompt, prompt_number, ...)
VALUES (?, ?, ?, ...)

3.5. 钩子3:工具使用后 – 保存工具执行结果

  • 目的: 捕获工具执行结果,以供后续处理
  • 触发点:任何工具成功完成后立即生效
  • 它的作用:
    • 接收工具名称、输入和输出
    • 查找当前项目的活跃会话
    • 在 observation_queue 表中排队观察
    • 完成立即退出(处理在 worker 中进行)
  • 主要代码:src/hooks/save-hook.ts

3.5.1. 配置

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "*",
      "hooks": [{
        "type": "command",
        "command": "${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js"
      }]
    }]
  }
}

3.5.2. 数据库操作

INSERT INTO observation_queue (session_id, tool_name, tool_input, tool_output, ...)
VALUES (?, ?, ?, ?, ...)

- 排队内容:
{
  "session_id": "abc123",
  "tool_name": "Edit",
  "tool_input": {
    "file_path": "/path/to/file.ts",
    "old_string": "...",
    "new_string": "..."
  },
  "tool_output": {
    "success": true,
    "linesChanged": 5
  },
  "created_at_epoch": 1698765432
}

3.6. 钩子4:停止钩子 – 生成总结

  • 目的: 在会话中生成 AI 驱动的会话摘要
  • 触发点:当 Claude 停止(由停止生命周期事件触发)
  • 它的作用:
    • 从数据库中收集会话观察数据
    • 发送给 Claude Agent SDK 进行摘要/总结
    • 流程响应与摘录结构化摘要
    • 存储在表格 session_summaries
  • 主要代码:src/hooks/summary-hook.ts

3.6.1. 配置

{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js"
      }]
    }]
  }
}

3.6.2. 摘要结构

<summary>
  <request>User's original request</request>
  <investigated>What was examined</investigated>
  <learned>Key discoveries</learned>
  <completed>Work finished</completed>
  <next_steps>Remaining tasks</next_steps>
  <files_read>
    <file>path/to/file1.ts</file>
    <file>path/to/file2.ts</file>
  </files_read>
  <files_modified>
    <file>path/to/file3.ts</file>
  </files_modified>
  <notes>Additional context</notes>
</summary>

3.7. 钩子 5:SessionEnd – 结束会话过程

  • 目的: 会话结束时标记为已完成
  • 触发点: Claude Code 会话结束/清理
  • 它的作用:
    • 在数据库中标记会话已完成
    • 允许 worker 完成加工
    • 清理动作
  • 主要代码:src/hooks/cleanup-hook.ts

3.7.1. 配置

{
  "hooks": {
    "SessionEnd": [{
      "hooks": [{
        "type": "command",
        "command": "${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-hook.js"
      }]
    }]
  }
}

4. Bun worker

Bun 本身也是 Claude Code 极其重要的底层基础设施。Anthropic(Claude 的开发商)甚至已经收购了 Bun 团队,将其作为 Claude Code 的核心引擎。
Claude Code 及其生态之所以大量使用 Bun 来运行各种 worker 或核心任务,主要是因为 Bun 相比传统的 Node.js 拥有巨大的优势:

  • 极速启动与运行:Bun 的底层使用 Zig 语言编写,启动速度极快(比 Node.js 快数倍),非常适合作为需要频繁启停的 CLI 工具或后台 worker。
  • 原生支持 TypeScript:Bun 可以直接执行 .ts 文件,无需像 Node.js 那样经过繁琐的预编译步骤,这让开发和构建流程变得极其简单高效。
  • 高性能的文件与网络操作:Claude Code 需要频繁地读写本地文件以及调用大模型 API。Bun 内置了高性能的 Bun.file() API 和基于 libcurl 的 HTTP 客户端,在处理这些 I/O 密集型任务时性能极其出色。
  • 单一文件分发:Bun 可以将 JavaScript/TypeScript 项目打包成一个自包含的二进制文件,这意味着用户不需要安装任何环境就能直接运行 Claude Code 的相关工具,极大地提升了分发和部署的便利性。

Bun worker 在 Calude-mem 中扮演着后台数据管家的角色:

  • 后台运行:它是一个在后台默默运行的 HTTP 服务(默认通常在端口 37777)。
  • 数据记录与检索:当你使用 Claude Code 写代码时,这个 worker 会在后台自动记录 Claude 的操作(比如文件读写、命令执行),并将其压缩成摘要存入本地的 SQLite 数据库。
  • 上下文注入:下次你开启新会话时,这个 worker 会迅速把相关的历史上下文检索出来并注入到对话中,让 Claude 能够“记住”之前的项目背景。
  • 提供接口:它还提供了一个本地的 Web 界面(如 http://localhost:37777),让你能直观地查看和搜索所有的历史记录。

正是有了 Bun 的高性能加持,这些后台任务才能在不卡顿、不打扰你正常编码的情况下高效运转。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐