MemPalace Hooks 自动保存全指南:为 Claude Code / Cursor 等编码 Agent 配置"永久记忆"
【免费下载链接】mempalaceThe best-benchmarked open-source AI memory system. And it's free.项目地址: https://gitcode.com/GitHub_Trending/me/mempalace
MemPalace Hooks 是 MemPalace 面向终端 AI 编码工具(Claude Code、Cursor、Codex CLI、Google Antigravity)提供的"自动保存"能力:无需手工执行任何保存命令,AI 在对话过程中就会把新事实、决策、代码与工具输出持续写入宫殿(palace)。本文将基于仓库内 examples/HOOKS_TUTORIAL.md 与 hooks/README.md 的文档骨架,结合真实 hook 脚本源码,完整讲解 hook 的安装接线、触发机制、配置参数、历史会话回填、多平台扩展与调试方法。读完你既能三分钟给 Claude Code 装上自动记忆,也能深入理解其防死循环、双层捕获与静默模式背后的实现原理。
一、Hook 家族总览:它们到底在什么时机做什么
MemPalace 目前提供三支"扁平安装"于仓库hooks/目录下的通用 hook 脚本,各自对应一个生命周期事件:
| Hook 脚本 | 触发时机 | 行为 |
|---|---|---|
| mempal_save_hook.sh(Save Hook) | 每 15 条人类消息(SAVE_INTERVAL)后的 Stop 事件 | 自动挖掘对话 JSONL 转写稿(含工具输出),并按配置决定是否短暂"阻断"AI,提示其把主题 / 决策 / 引语写入结构化记忆 |
| mempal_precompact_hook.sh(PreCompact Hook) | 上下文窗口即将被压缩(compaction)之前 | 同步挖掘转写稿做一次"最终保存",兜底保住压缩前的一切细节 |
| mempal_session_end_hook.sh(SessionEnd Hook) | 会话正常退出 | 后台化执行一次最终挖掘,避免短会话被遗漏,立即返回、绝不拖慢退出 |
正如 hooks/README.md 开头所说:Save Hook 是定时器,PreCompact Hook 是安全网。Save Hook 依赖消息计数阈值,可能几次消息都没触发;而 PreCompact 发生在 AI 即将丢失详细上下文之前,无论是否到点都必须保存。二者的区别在源码里体现得淋漓尽致——PreCompact 钩子对转写稿执行的是**同步(前台阻塞)**挖掘(见 mempal_precompact_hook.sh),因为压缩不可逆,一旦 Cursor / Claude Code 摘要了对话,逐字的原文就再也取不回来了;而 Save Hook 的挖掘是在后台&执行的(见 mempal_save_hook.sh),绝不阻塞 AI 的正常停步。
版本说明:本教程针对v3.1.0+的 hook 行为撰写。更早版本只依赖"AI 在聊天窗口里写日记",而 v3.1.0+ 引入了下文要讲的双层捕获机制。
二、Claude Code 安装接线(全局 / 项目级)
MemPalace 的 Claude Code hook 通过 Claude Code 的settings.local.json挂载。可以放在全局~/.claude/settings.local.json,也可以放在项目级.claude/settings.local.json。把完整 JSON 写入其中之一:
{ "hooks": { "Stop": [ { "matcher": "*", "hooks": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_save_hook.sh", "timeout": 30 }] } ], "SessionEnd": [ { "hooks": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_session_end_hook.sh", "timeout": 10 }] } ], "PreCompact": [ { "hooks": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_precompact_hook.sh", "timeout": 30 }] } ] } }随后为脚本添加执行权限:
chmod +x hooks/mempal_save_hook.sh hooks/mempal_session_end_hook.sh hooks/mempal_precompact_hook.sh注意:把/absolute/path/to/hooks/替换成你实际克隆 MemPalace 仓库的目录(例如~/projects/mempalace/hooks/)。脚本自身能从所在路径解析仓库根目录,因此仓库装在哪里都能工作,但command字段必须是绝对路径。
三个字段值得说明:
Stop与PreCompact的timeout取30,因为挖掘(mine)可能需要一点时间;SessionEnd取10即可——它把重活丢给后台进程后立即返回,见 mempal_session_end_hook.sh。matcher: "*"表示对所有消息生效。- 若只想要"最小可用"版本,仅保留
Stop一节即可(对应下文 Cursor 的 hooks.minimal.json 思路)。
必须重启会话。Claude Code 只在会话启动时加载
settings.json中的 hooks。安装或改动 hook 配置后,请完全重启 Claude Code 再验证,否则不会触发(这是 Claude Code 的固有限制,见 hooks/README.md 的 Known Limitations)。
三、Hook 工作原理:源码级剖析
3.1 Hook 协议:stdin JSON 是唯一的输入
Claude Code 在触发 hook 时会把一个 JSON 对象写入脚本的 stdin,关键字段包括:
session_id—— 会话唯一标识;stop_hook_active—— 是否已处于"保存循环"中(防死循环的关键标志);transcript_path—— 本次会话的 JSONL 转写稿路径。
脚本读取 stdin 后,把解析、清洗与计数工作委托给 Python,而不是在 shell 里裸写正则。这个分工沉淀在 mempalace/hook_shell.py 中,命令有三种:
| 子命令 | 职责 | 实现位置 |
|---|---|---|
parse-stop | 解析并清洗 Stop 载荷,输出session_id/stop_hook_active/transcript_path | hook_shell.py |
parse-precompact | 同上,面向 PreCompact 载荷 | hook_shell.py |
count-human-messages | 数 JSONL 中人类消息条数 | hook_shell.py |
以人类消息计数为例(hook_shell.py):它逐行解析 JSONL,统计message.role == "user"的条目;特别地,把内含<command-message>的内容排除在外,避免把命令类消息也算成"人类对话"。它对"路径存在但不是普通文件"的情况直接返回 0——因为打开 FIFO 读取会阻塞在内核上且没有超时。这也是脚本先[ -f "$TRANSCRIPT_PATH" ]判定的原因。
值得一提的安全细节:脚本通过"哨兵 +sed -n 'Np'逐行取值"的方式从 Python 输出还原变量,全程不eval生成代码;session_id会被清洗到[a-zA-Z0-9_-]字符集、transcript_path会被去除控制字符并把\规整为/(兼容 Windows 路径)。若解析失败且输入非空,脚本会把不超过 4 KB 的原始载荷写入last_input.log并以chmod 600锁定权限——fail-loud 契约由 tests/test_hooks_bash_compat.py 钉死。之所以用sed -n 'Np'而非mapfile/readarray,是因为 macOS 自带的 bash 3.2.57(Apple 在 2006 年 GPLv3 冻结时封存的版本)没有数组读取内建命令——见脚本内注释引用的回归记录。
3.2 Save Hook:计数 → 触发 → 后台挖掘 → 阻断(可选)
mempal_save_hook.sh 的执行主流程可以归纳为一张图:
用户发消息 → AI 回复 → Claude Code 触发 Stop hook ↓ 脚本用 Python 数 JSONL 里的人类消息数 ↓ ┌── 距上次保存 < SAVE_INTERVAL ──→ echo "{}"(放行,AI 正常停止) │ └── 距上次保存 ≥ SAVE_INTERVAL ↓ 后台自动挖掘转写稿 → 宫殿(原始工具输出被捕获) ↓ MEMPAL_VERBOSE=true → {"decision":"block","reason":"..."} (默认静默) → echo "{}"(纯后台保存,不打扰聊天) ↓ AI 尝试再次停止 ↓ stop_hook_active = true → 脚本放行(防死循环)几个关键实现点:
- 触发判定(mempal_save_hook.sh):
EXCHANGE_COUNT(本次人类消息数)减去LAST_SAVE(记录在~/.mempalace/hook_state/<session_id>_last_save的计数)≥SAVE_INTERVAL才触发。状态文件按 session 隔离,所以会话各自独立计时。 - 防死循环(mempal_save_hook.sh):一旦
stop_hook_active为真(说明 AI 正在执行上一轮"请保存"的指令),脚本直接echo "{}"放行。协议上是"block 一次 → AI 保存 → 再次尝试停止 → 放行",天然不成环。 - 双层捕获的第 1 层(Auto-mine)(mempal_save_hook.sh):触发保存时,hook 对转写稿所在目录执行
mempalace mine <transcript-dir> --mode convos(后台运行)。这一步把Bash 结果、搜索结果、构建报错等原始工具输出直接 upsert 进宫殿——这些正是 AI 在摘要时通常会"总结掉"的细节。 - 双层捕获的第 2 层(阻断提示)(mempal_save_hook.sh):当
MEMPAL_VERBOSE=true时,hook 返回decision: "block",并把 reason 作为系统消息喂给 AI:
MemPalace save checkpoint. Write a brief session diary entry covering key topics, decisions, and code changes since the last save. Use verbatim quotes where possible. Continue after saving.注意 reason 的措辞是"verbatim quotes"(逐字引语)——与 v3.1.0 之前的"只记主题和决策"不同,它显式要求 AI 原样保存工具输出。两条路径互为保险:即使 AI 偷懒只做摘要不引原文,Auto-mine 那层也已经把逐字工具输出落库了(hooks/README.md 称之为 "belt and suspenders")。
3.3 PreCompact Hook:同步最终保存
与 Save Hook 不同,mempal_precompact_hook.sh不计数、不阻断:
- 解析出
session_id与transcript_path; - 同步执行
mempalace mine <transcript-dir> --mode convos(必要时再加MEMPAL_DIR --mode projects),必须等挖掘完成、记忆落库后才返回; - 打印
{},让压缩正常进行。
正如脚本头注释所强调的:压缩是破坏性的——它把 AI 的详细上下文摘要掉之后,逐字信息就丢了。因此"压缩前必保存"这一保证由同步挖掘承载,而不是 Stop 钩子的 block 协议(PreCompact 场景下decision: "block"会把"保存"伪装成一次普通续写,语义并不合适,且 Claude Code 对 PreCompact 的协议约束与此不同)。同样的工程决策也体现在 Cursor 版 preCompact 的注释里:宁可让大转写稿的同步挖掘超过 hook 超时被 Cursor 杀掉,也不截断挖掘——因为mempalace mine是增量、仅追加的,中断只会让下次挖掘续上,不会损坏宫殿。
3.4 SessionEnd Hook:干净退出的收尾
当一次 Claude Code 会话正常退出时,若会话很短、还没走到 Save Hook 的 15 条阈值,这段对话可能整个丢失。SessionEnd Hook 解决这个问题:它捕获 stdin 的 JSON 载荷后,把真正的逻辑丢进detached 子进程执行:
printf '%s' "$payload" | run_mempalace_hook --hook session-end --harness claude-coderun_mempalace_hook依次尝试mempalace命令、MEMBAL_PYTHON -m mempalace、python -m mempalace(见 mempal_session_end_hook.sh)。之所以必须后台化,是因为 Claude Code 文档给的 SessionEnd 默认超时只有 1.5 秒,而一次冷启动mempalace本身就可能超过这个预算;脚本立即返回{},让退出流程永远不被拖延。其业务逻辑全部收敛在 mempalace/hooks_cli.py 的hook_session_end,便于跨 harness 复用。
四、配置参数全解
Hooks 的全部行为由脚本头部变量与环境变量控制。核心参数如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
SAVE_INTERVAL | 15 | 每 N 条人类消息保存一次。调小 = 更频繁保存、更多打断;调大 = 更少打断 |
STATE_DIR | ~/.mempalace/hook_state/ | hook 状态目录:会话计数、.pending标记、hook.log日志、诊断转储都在这里 |
MEMPAL_DIR | 空 | 可选的项目目录(代码 / 笔记 / 文档),每次保存触发时额外以--mode projects挖掘。纯增量——对话转写稿无论如何都会以--mode convos挖掘,此选项绝不取代它 |
MEMPAL_PYTHON | 自动探测 | 指定 hook 内部 Python 调用的解释器,见下文解析顺序 |
MEMPAL_VERBOSE | 关闭 | true/1时 Save Hook 阻断 AI 并展示日记提示(开发模式);默认静默后台保存 |
MEMPALACE_HOOKS_AUTO_SAVE | 开启 | false/0/no时全局停用自动保存阻断(kill switch) |
hooks.auto_save(config.json) | true | 与上一条等效的文件式开关,见 4.2 节 |
参数命名勘误:文档写的是
MEMPALACE_PYTHON,但脚本源码实际读取的是MEMPAL_PYTHON(见 mempal_save_hook.sh 与 mempal_precompact_hook.sh),Cursor 版本亦然(lib/common.sh)。以源码为准,设置MEMPAL_PYTHON才生效。
4.1 Python 解释器解析顺序
为何解析解释器如此重要?GUI 启动的 Claude Code(macOS 下经open -a、Spotlight 或 Dock 启动)继承的是launchd的最小 PATH(/usr/bin:/bin:/usr/sbin:/sbin),往往找不到你装了 mempalace 的那个python3(比如你在 venv 或 pyenv 里)。解析顺序(首个命中即胜出):
$MEMPAL_PYTHON—— 显式覆盖(绝对路径,且必须可执行);$(command -v python3)—— PATH 上第一个python3;- 裸
python3—— 最后兜底。
注意:hook 内部用于解析 JSON / 计数的解释器只需要标准库json和sys,不要求装 mempalace;真正执行挖掘的是mempalace mine这条 CLI,因此mempalace本身也需要位于 hook 环境的 PATH 上。建议用pipx install mempalace或uv tool install mempalace把它装到稳定的全局位置,否则要手动把 venv 的bin/加进 hook 环境 PATH。
4.2 如何彻底停用自动保存(静默模式)
想让 hook 保持安装但不打扰会话?两种方式二选一:
方式一:配置文件(~/.mempalace/config.json):
{ "hooks": { "auto_save": false } }方式二:环境变量:
export MEMPALACE_HOOKS_AUTO_SAVE=false停用后,Save Hook 与 PreCompact Hook 都会直接echo "{}"放行、不再阻断;手动保存依然可用:mempalace mine <dir> --mode convos。
五、一次性回填历史会话(Backfill)
Hooks 只对未来的对话生效——你过去几个月堆积的会话记录不会自动进入宫殿。请对历史会话执行一次回填:
mempalace mine ~/.claude/projects/ --mode convos这条命令会扫描~/.claude/projects/下所有历史会话的 JSONL 转写稿,把它们归入conversationswing。按文档估计,典型开发者机器上数月的会话历史可产出数万条抽屉记录(drawers)。Codex CLI 用户对应执行:
mempalace mine ~/.codex/sessions/ --mode convos回填只需一次,此后 Save / PreCompact / SessionEnd 三支 hook 会随会话自动挖掘。
六、把 Auto-Save 扩展到其他编码工具
6.1 Cursor(IDE 专用 hook 集)
Cursor 的 hook 生态与 Claude Code 不同,仓库在 hooks/cursor/ 下维护了一整套专用脚本,并共享 hooks/cursor/lib/common.sh(提供状态目录、Python 解析、kill switch、wing 推断等公共逻辑)。推荐用安装器一键接线:
bash hooks/cursor/install.sh它会把脚本复制到~/.mempalace/hooks/cursor/并合并写入你的~/.cursor/hooks.json。完整接线示意见 examples/cursor/hooks.json:
{ "version": 1, "hooks": { "sessionStart": [ { "command": "$HOME/.mempalace/hooks/cursor/mempal_wake_hook_cursor.sh" } ], "stop": [ { "command": "$HOME/.mempalace/hooks/cursor/mempal_save_hook_cursor.sh", "loop_limit": 1 } ], "preCompact": [ { "command": "$HOME/.mempalace/hooks/cursor/mempal_precompact_hook_cursor.sh" } ] } }Cursor 集成有三点与 Claude Code 显著不同,均可在源码中找到依据:
sessionStart→ Wake Hook:Cursor 独有的"会话开始即召回"能力。Claude Code 的第三方 hooks 兼容层没有等价事件。mempal_wake_hook_cursor.sh 在会话启动时从workspace_roots[0]推断 wing(basename(workspace)归一化为[a-z0-9_-]),返回additional_context,让 AI 在回答任何涉及既往工作的问题前先mempalace_search+mempalace_diary_read(MCP 工具名与 mempalace/mcp_server.py 中实现一一核对)。followup_message默认开启:Cursor 的转写格式未公开,normalize.py没有 Cursor parser,因此后台挖掘只是best-effort,无法产出干净的逐字 drawers。真正承担"逐字捕获"的是默认开启的followup_message(引导 Agent 用mempalace_checkpoint一次调用完成去重归档 + 写日记)。这与 Claude Code hook 默认静默的策略相反——理由见 mempal_save_hook_cursor.sh 头注释:Cursor 默认关掉 followup 就等于默认零捕获。loop_limit: 1与.pending标记:Cursor 的防循环信号是loop_count(等价于 Claude 的stop_hook_active),loop_limit: 1是纵深防御。而 preCompact 在 Cursor 里是只读观察型事件(仅支持user_message输出,不能阻断压缩),所以 preCompact hook 只能做同步挖掘 + 丢一个.pending标记文件,由下一次 stop hook 消费标记、强制触发一次保存提示(见 hooks/cursor/lib/common.sh)。
想回到 Claude 式"聊天窗口零打扰",可用MEMPAL_CURSOR_SILENT=1或MEMPAL_VERBOSE=false关闭 followup。Cursor 的完整配置手册见 hooks/cursor/README.md 与渲染版 website/guide/cursor-hooks.md。
6.2 Codex CLI(OpenAI)
把同一套通用脚本挂到.codex/hooks.json:
{ "Stop": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_save_hook.sh", "timeout": 30 }], "PreCompact": [{ "type": "command", "command": "/absolute/path/to/hooks/mempal_precompact_hook.sh", "timeout": 30 }] }6.3 Google Antigravity
Antigravity 的接线格式(camelCase JSON、injectSteps[]输出)与事件名(Stop、PreInvocation)都是专用方言,集成代码独立维护在 hooks/antigravity/ 子目录。使用专用安装器:
bash hooks/antigravity/install.sh该安装器把内容装到~/.gemini/config/plugins/mempalace/,注册 MCP 服务器、附带mempalaceskill,并接线 Stop + PreInvocation hooks。完整指南见 hooks/antigravity/README.md,对所用 Antigravity 各表面能力的审计见 hooks/antigravity/INVESTIGATION.md。由于 Antigravity 不暴露专用的会话结束事件(其生命周期钩子为 PreToolUse/PostToolUse/PreInvocation/PostInvocation/Stop,且 MemPalace 已通过 Stop 保存),该 harness 暂无 session-end 接线——clean-exit 保存统一走 harness 无关的mempalace hook run --hook session-end入口(hooks/README.md "Other harnesses" 一节)。
七、调试与故障排查
7.1 看日志
Save / PreCompact 每次触发都会追加一行到状态目录:
cat ~/.mempalace/hook_state/hook.log典型输出:
[14:30:15] Session abc123: 12 exchanges, 12 since last save [14:35:22] Session abc123: 15 exchanges, 15 since last save [14:35:22] TRIGGERING SAVE at exchange 15 [14:40:01] Session abc123: 18 exchanges, 3 since last saveCursor 系列则写到~/.mempalace/hook_state/cursor_hook.log,行格式为 ISO8601 时间戳 +event=+conv=,便于跨时区 grep。
7.2 常见故障定位
| 现象 | 排查方向 |
|---|---|
| hook 从不触发 | 是否改了配置后没重启会话?Claude Code 只在会话启动时加载 hooks |
Session unknown刷屏 | 查看~/.mempalace/hook_state/last_input.log与last_python_err.log(解析失败时,脚本会 dump 至多 4 KB 原始载荷并chmod 600) |
| GUI 启动下无法计数 | macOS GUI 启动路径不含你的 shell PATH → 显式export MEMPAL_PYTHON="/usr/bin/python3"(或你的 venv) |
| 后台挖掘静默失败 | mempalace mine需在 PATH 上;用pipx/uv tool安装到全局,或把 venvbin/加入 hook PATH |
| 状态目录无限膨胀 | Cursor 钩子带每日节流、默认 30 天 TTL 的 GC(cursor_last_sweep标记 +find -mtime),可通过MEMPAL_STATE_TTL_DAYS调整 |
7.3 成本与打扰
按文档口径,v3.1.0+ 的设计目标是零额外 token:Auto-mine 层在后台直接把原始工具输出落库,AI 不必在聊天里誊写内容;MEMPAL_VERBOSE=true的阻断式提示是可选的开发模式。早期版本让 AI 在聊天窗口写日记与抽屉内容,每个会话约额外耗费约 $1 的重传 token——这正是新架构把它变成默认静默的原因(hooks/README.md "Cost" 一节)。
八、小结
从本教程出发,你可以按图索骥完成三层落地:
- 接线:把 mempal_save_hook.sh 挂到
Stop、mempal_precompact_hook.sh 挂到PreCompact、mempal_session_end_hook.sh 挂到SessionEnd,重启会话生效; - 调参:用
SAVE_INTERVAL控制保存节奏,用MEMPAL_DIR顺带挖掘项目文件,用MEMPAL_PYTHON修正解释器解析,用MEMPALACE_HOOKS_AUTO_SAVE=false随时静默; - 回填与扩展:一次性执行 mempalace-mine 回填历史会话,再按需把同一套能力铺到 Cursor、Codex、Antigravity。
想进一步深挖,推荐继续阅读同仓库的 hooks/README.md(含流程图与技术细节)、website/guide/claude-code-retention.md(现网会话保护的快速检查清单)、hooks/cursor/README.md(Cursor 完整手册),以及核心实现 mempalace/hook_shell.py 与配套测试 tests/test_hooks_bash_compat.py、tests/test_save_hook_mines.py、tests/test_save_hook_verbose.py。多读几遍脚本里那些"为什么这样做"的长注释——它们本身就是一份非常诚实的工程笔记。
【免费下载链接】mempalaceThe best-benchmarked open-source AI memory system. And it's free.项目地址: https://gitcode.com/GitHub_Trending/me/mempalace
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考