关于 ov-memory-doctor
OpenViking Memory Doctor 是面向 Claude Code 中 OpenViking memory 插件用户的排障技能。它检查安装、配置、连接和本地服务器状态,并将发现对应到修复步骤。
主要功能
- 01检查插件注册与钩子
- 02解析配置来源和覆盖项
- 03探测服务器连接与就绪状态
- 04报告近期活动与故障
- 05提供检查结果及修复步骤
适用场景
- 01排查未运行的钩子
- 02查找格式错误或被覆盖的设置
- 03调查认证与连接错误
- 04检查本地 OpenViking 服务器就绪状态
MCP 相关
它会检查插件的 stdio MCP 代理,并提供验证 Claude Code 的 MCP 连接和 `/mcp` 端点的步骤。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ volcengine/ openviking --skill ov-memory-doctor安装后在 Claude Code 中输入/ov-memory-doctor确认已加载。
附带文件reference.md
详细介绍
OpenViking Memory Doctor
用于排查 OpenViking 记忆插件问题的客户端工具。该插件由三个部分组成,每个部分出错时都有各自的静默失败方式:
- 安装 — 市场注册、插件启用、九个钩子、stdio MCP 代理。这些设置出错时,钩子永远不会运行,也不会有任何日志。
- 配置 —
~/.openviking/ovcli.conf、~/.openviking/ov.conf和OPENVIKING_*环境变量,按 env → ovcli.conf → ov.conf → 默认值的顺序解析。格式错误的文件会被视为“无配置”,从而静默禁用插件;多余的环境变量则会静默覆盖文件中的配置。 - 连接 — 在可自托管的服务端,即使密钥无效,
/health也会返回 200,因此状态栏可能显示绿色,而每个实际请求都返回 401。在 OpenViking Cloud 上,网关也会对/health和/ready进行身份验证,因此同样的探测在没有密钥时会返回 401,无法说明 url 是否正确。
当解析出的 url 是环回地址时,服务端会在本机运行,doctor 会添加一个 服务端健康状况 部分:端口上是否有进程在监听、ov.conf 中会导致服务端拒绝启动的仅插件专用密钥(顶层块名称可以是任意一种宿主,例如:claude_code、codex、cursor、trae、trae_cn、zcode、opencode、dsh、pi,以及 server.url),以及 GET /ready——服务端对各子系统(agfs、vectordb、api keys、embedding、ollama)给出的判定。远程服务只会探测 /ready。服务端的其他所有检查——配置验证、实时 embedding 探测、原生引擎、磁盘——都由 openviking-server doctor 完成,并在服务端的 Python 环境中运行。
步骤 1 — 运行 doctor
node ${CLAUDE_PLUGIN_ROOT}/scripts/ov-memory-doctor.mjs
选项:--json(机器可读)、--offline(跳过网络探测)、--timeout <ms>(每项探测的超时时间,默认 5000)、--no-color。
报告包含六个部分——环境、插件安装、配置、连接、服务端健康状况、近期活动——以及列出每项 ✗/⚠ 并附有修复方法的摘要。
采取行动前,请阅读完整报告:同一个根本原因通常会出现在多个部分中(例如密钥错误会导致“api key rejected” + “system/status → 401” + turns_failed > 0)。
如果报告显示“此脚本并非从已注册的安装路径运行”,请从报告打印的路径重新运行——Claude Code 会从该副本执行钩子。
API 密钥不会完整显示。三段式密钥会显示为 account=<a> user=<u> secret=abcd…wxyz(前两段只是 base64url 格式的身份信息,解码后可以查看密钥所指向的账户/用户)。其他格式会显示为 abcd…wxyz (N chars, unsupported format)。向用户展示内容时,请始终遵循这一规则。
步骤 2 — 将发现的问题对应到原因
从上到下处理;先修复第一个 ✗,然后重新运行,再排查下一个。
| Doctor 检查结果 | 含义 | 操作 |
|---|---|---|
plugin disabled — every hook exits immediately | 没有可解析的配置、OPENVIKING_MEMORY_ENABLED=0,或 ov.conf 中 claude_code.enabled: false | 修复其指出的原因。全新机器:创建 ~/.openviking/ovcli.conf,包含 url + api_key(chmod 600)。 |
ovcli.conf cannot be parsed | 结尾多了逗号/注释;插件将该文件视为不存在 | 修复 JSON。这是最常见的“已安装但毫无反应”。 |
not registered in installed_plugins.json / claude plugin list does not show … | 插件从未安装,或以旧 id 安装 | 重新运行一行安装命令(curl -fsSL https://openviking.ai/install | bash -s -- --harness claude)。 |
plugin is disabled in ~/.claude/settings.json | 已安装,但 enabledPlugins 为 false/缺失 | claude plugin enable openviking-memory@openviking,重启 Claude Code。 |
marketplace 'openviking' … missing directory / registered as a file | checkout/归档文件被移动,或是文件类型的 marketplace(marketplace update 会以 EISDIR 失败) | claude plugin marketplace remove openviking,然后重新运行安装命令。 |
no skills/ directory in this plugin copy / registered version behind the repo | 版本键控的缓存已过期;当版本字符串未变化时,claude plugin update 是空操作 | claude plugin marketplace update openviking && claude plugin uninstall openviking-memory@openviking && claude plugin install openviking-memory@openviking。 |
legacy openviking hooks … settings.json / extra plugin ids / user-scope MCP openviking | 2.0 之前的安装残留;每个 hook 触发两次,MCP 服务注册两次 | 从 ~/.claude/settings.json 的 .hooks 中移除 openviking 条目(先备份),claude plugin uninstall <stale id>,claude mcp remove openviking -s user。 |
node is not on PATH / node < 18 | Hook 和 .mcp.json 运行裸命令 node;GUI/IDE 启动时常常缺少 nvm/volta shim | 将 node 放入启动环境的 PATH,或在 ~/.claude/settings.json 的 env 块中设置 PATH。 |
server unreachable(refused / dns / timeout / tls) | url/端口错误、服务未运行、DNS/VPN、私有 CA | 用 curl -sS <url>/health 对比。curl 正常但 doctor 失败 ⇒ 代理或 CA 问题(见 Step 3)。 |
base URL ends with /api/v1 或 /mcp、无 scheme、GET /health → 404 | url 形式错误(路径是直接拼接的);Cloud 需要 /openviking 前缀 | 将 url 修正为 API 根地址。 |
/health is authenticated at this deployment(info)/ api key rejected on /health → 401 | OpenViking Cloud 在网关处对 /health 和 /ready 做鉴权,因此不带 key 的探测会返回 401,且无法反映 url 是否正常 | 该 info 行无需修复——报告改为带 key 读取 /health。✗ 表示网关拒绝了此 key:请使用为该部署签发的 key(Cloud key 来自火山引擎控制台)。 |
api key rejected(/health 返回 200 但无身份)然后是 system/status → 401 Invalid API Key | Key 无效/已吊销/属于其他部署。用于不存在账号的 3 段式 key 看起来完全相同。 | 重新签发 key;检查没有环境变量覆盖 ovcli.conf(Configuration 一节中的“← env”)。 |
using the ROOT api key / 403 ROOT API keys cannot access tenant-scoped data APIs | api_key 回退到了 ov.conf server.root_api_key,或用户粘贴了 root key | 创建用户 key(用 root key 调用 POST /api/v1/admin/accounts/<account>/users)并放入 ovcli.conf。 |
server is in trusted mode and needs account + user / 400 Trusted mode requests must include… | 服务身份来自 header | 在 ovcli.conf 中设置 account 和 user。 |
configured account/user differ from the key's identity | 在 api_key 模式下,服务会忽略 X-OpenViking-Account/User;数据会落在 key 的身份下 | 移除它们,或使用该身份对应的 key。这解释了“我改了 account 但什么都没变”。 |
request/capture timeout exceeds the hook budget | Claude Code 在请求完成前就杀掉了 hook | 调低 OPENVIKING_TIMEOUT_MS / OPENVIKING_CAPTURE_TIMEOUT_MS。 |
POST /mcp tools/list → 404/406/502/504,但 /health 正常 | 反向代理未转发 /mcp、重写了 Accept,或缓冲了 SSE | 修复代理(proxy_buffering off、转发 /mcp、传递 Authorization)。 |
proxy variables set + curl 正常但 doctor/hook 失败 | Node 的 fetch 忽略 HTTP(S)_PROXY;插件未内置代理/CA 处理 | 在启动 Claude Code 的环境中设置 NODE_USE_ENV_PROXY=1 或 NODE_EXTRA_CA_CERTS=<ca.pem>(~/.claude/settings.json 的 env 块)。 |
last auto-recall … reason=offline/bypass/disabled/short_query | Hook 运行了,但选择不注入 | offline → 连接问题;bypass → OPENVIKING_BYPASS_SESSION*;short_query → 提示词短于 minQueryLength;只有 no_results/filtered_out 才表示搜索真正执行了。注意,搜索调用返回 401 也会显示为 no_results。 |
turns_failed > 0 / capture payload(s) waiting | 写入被拒绝(401/403/404 会被丢弃而非排队),或服务当时不可用(已排队,下次 SessionStart 时重放) | 修复凭据/连接;OPENVIKING_WRITE_PATH_ASYNC=0 会让错误显示在 stderr 上。 |
MCP proxy last started against <other url> | 代理是长驻进程;更改 url 只有在重启后才生效 | 重启 Claude Code 或 /mcp → reconnect。如果磁盘上的 ovcli.conf 已更改,key 轮换会在 401 后自愈。 |
recall is pinned to the legacy /search/recall endpoint | 任何提到“mode”的 4xx 会将 recall 固定 6 小时 | rm ~/.openviking/state/context-face.json。 |
no hook log … debug is on but no hook has run | Hook 根本没有被启动 | 注册/启用/node 问题,不是服务问题。 |
ov.conf has a top-level '<harness>' block / server.url is rejected | 服务器的自有配置中出现了仅属于插件的键——任何以 harness 命名的顶层块(claude_code、codex、cursor、trae、trae_cn、zcode、opencode、dsh、pi)加上 server.url;服务在下次重启时会拒绝启动(Unknown config field / Extra inputs are not permitted) | 将它们移到 ovcli.conf(plugin.<harness>、url),并从 ov.conf 中删除。仅当此 ov.conf 从不启动服务时才可以忽略。 |
nothing listens on port … — the server is not running | 服务未运行或从未启动;.openviking.lock 是否存在并不表示服务是否在运行 | 在终端中启动它(openviking-server;首次为 openviking-server init)并查看启动输出。重启用户自己运行的服务前先询问。 |
/ready: embedding → error … | 正在运行的服务无法调用其 embedding 提供方:recall 搜索不到任何内容,commit 提取不到任何内容 | 修复 ov.conf 中的 embedding.*(api_key/api_base/model)并重启;openviking-server doctor 会打印提供方的回复。 |
/ready: vectordb → … / /ready: agfs → … | 存储损坏:磁盘满、同一 workspace 上运行两个服务、索引损坏 | 查看服务日志;停止重复的服务;释放磁盘。 |
server is still initializing (503 /ready) | 首次启动会下载本地 embedding 模型,或初始化较慢 | 等待并重新运行;如果始终无法完成,查看服务日志。 |
docker container is up but has no ov.conf | 官方镜像启动时未挂载配置(每个请求都返回 503) | 将 ~/.openviking 挂载到 /app/.openviking,或执行 docker exec -it openviking openviking-server init。 |
| 更多症状、准确的错误字符串和日志阶段名称:reference.md。 |
第 3 步 — 针对性检查(仅在报告尚无定论时)
证明钩子确实在运行。OPENVIKING_DEBUG=1 必须到达 Claude Code 自身的进程 — shell 导出做不到,而 ~/.claude/settings.json 中的 env 块可以。然后在新会话中发送一条提示词,并读取 ~/.openviking/logs/cc-hooks.log(JSONL;grep "error" 和 "hook":"mcp-proxy","stage":"start")。subagent-stop transcript_read ENOENT 这一行是无害的噪音。
手动验证密钥和身份(Bearer 区分大小写,且中间恰好有一个空格):
URL=<url>; KEY=<key>
curl -sS "$URL/health" # reachability, version, auth_mode (401 on Cloud: the gateway gates /health)
curl -sS -H "Authorization: Bearer $KEY" "$URL/health" # 200 without account_id/user_id/role ⇒ key invalid
curl -sS -w '\n%{http_code}\n' -H "Authorization: Bearer $KEY" "$URL/api/v1/system/status" # real 401/403
直接验证 /mcp(无状态 — 无需 initialize):
curl -sS -o /dev/null -w '%{http_code}\n' -X POST "$URL/mcp" \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-H "Authorization: Bearer $KEY" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
验证 Claude Code 的 MCP 接线:claude mcp list(较慢,30–60s)必须显示 plugin:openviking-memory:openviking: node <installPath>/servers/mcp-proxy.mjs - ✔ Connected;claude mcp get 'plugin:openviking-memory:openviking' 需要完整的带引号名称。会话内的 /mcp 会重新连接代理。
证明一次捕获已落地:从 ~/.openviking/state/last-capture.json 中取出 ov_session_id,然后 GET $URL/api/v1/sessions/<id>(或 ov session get <id>);total_message_count 应 ≥ 捕获的轮次,commit_count > 0 证明提取已运行。
来自命令行的第二意见:ov health 和 ov config validate 读取同一个 ~/.openviking/ovcli.conf(它们会显示该密钥对应的账户/用户/角色)。ov config list 会揭示是否用 ov config switch 切换到了另一个 profile — 这同样会改变插件的目标。
服务端(仅当服务运行在本机时才有意义):
curl -sS "$URL/ready" # agfs / vectordb / api_key_manager / embedding (live probe, ≤10s) / ollama
openviking-server doctor # in the server's own environment: config, native engine, embedding probe, VLM key, disk
lsof -nP -iTCP:1933 -sTCP:LISTEN # who owns the port
docker logs --tail 100 openviking # container deployments
log.output 默认为 stdout,因此服务日志就是它运行所在的终端/tmux 窗格、nohup 文件、journalctl -u openviking 或 docker logs;设置为 "file" 时则为 <storage.workspace>/log/openviking.log。启动时退出的服务会直接在那里打印原因 — 在前台运行 openviking-server 是查看它的最快方式。它是用户的进程:在停止或重启之前先征得同意。
修复
- 仅在用户同意的情况下编辑
~/.openviking/ovcli.conf;展示更改内容,保留未知键,保持 0600 权限,切勿回显密钥。 - 对于机器级覆盖,优先使用
~/.claude/settings.json的env块中的环境变量;shell rc 导出只能到达从该 shell 启动的会话,并且会在所有地方静默地覆盖该文件。 - 更改
url、安装或更新插件后:重启 Claude Code。钩子每次调用都会重新读取配置,MCP 代理则不会。 - 更新:GitHub 安装 →
claude plugin marketplace update openviking && claude plugin update openviking-memory@openviking;在 Claude Code 2.1.224+ 上,TOS 安装(一个urlmarketplace)会在后台自动更新,或用claude plugin update openviking-memory@openviking按需更新;更早的 TOS、归档和 dev-checkout 安装 → 重新运行安装程序。 - 通过重新运行 doctor,然后观察下一条提示词上出现的
<openviking-context>块来确认修复。
文档
- 源码和 issue:https://github.com/volcengine/OpenViking — 插件代码位于
examples/下,共享安装程序位于examples/memory-plugin-shared/下。 - 文档索引(对 LLM 友好):https://docs.openviking.ai/llms.txt;其下的 harness 集成页面涵盖安装路径、配置键和已知限制。
https://api.vikingdb.cn-beijing.volces.com/openviking是火山引擎托管的 OpenViking Service(OpenViking Cloud):路径前缀是 base url 的一部分,它只接受Authorization: Bearer,其密钥由火山引擎控制台签发,而非由自托管管理员签发。
规则
- 绝不打印完整 API key 或
ovcli.conf的原始内容;doctor 的脱敏形式就是底线。 scripts/setup.mjs需要 TTY,并且在旧版插件上需要已有的ovcli.conf;在全新机器上直接写入该文件,或重新运行安装程序。- 绝不将
claude plugin list通过管道传给grep -q;先捕获输出(在pipefail下提前退出会被读作"未安装")。 /health返回 200 只能证明可达性。认证需通过带 key 的身份字段,或通过/api/v1/system/status来证明。ov doctor就是openviking-server doctor:它在服务自身的 Python 环境中验证服务自身的配置和 provider,发起一次实时 embedding 调用,并且对本插件只字不提。在遇到 provider 级故障时运行它,而不是首选运行。- doctor 只读取。未经询问,绝不停止、重启或
kill用户的服务,也绝不编辑ov.conf。 - 旧版代理会说"检查 'ov serve' 是否在运行"——不存在这样的命令;服务是通过
openviking-server启动的。 OPENVIKING_MEMORY_ENABLED=0会禁用 hooks,但不会禁用 MCP 工具;OPENVIKING_MCP_URL对本插件没有影响。