Claude Code 记忆插件
为 Claude Code 提供长期语义记忆。每次用户输入前自动召回相关记忆,每轮对话结束后自动捕获上下文——模型不需要主动调用任何 MCP 工具。
源码:examples/claude-code-memory-plugin
快速开始
一行安装(推荐)
bash <(curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/examples/claude-code-memory-plugin/setup-helper/install.sh)脚本支持 macOS 和 Linux。它会检查依赖、询问你接入自托管服务器还是火山引擎 OpenViking Cloud(https://api.vikingdb.cn-beijing.volces.com/openviking)、按需配置 ~/.openviking/ovcli.conf(已存在则复用)、把 OpenViking 仓库 clone 到 ~/.openviking/openviking-repo、把 claude function 包装写入 shell rc,然后通过 claude plugin install 安装插件。每一步都是幂等的——重复执行安全。
如果你更喜欢手动操作,按下面三步走。
手动安装
1. 用 shell function 在调用 claude 时注入 env
这是推荐路径。插件的 hooks 和自带的 MCP 服务器都读 env vars,所以我们把它们设一次——但只在调用 claude 时注入,不全局 export。在 ~/.zshrc 或 ~/.bashrc 末尾追加:
claude() {
if [ -f ~/.openviking/ovcli.conf ]; then
OPENVIKING_URL=$(jq -r '.url' ~/.openviking/ovcli.conf) \
OPENVIKING_API_KEY=$(jq -r '.api_key' ~/.openviking/ovcli.conf) \
command claude "$@"
else
command claude "$@"
fi
}重新 source 后验证(用 bash 的话改成 ~/.bashrc):
source ~/.zshrc # 或:source ~/.bashrc
type claude # 期望输出:claude is a shell function下一次启动 claude 后,进入 /mcp 应该能看到 OpenViking 这一项的 URL 是远程地址,认证也有效。
还没有
ovcli.conf? 先按 部署指南 → CLI 章节 创建一份。纯本地模式(
http://127.0.0.1:1933,无鉴权)?这一步可以跳过——插件会静默使用本地默认值。为什么用 function 而不是
export? 全局 export 的 env vars 会被该 shell 派生的所有子进程继承——npm 脚本、构建工具、崩溃 dump、/proc/<pid>/environ都会带上。函数包装把秘钥限定在claude进程树内。
2. 安装插件
在 OpenViking 仓库根目录执行:
claude plugin marketplace add "$(pwd)/examples"
claude plugin install claude-code-memory-plugin@openviking-plugins-local默认装在 user scope —— 任何目录下都生效。这里不显式传
--scope,因为老的 Claude Code 2.0.x(比如 2.0.76)不识别这个 flag 会直接报错。marketplace 条目让 Claude Code 直接引用源码目录,对
scripts/、hooks/、配置文件的修改下次 hook 触发即生效,无需重装。但移动 / 重命名 / 删除源码目录,或git checkout到不含这些文件的分支,会让插件失效。Claude Code < 2.0?
claude plugin是 2.0(2025-10)才引入的。更老的版本仍然有claude mcp add和 hooks 系统,可以走插件 README 的兼容模式章节手动接同样的功能。一键安装脚本会自动检测版本并询问你是否走这条路径。
3. 启动 Claude Code
claude进入后执行 /mcp,确认 OpenViking 这一项的 URL 是你的远程地址。如果插件似乎没在工作,开 OPENVIKING_DEBUG=1 看 ~/.openviking/logs/cc-hooks.log。
为什么用 function 包装?
插件的 hook 会自动读 ovcli.conf,但自带的 .mcp.json 条目读不到。Claude Code 自己解析 .mcp.json 且只支持 ${VAR} 替换,所以插件无法把配置文件里的值透明地注入 MCP URL 和认证头。
在 claude 调用时注入 env vars 是同时覆盖 hooks 和 MCP 的唯一路径。用 shell function 包装(而不是全局 export)能把 API Key 限定在 claude 一个进程树内,不会泄漏到其他子进程——见 手动安装的步骤 1 的安全说明。
配错的症状:hook(auto-recall、auto-capture)正常工作,因为它们直接通过 Node 读配置文件;但按需 MCP 工具(search、read、store…)会静默连到 http://127.0.0.1:1933、认证头为空,且 /mcp 显示错误的 URL。
配置
解析优先级
每个插件字段按从高到低:
- 环境变量(
OPENVIKING_*) ovcli.conf— 只承载连接字段(url、api_key、account、user、agent_id)ov.conf— 服务端配置;插件读取server.url、server.root_api_key,以及(旧版兼容)claude_code区块(如有)- 内置默认值(
http://127.0.0.1:1933,无鉴权)
⚠️ 仅适用于 hooks。 这条优先级链由
scripts/config.mjs实现,hook 脚本消费。它不适用于 MCP 服务器注册——见 为什么用 function 包装? 一节。
主要环境变量
| 环境变量 | 默认值 | 说明 |
|---|---|---|
OPENVIKING_URL / OPENVIKING_BASE_URL | — | 完整服务器 URL |
OPENVIKING_API_KEY / OPENVIKING_BEARER_TOKEN | — | API Key;通过 Authorization: Bearer <key> 发送 |
OPENVIKING_AUTO_RECALL | true | 每次用户输入前是否自动召回 |
OPENVIKING_RECALL_LIMIT | 6 | 单轮最多注入的记忆条数 |
OPENVIKING_RECALL_TOKEN_BUDGET | 2000 | 内联内容的 token 预算;超出预算的条目降级为 URI 提示 |
OPENVIKING_AUTO_CAPTURE | true | 是否自动捕获;同时控制写入类 hooks |
OPENVIKING_BYPASS_SESSION | false | 一次性开关:1/true 让当前进程跳过所有 hook |
OPENVIKING_BYPASS_SESSION_PATTERNS | "" | CSV 形式的 glob,匹配 session_id 或 cwd |
OPENVIKING_MEMORY_ENABLED | (auto) | 0/false=强制关闭;1/true=强制开启 |
OPENVIKING_DEBUG | false | 把 hook 日志写到 ~/.openviking/logs/cc-hooks.log |
多租户场景下,OPENVIKING_ACCOUNT、OPENVIKING_USER、OPENVIKING_AGENT_ID 用于设置对应的 X-OpenViking-* 请求头。完整环境变量列表(召回/捕获微调、生命周期、调试)见 插件 README。
临时跳过当前 session
在 /tmp 下用 Claude Code 做 PoC,不污染长期记忆:
# 持久化:任何 session_id 或 cwd 命中模式的 session 都跳过
export OPENVIKING_BYPASS_SESSION_PATTERNS='/tmp/**,**/scratch/**,/Users/me/Dev/throwaway/*'
# 或一次性:
OPENVIKING_BYPASS_SESSION=1 claudebypass 启用时,所有 hook 立即返回 approve,不与 OpenViking 通信。
Statusline 状态行
插件会在 Claude Code 输入框下方渲染一行 OpenViking 状态。安装脚本把它注册到 ~/.claude/settings.json(CC 插件 manifest 不支持 statusLine,必须走用户 settings)。
OV ✓ │ ↩ 6 mem (0.92) · 50ms 本轮注入 6 条记忆,最高分 0.92
OV ⚠ slow 探针超过 1s 预算(服务器可能在抽风)
OV ✗ offline 服务器不可达
OV ⚡ bypass 命中 OPENVIKING_BYPASS_SESSION*
OV ✓ │ ✎ 573/20k · 2 arch 待提交进度 + 本 session 已归档 2 次
OV ✓ │ 🔗 resumed │ +3 today session 已恢复上下文;今日累计归档 3 次hook 脚本把每轮的小快照写到 ~/.openviking/state/;statusline 脚本读快照,再加 5 秒共享缓存的 GET /health。探针 1s 硬超时,多 session 共享缓存避免风暴。
OPENVIKING_STATUSLINE=off 可静默不删;jq 'del(.statusLine)' ~/.claude/settings.json 彻底移除。已有自定义 statusline 时安装会询问替换 / 跳过 / 手动 compose。
完整的段位说明(每个 segment 何时出现、为什么有时不显示)以及个性化 recipe(隐藏段位、改色、与已有 statusline 组合、自定义段位),参见 examples/claude-code-memory-plugin/STATUSLINE.md。最方便的方式是打开 Claude Code 把链接喂给它,让它读完文档既能解释你看到的内容,又能按你的偏好调整。
与 Claude Code 内置 MEMORY.md 的对比
本插件补充Claude Code 原生记忆系统,不替代:
| 维度 | 内置 MEMORY.md | OpenViking 插件 |
|---|---|---|
| 存储 | 平铺 markdown | 向量库 + 结构化抽取 |
| 检索 | 整体加载到上下文 | 语义相似度 + 排序 + token 预算 |
| 范围 | 单项目 | 跨项目、跨 session、跨 agent |
| 容量 | ~200 行(受上下文限制) | 无限(服务端存储) |
| 抽取 | 手写规则 | LLM 驱动的实体 / 偏好 / 事件抽取 |
| Subagents | 与父 agent 共享 | 隔离 session + agent 命名空间分类 |
Hook 行为
| Hook | 触发时机 | 行为 |
|---|---|---|
UserPromptSubmit | 每次用户输入 | 搜索 OV → 排序 → 在 token 预算内注入 <openviking-context> 块 |
Stop | Claude 完成一次回复 | 解析 transcript → 把新的用户轮推入 OV session → pending tokens 超阈值时 commit |
SessionStart | 新建 / 恢复 / compact 后的 session | 在 resume/compact 场景,拉取最新归档摘要并注入为额外上下文 |
PreCompact | Claude Code 重写 transcript 之前 | 在 CC 改写前,把待写入消息 commit 成归档 |
SessionEnd | Claude Code session 关闭 | 最终 commit,让最后一个窗口归档 |
SubagentStart | 父 agent 通过 Task 工具派生 subagent | 为 subagent 派生隔离的 OV session ID,持久化启动状态 |
SubagentStop | Subagent 完成 | 读取 subagent transcript → 推入隔离 session(带 subagent 类型的 agent 头)→ commit |
Stop、SessionEnd、SubagentStop 用 detached-worker 模式,用户感知不到 OV 的 RTT。需要确定性顺序时设置 OPENVIKING_WRITE_PATH_ASYNC=false。
auto-capture 在推送到 OV 前会剥离 <openviking-context>、<system-reminder>、<relevant-memories>、[Subagent Context] 等区块——否则插件本轮注入的召回上下文会作为下一轮"用户消息"被回灌进去,形成自污染。
OV session id 派生
OV 端的 session id 直接包含 CC 的 session_id,方便肉眼对账:
- 主 session:
cc-<ccSessionId>,例如cc-7d978bb3-cd9c-4ac6-828d-20965d66b783 - subagent:
cc-<ccSessionId>__agent-<agentId>,例如cc-7d978bb3-cd9c-4ac6-828d-20965d66b783__agent-abc123
可在 ~/.openviking/state/last-capture.json 看到当前 session 的 cc_session_id 和 ov_session_id 对应关系;CC 这边的 session id 也是 ~/.claude/projects/<encoded-cwd>/<session_id>.jsonl 的文件名。
故障排查
| 现象 | 原因 | 修复 |
|---|---|---|
| 插件未激活 | 找不到 ov.conf / ovcli.conf | 跑 一行安装脚本,或者设 OPENVIKING_MEMORY_ENABLED=1 + URL/API_KEY env vars |
| Hook 触发但召回为空 | OpenViking 服务器没起来,或 URL 不对 | curl "$(jq -r '.url' ~/.openviking/ovcli.conf)/health" |
MCP 工具连到 127.0.0.1 而不是远程 | .mcp.json 只支持 ${VAR} 替换,读不到 ovcli.conf | 见 为什么用 function 包装? |
| 远程认证 401 / 403 | API Key 错误,或多租户头缺失 | 检查 OPENVIKING_API_KEY;多租户场景还要核对 OPENVIKING_ACCOUNT / OPENVIKING_USER |
Stop hook 超时 | 服务器慢 + 同步写路径 | 保持 OPENVIKING_WRITE_PATH_ASYNC=true(默认),或在 hooks/hooks.json 提高 Stop 超时 |
参见
- 完整插件 README — 完整环境变量表、hook 超时、调试日志、架构图
- 迁移说明 — 从旧版插件升级
- MCP 集成指南 — MCP 工具参数与其他客户端
- 部署指南 → CLI —
ovcli.conf配置
