@fuxi-ailabs/crowdmemory-openclaude-plugin
v0.1.1
Published
Crowd Memory plugin for OpenClaude: hooks translate session events into memory-agent-ingress/v1 and an MCP server forwards memory tools to the local Runtime (fail-open, no storage).
Keywords
Readme
crowdmemory-openclaude-plugin
Crowd Memory(群体记忆)的 OpenClaude 插件,做的事和 DSH 适配器一样:
- 把 OpenClaude 的会话事件翻成规范事件
memory-agent-ingress/v1,交给本机的 Crowd Memory Runtime; - 在第一步和失败后的下一步之前,把 Runtime 选出的经验作为引用资料交给 Agent,子代理也一样;
- 给 Agent 三个工具:
memory_search、memory_read、memory_note。
它不存储、不排序、不判定。Runtime 不可用时一律降级,会话照常运行,工具返回「记忆暂不可用」。
插件里有三样东西:hooks/hooks.json 里的 9 个 hook、.mcp.json 里提供三个工具的 MCP 服务,以及它们共用的
lib/。没有运行时依赖,只要 Node.js。Runtime 客户端、错误签名、脱敏和掩盖退出码的识别直接取自 DSH 适配器的
共用的适配器公共包(src/core/ 是 distributions/memory-adapter-core 生成的副本,不在这里改;测试和仓库门禁都检查副本没改偏)。
依赖
| 依赖 | 版本 |
|---|---|
| Node.js | ≥ 22.18,在 PATH 上叫 node(hook 和 MCP 服务都用它启动) |
| OpenClaude | 实测 0.12.0、0.31.0 |
| Crowd Memory Runtime | crowdmemory-runtime,协议 major 1 |
安装
从 npm 包装(发布后):在 OpenClaude 的 marketplace 里登记 npm 来源,再安装。
{
"name": "crowdmemory",
"owner": { "name": "cacheline" },
"plugins": [{ "name": "crowdmemory", "source": { "source": "npm", "package": "@fuxi-ailabs/[email protected]" } }]
}openclaude plugin marketplace add <放上面 marketplace.json 的目录或仓库>
openclaude plugin install crowdmemory@crowdmemory从本地构建装:
npm install && npm run build && npm pack # 得到 fuxi-ailabs-crowdmemory-openclaude-plugin-0.1.1.tgz
mkdir plugin && tar -xzf fuxi-ailabs-crowdmemory-openclaude-plugin-0.1.1.tgz -C plugin
openclaude plugin marketplace add "$PWD/plugin/package" # 包里自带 .claude-plugin/marketplace.json
openclaude plugin install crowdmemory@crowdmemory只想在一次运行里用:openclaude --plugin-dir <解开的包目录> …。
装完 openclaude plugin list 应看到 crowdmemory@crowdmemory 为 enabled;会话的 init 信息里 MCP 服务
plugin:crowdmemory:memory 为 connected。无头 -p 也能用,但不要加 --bare(它跳过插件);用 marketplace
安装时设 CLAUDE_CODE_SYNC_PLUGIN_INSTALL=1,插件在第一个请求前就绪。
建议关掉 OpenClaude 自带的 auto-memory(CLAUDE_CODE_DISABLE_AUTO_MEMORY=1):笔记由 Agent 调 memory_note
提交,两套记忆同时开着会互相干扰。
配置
和 DSH 适配器用同一组环境变量:
| 环境变量 | 说明 |
|---|---|
| CROWDMEMORY_ENDPOINT_FILE | Runtime 写出的 endpoint.json 的绝对路径。不设时用 $HOME/.crowdmemory/state/endpoint.json(npm 包 crowdmemory-runtime 默认安装的位置) |
| CROWDMEMORY_PROJECT | 项目标识,请设成稳定的仓库名。不设时取会话工作目录名 |
| CROWDMEMORY_PROFILE | 记忆模板,默认 session-default |
| CROWDMEMORY_INJECT | 设为 0 / false 时不把推送交给 Agent(事件照常上报) |
| CROWDMEMORY_NOTES | 设为 0 / false 时不提供 memory_note |
| CROWDMEMORY_OPENCLAUDE_STATE | 会话路由状态目录。不设时用 OpenClaude 给插件的数据目录 $CLAUDE_PLUGIN_DATA/sessions |
| CROWDMEMORY_DEBUG | 1:hook 的错误写到 stderr;绝对路径:追加到该文件 |
| CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS | 不需要调:SessionEnd 的 hook 把收尾交给后台进程后立即返回,不受 OpenClaude 默认 1.5 秒的限制 |
Runtime 的启动、生产配置和端点文件的信任规则与 DSH 适配器相同,见 DSH 适配器 README「启动 Runtime」。
事件对照
| OpenClaude hook | 对应 DSH 适配器的 | 发给 Runtime |
|---|---|---|
| SessionStart(startup / resume / clear) | agent/created | session.start |
| UserPromptSubmit(会话第一条) | 第一步的 agent/pre-step | step.before(带脱敏后的任务文本),返回的推送交给 Agent |
| PostToolUseFailure | tools/result 失败 + 下一步的 pre-step | tool.result(退出码、错误尾部、错误签名、命令)、step.before,推送交给 Agent |
| PostToolUse(Bash / Write / Edit / MultiEdit / NotebookEdit) | tools/result 成功 | 写文件只报路径;用 echo "exit code: $?" 之类掩盖了失败的命令按失败处理;看过记忆之后的成功命令 |
| PreToolUse(Agent / Task) | — | 不发;记下子代理的任务文本 |
| SubagentStart | subagent/start + 子会话第一步 | 子会话 session.start(parent_ref 指向父会话)、step.before,推送交给子代理 |
| SubagentStop | subagent/end + 子会话结束 | subagent.end、子会话 session.end |
| PostCompact | compaction/summary | context.compaction |
| SessionStart(compact) | — | 不发;把上一次推送再交给 Agent(压缩会丢掉之前 hook 给的内容) |
| SessionEnd | agent/disposed | 先结束还开着的子会话,再 session.end |
| PreToolUse(三个记忆工具) | — | 不发;把调用方会话交给 MCP 服务并放行,不弹权限确认 |
声明的能力:session_binding、step_injection、tool_capture、compaction_capture、subagent_capture、
note_tool、query_tools、workspace_snapshot。工具名按 DSH 的写法上报(Bash → bash,MultiEdit →
multi_edit),两边的错误签名和工具名信号可以互相命中。
和 DSH 适配器的差别
- 没有 L2:OpenClaude 没有 workflow 引擎和 goal 事件,不声明
workflow_events、goal_events。 - 成功命令没有退出码:OpenClaude 只在失败时给出
Exit code N;成功时 stdout 与 stderr 合在一起,grep返回 1 这类也算成功。 - 子代理的任务文本按顺序配对:SubagentStart 不带 prompt,插件按 Agent / Task 调用的先后把 prompt 配给子代理。同时派出多个子代理时,配错只影响第一步的排序。
- 压缩不区分子代理:PostCompact 不带子代理身份,压缩摘要都记在主会话上。
- 每个 hook 是一个新的 Node 进程(约 100 ms)。PostToolUse 只挂在会产生记录的工具上。
- 会话路由状态存在磁盘上(目录 0700、文件 0600,加锁读写,Runtime 请求不持锁),7 天未动的自动清理。
开发
npm install
npm run build # lib/
npm test # 单元测试:假 Runtime、契约 schema 校验、hook 进程、MCP 协议、公共包副本没改偏
e2e/run-l0.sh # 真实 OpenClaude 上的 e2e,见下e2e/run-l0.sh 和 DSH 适配器的同名脚本对应,分两段:
- 脚本化模型(离线,不要 key),断言全过才算通过:A 失败并记笔记 → B 同样失败收到推送并读取 → C 子代理收到推送 → D 收到推送后被压缩,Runtime 收到压缩摘要、压缩后推送重新出现 → 停掉 Runtime 后 X 照常跑完。记忆工具只靠插件自己的 PreToolUse 放行,脚本没有给它们预授权。
- 真实模型(只报告,不影响结果):有
ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN(环境变量,或~/.config/crowdmemory/e2e.env,ANTHROPIC_BASE_URL指向网关)时,在同一份 Runtime 状态上让CROWDMEMORY_E2E_ANTHROPIC_MODEL(默认claude-sonnet-5)跑一个会失败的命令,再查、读记忆。key 只在 本地认证代理(e2e/auth-proxy.mjs,与 DSH 共用)进程里,OpenClaude 和 Agent 的 shell 只拿到占位值。 OpenClaude 不认识的新模型会被发旧式 thinking 参数,这一段默认MAX_THINKING_TOKENS=0(CROWDMEMORY_E2E_MAX_THINKING_TOKENS可改)。CROWDMEMORY_E2E_REAL_PROVIDER=off关掉这一段。
默认用仓库 .venv 里的真实 Runtime(没有时用假 Runtime);CROWDMEMORY_E2E_OPENCLAUDE 指定 OpenClaude,
CROWDMEMORY_E2E_PLUGIN_DIR 指定插件目录(例如解开的 npm 包)。脚本会清掉调用方的 CLAUDE_CODE_* 环境变量。
