Recall:在 VPS 上为 Claude Code 添加会话记忆
Recall 0.4.0 是完全本地的 Claude Code 插件,不调用 API。本文介绍 VPS 安装、Python 要求、钩子写入的两份 Markdown 文件,并实测记忆节省。
Recall 如何实现 Claude Code 记忆
Recall 是一个 Claude Code 插件,可让每个项目在不同会话之间保留记忆。它会在项目中的 .recall/ 文件夹内写入两个 Markdown 文件:一个只追加的事件日志,以及一份简短的上次工作进度摘要。这两个文件都由本机上的 Python 摘要程序生成,因此记忆功能本身不会消耗任何 API token。
它解决的是一个持续存在但范围有限的问题。您在周二结束了 VPS 上的会话。到了周三,Claude Code 完全不知道周二发生了什么。您需要手动重新说明项目,或者让模型再次读取半个代码库来了解情况。两种方式都会消耗 token,后一种消耗的 token 会多得多。
截至 2026 年 7 月,Recall 的当前版本是 0.4.0,项目采用 MIT 许可证。它是一个插件。它不会发起任何网络请求。
VPS 上的要求
Recall 的捕获钩子是随插件发布的 Python 脚本。它们没有第三方依赖,因此唯一的实际要求是 Python 解释器。
python3 -VUbuntu 24.04 的响应是 Python 3.12.3。Recall 支持 Python 3.9 及更高版本。精简容器镜像有时完全不包含解释器,此时 shell 会响应 python3: command not found。继续之前,请先安装解释器。
sudo apt update && sudo apt install -y python3NumPy 是摘要器某个步骤的可选加速组件。您不需要安装它。
python3 -c "import numpy"ModuleNotFoundError: No module named 'numpy' 在这里是可接受的响应。摘要器包含纯 Python 路径,项目的测试套件会检查两条路径是否选择相同的句子。
与笔记本电脑相比,服务器上的会话记忆更重要,因为服务器工作通常以短暂访问的形式分散在数天内。如果您已经在 VPS 的 tmux 中运行 Claude Code,Recall 就是将昨天的会话带入今天会话的组件。
从插件市场安装 Recall
在 Claude Code 会话中输入以下两个命令:
/plugin marketplace add raiyanyahya/recall
/plugin install recall@recall第二个命令会读取 plugin@marketplace。这里两个名称都是 recall,这看起来像是复制粘贴错误,但实际并不是。
运行插件自带的命令之一,检查安装是否成功:
/recall:show/recall:show 会输出当前摘要。对于全新的项目,目前还没有内容可供输出,因此实际检查的是该命令是否存在。如果 Claude Code 无法识别 /recall:show,则表示插件未加载,也不会触发任何 hook。
如果要从检出的代码运行,请先克隆仓库并进行验证:
git clone https://github.com/raiyanyahya/recall ~/recall
cd ~/recall && claude plugin validate .claude plugin validate . 会读取 .claude-plugin/ 中的清单,并报告插件格式是否正确。然后从项目目录启动 Claude Code,并使用 claude --plugin-dir ~/recall。
钩子写入的内容和执行时机
Recall 注册了 3 个 Claude Code 钩子。每个钩子都会从插件目录运行一个 Python 脚本。
SessionStart在启动、恢复和清除时触发。它显示context.md,让会话打开时就能看到摘要。Stop在 Claude 完成每次响应时触发。它会将该轮内容追加到日志。SessionEnd在会话关闭时触发,并可重新生成摘要。
这些钩子会生成 2 个文件,且都位于 .recall/ 中。
history.md是只追加记录:包括提示、响应、涉及的文件和运行的命令。context.md是生成的摘要:包括目标、摘要、后续步骤、涉及的文件、运行的命令和 git 上下文。
完成一次实际会话后,查看该目录。
ls -la .recall/您应能看到其中包含内容的 history.md。您可能完全看不到 context.md,这是默认行为,不是故障。除非设置 auto_save_context,否则 off,因此只有在您请求时才会写入摘要:
/recall:save该命令会对 history.md 运行本地摘要程序,并重写 context.md。算法使用 TF-IDF(词频、逆文档频率)评分,并将结果输入 TextRank 句子排序。该过程具有确定性且采用抽取式方法,也就是说,它会选择日志中已有的句子。该过程不会调用模型,因此免费,并且可在机器离线时运行。
为单个项目配置 Recall
配置位于项目根目录的 recall.config.json 文件中。以下是软件提供的默认配置:
{
"output_dir": ".recall",
"capture_history": true,
"summary_sentences": 8,
"redact": true,
"include_git": true,
"max_input_chars": 200000
}output_dir设置两个文件的存放位置。请将其保留在项目内。capture_history用于启用或禁用history.md日志。auto_save_context接受off或on_end,默认值为off。summary_sentences设置保留到context.md中的句子数量。增大该值会生成更长的摘要,并略微增加会话启动时的负载。redact会在写入磁盘前删除常见的机密信息模式。include_git会将当前差异和最近的提交添加到摘要中。max_input_chars限制摘要程序单次读取的history.md数量。
对于运行在 VPS 上的项目,建议启用自动保存。服务器上的会话通常会因终端断开而结束,而不是在您主动决定停止时结束。
{
"auto_save_context": "on_end",
"summary_sentences": 12
}如果要暂时停止捕获而不修改配置,请创建暂停标记。删除该标记即可重新开始捕获。
touch .recall/.capture-paused在处理生产环境凭据的会话前执行此操作,因为脱敏只是过滤器,并不能提供绝对保证。出于同样的原因,通常也应避免让 AI 代理接触机密信息:最安全的机密信息,是代理从未看到的信息。
Recall 可节省多少 token?
这取决于原来的替代方案。会话开始时加载摘要的成本很低。被它替代的操作可能成本很高,因为不具备项目记忆的模型需要通过读取文件重新了解项目。
The data behind this chart
[
{
"label": "Recall context.md",
"char_count": "4,800",
"est_tokens": "1,200"
},
{
"label": "Hand-written CLAUDE.md",
"char_count": "3,200",
"est_tokens": "800"
},
{
"label": "Re-reading the repo",
"char_count": "120,000",
"est_tokens": "30,000"
},
{
"label": "Full transcript replay",
"char_count": "340,000",
"est_tokens": "85,000"
}
]以下是中型项目的典型数值,不代表对您的项目进行的测量。加载 Recall 摘要大约需要 1,200 个 token,这与项目发布的恢复会话需要 1000 到 2000 个 token 的说法一致。重放完整的先前 transcript 会重新加载整个对话,需要约 85,000 个 token。让模型通过读取文件重新了解项目,成本介于两者之间,约为 30,000 个 token;该数值会随着代码仓库增大而增加。CLAUDE.md 行用于提供尺度参考:它更短且内容固定,因此成本更低,并且用于告知模型您长期适用的规则,而不是告知模型昨晚发生的事情。
请测量您自己的数值。1 个 token 大约对应 4 个英文散文字符,代码对应的字符数通常略少。
wc -c .recall/context.md .recall/history.md
echo $(( $(wc -c < .recall/context.md) / 4 ))在会话中,/context 显示当前已加载到上下文窗口的内容,/cost 报告会话累计值。先启动一个冷会话,再启动下一个已加载摘要的会话,然后进行比较。要全面了解会话 token 的实际消耗位置,请参阅Claude Code 如何消耗 token,其中提供了详细分解。
有一个注意事项可以使这一说法保持准确。摘要会在每次会话开始时加载,因此,如果您从未使用摘要,它带来的只是少量额外开销,而不是节省。除非您的会话运行时间较长,否则请将 summary_sentences 保持在默认值附近。
在无会话的情况下重新生成摘要
如果您克隆了代码仓库,摘要生成器有自己的命令行入口。在 VPS 上,如果会话随终端一同中断,而您仍需要摘要,这一入口很有用。
python3 ~/recall/scripts/make_context.py --help帮助输出会列出它接受的标志:--cwd 用于指定项目根目录,--transcript 用于指定明确的会话记录文件,--quiet 用于禁止输出,--harness 用于在 claude 和 opencode 之间进行选择。将其指向一个项目:
python3 ~/recall/scripts/make_context.py --cwd /srv/projects/api它会读取会话记录并执行 history.md,然后将 context.md 写入您指定的目录。如果您通过 marketplace 安装,插件位于由 Claude Code 管理的目录中;/recall:save 是执行相同操作的受支持方式。
为什么没有写入任何内容
完整会话结束后没有 .recall/ 目录。 钩子从未运行。输入 /recall:show 确认插件已加载,然后运行 python3 -V。钩子命令会先尝试 python3,再尝试 python,因此两者都不存在的主机不会写入任何内容,也不会对此发出提示。
history.md 在增长,但 context.md 从未变化。 默认情况下,auto_save_context 是 off。运行 /recall:save,或将该键设置为 on_end,让 SessionEnd 钩子执行此操作。
文件出现在错误的项目下。 Claude Code 会将文件写入其启动目录的相对路径,因此从主目录启动会话会将记忆文件写在那里。请从项目根目录启动,并使用 ls -la .recall/ 查找文件实际写入的位置。
捕获已停止,但没有任何警告。 使用 ls -a .recall/ 检查暂停标记。您上周创建的 .capture-paused 文件仍在生效。
长会话结束后摘要内容很少。 max_input_chars 会将摘要器输入限制为 200000 个字符,因此过长的日志会被截断。请轮换日志。
mv .recall/history.md .recall/history-2026-07-30.md随后运行一个简短会话,再次检查 ls -la .recall/,确认已生成新的 history.md。
Recall 的适用范围
Recall 由日志和摘要器组成。需要明确它无法覆盖哪些内容。
摘要器采用抽取式摘要。TextRank 会选择已经存在于 history.md 中的句子,因此不会判断某个决策是否正确。周二记录的错误方向,读起来与周三的正确决策完全一样。如果涉及实际风险,请阅读 context.md 并手动修正。它是 markdown 文件,可以直接编辑。
Recall 不提供搜索功能。每个项目只有一份当前摘要和一份持续增长的日志,无法跨项目查询记忆。如果要查找三周前对数据库作出的决定,就需要对 history.md 执行 grep。
Recall 在会话内部不起作用。会话期间上下文窗口耗尽是另一个问题,需要采用不同的解决方法;在单个会话中管理上下文窗口 是本指南的配套文章。
摘要会被有意视为不可信输入。context.md 会以带围栏并标注的形式注入,Claude 在依赖其内容前会先询问。这种设计是必要的,因为已提交的 .recall/ 目录中,任何拥有提交权限的人都可以写入代理将读取的文本。请一次性决定 .recall/ 是个人使用还是共享使用:个人记忆应将其添加到 .gitignore,共享内容则提交它,并像审查其他贡献一样进行审查。如果代理无人值守运行,请参阅在 VPS 上安全运行 Claude Code,了解更广泛的边界。
脱敏只能尽力而为。它会处理 API 密钥、令牌、PEM 块和 .env 赋值等常见模式。提交前请阅读 .recall/。
版本号如实反映了项目的成熟度。2026 年 7 月的版本为 0.4.0,配置键和文件布局在不同版本之间仍可能发生变化,因此升级所依赖的配置前请先阅读更新日志。
FAQ
Recall 会将我的代码或转录内容发送到其他地方吗?
不会。捕获钩子和摘要程序都是在您自己的计算机上运行的 Python 脚本。插件不保存 API key,也不会发起网络请求。摘要使用 TF-IDF 和 TextRank,而不是模型,因此不产生费用,并且可在计算机离线时运行。代价是摘要采用抽取式方式:它从日志中选择句子,而不是生成新句子。
为什么我的 .recall/context.md 缺失或不是最新版本?
auto_save_context 默认为 off,因此只有在运行 /recall:save 时才会重新生成摘要。在 recall.config.json 中将 "auto_save_context": "on_end" 设置为在每个会话结束时重写摘要。如果 history.md 也缺失,则表示钩子根本没有运行:使用 /recall:show 确认插件已加载,然后确认该主机上的 python3 -V 能够返回结果,因为这些钩子是 Python 脚本。
Recall 每个会话可以节省多少?
加载摘要大约需要 1,200 个 token;相比之下,模型需要重新读取代码仓库以确定当前状态时,通常需要 30,000 个 token。这些只是典型数值。请在会话中使用 wc -c .recall/context.md 和 /context 命令进行测量,并比较冷启动与从摘要恢复的会话。
我仍然需要 CLAUDE.md 文件吗?
需要,而且两者用途不同。CLAUDE.md 是您有意编写的内容:固定规则和构建命令。context.md 根据上一个会话中实际发生的情况生成,因此会记录您通常不会主动写下的未完成迁移。请同时保留两者。
一台 VPS 可以为多个项目保存记忆吗?
可以。Recall 将记忆保存在每个项目目录中的 .recall/ 内,因此同一台服务器上的两个项目会保留彼此分离的日志和摘要。每次都从项目根目录启动 Claude Code,因为这些文件跟随工作目录,而不是用户帐户。