35 KiB
Wave 2/3 Hook Feasibility — Porting the hive-mind claude-code hook package to 6 other AI tools
Date: 2026-06-01
Author: Synthesis from 6 per-tool feasibility research passes
Status: Scoping brief — gates a human go/no-go + ordering decision
Reference package: packages/hive-mind-hooks-claude-code (Wave 1, shipped)
Targets: cursor, claude-desktop, codex, codex-desktop, hermes, openclaw (all currently export {} stubs)
0. TL;DR
Five of six tools have a real, deterministic lifecycle-hook surface and can reuse ~80% of the Wave 1
package (shim-core + the four handler bodies + the runHook stdin/stdout/exit-0 contract). The per-tool
work is almost entirely confined to three install-layer modules — paths.ts, settings-merger.ts,
install.ts (+ matching uninstall.ts/verify.ts) — plus payload-field remapping in the handlers.
The single outlier is Claude Desktop: it has no lifecycle hook API at all. It is not a hook port;
it is an MCP-server registration that yields only voluntary, model-initiated, on-demand capture — strictly
weaker than the every-turn deterministic capture the Wave 1 hook gives. Build it (the MCP server already
exists in packages/memory-mcp) but label it honestly as "MCP-bridge, partial capture."
Codex + Codex Desktop should be ONE package — they share ~/.codex/ entirely.
1. Comparison Matrix
| Tool | What it is | Config surface | SessionStart | UserPromptSubmit | Stop | PreCompact | Tier | Confidence |
|---|---|---|---|---|---|---|---|---|
| Cursor | AI-native VS Code-fork editor; first-party Hooks since v1.7 | ~/.cursor/hooks.json (JSON, {version,hooks:{event:[...]}}) |
native (sessionStart, additional_context inject) |
native (beforeSubmitPrompt; save-only, no inject) |
native (stop; turn read via transcript_path) |
approx (preCompact; observational, can't block) |
near-direct port | high |
| Codex CLI | OpenAI terminal coding agent; stable hooks mirror CC schema | ~/.codex/hooks.json (JSON, {hooks:{Event:[{matcher,hooks:[...]}]}}) |
native (SessionStart, additionalContext) |
native (UserPromptSubmit, prompt) |
native (Stop, last_assistant_message) |
native (PreCompact, trigger) |
near-direct port | high |
| Codex Desktop | OpenAI native GUI app; same runtime + same ~/.codex/ as CLI |
shared ~/.codex/hooks.json (identical to Codex CLI) |
native | native | native | native (PostCompact bonus) |
near-direct port (fold into Codex pkg) | high |
| Hermes Agent | Nous Research MIT Python self-improving CLI/server agent | ~/.hermes/config.yaml (YAML, hooks: block) |
native split (on_session_start observe + pre_llm_call first-turn inject) |
native (pre_llm_call) |
approx (post_llm_call per-turn / on_session_finalize) |
none (internal compaction, no hook) | lifecycle-hooks-need-adapter | medium |
| OpenClaw | Self-hosted Node "Gateway" bridging chat apps to coding agents | ~/.openclaw/openclaw.json (JSON5) + ~/.openclaw/hooks/<name>/{HOOK.md,handler.ts} (in-process TS, not stdin/stdout) |
native (agent:bootstrap mutable bootstrapFiles / command:new) |
native (message:received) |
approx (message:sent 0..N/turn / before_agent_finalize) |
native (session:compact:before) |
lifecycle-hooks-need-adapter | medium |
| Claude Desktop | Anthropic first-party GUI chat app; only extensibility = MCP | claude_desktop_config.json mcpServers key (macOS ~/Library/Application Support/Claude/, Win %APPDATA%\Claude\) |
none (MCP tool/prompt, model-discretion) | none (raw prompt never handed to server) | none (no turn event) | none (no host compaction event) | mcp-bridge-only | high |
"near-direct port" = reuse shim-core + handlers as-is; rewrite only the 3 install-layer modules + payload-field renames. "lifecycle-hooks-need-adapter" = all/most lifecycle events exist but the config format (YAML / JSON5+TS-handler) and/or registration model differs enough that the install layer is a rewrite and one event is degraded/missing. "mcp-bridge-only" = no hook surface; replace the hook package with an MCP-server config patcher; partial capture only.
2. Per-Tool Detail
2.1 Cursor — near-direct port — confidence: high
What it is. Anysphere's Cursor, an AI-native VS Code-fork desktop app with an Agent/Composer loop and a
cursor-agent CLI. Since v1.7 (late 2025, expanded through 2026) it ships a real first-party Hooks
feature that runs scripts on agent-loop lifecycle events.
Config surface. ~/.cursor/hooks.json (user-global), plus project <repo>/.cursor/hooks.json and enterprise
paths (Win C:\ProgramData\Cursor\hooks.json; mac /Library/Application Support/Cursor/hooks.json; linux
/etc/cursor/hooks.json). Format: { "version": 1, "hooks": { "<event>": [ { "command": "node \"<abs>\\dist\\hooks\\<event>.js\"", "type": "command", "timeout": 5 } ] } }. Each event maps to an array of hook
entries → additive append/merge works exactly like the Wave 1 settings.json merge. This is a separate file
from settings.json (which Cursor uses for editor prefs) — new path constants, same merge/marker/backup logic.
Detection already present: binary candidates + pointer ~/.cursor/hive-mind-install.json in HOOK_POINTER_BY_TOOL.
Lifecycle mapping.
- SessionStart →
sessionStart(new composer conversation); stdout{additional_context, env}— directly satisfies recall-and-inject. - UserPromptSubmit →
beforeSubmitPrompt(stdin{prompt, attachments}); save-only. Caveat: cannot inject (stdout only{continue, user_message}) — fine, hive-mind's UserPromptSubmit only persists. - Stop →
stop(statuscompleted|aborted|error,loop_count); completed turn read via base fieldtranscript_path, not inline — minor handler change. - PreCompact →
preCompact(rich usage stats) but observational only (stdout{user_message}, cannot block/reorder).compact_memoryruns fire-and-forget; "before host truncates" is best-effort, not guaranteed-before.
Recommended approach. Port nearly verbatim. shim-core reusable as-is. hooks/_shared.ts ports verbatim
(identical stdin-JSON/stdout-JSON command-hook model). Four handlers port with small field renames (SessionStart
returns {additional_context}; UserPromptSubmit reads stdin.prompt; Stop summarizes via base.transcript_path;
PreCompact shells compact_memory best-effort). Rewrite the 3 install modules: paths.ts (hooks.json target,
keep pointer), settings-merger.ts (HOOK_EVENT_BY_BASENAME = {session-start:'sessionStart', user-prompt-submit:'beforeSubmitPrompt', stop:'stop', pre-compact:'preCompact'}; wrap with version:1 +
hooks.<event> arrays; keep _hiveMindShim marker), install.ts (create {version:1,hooks:{}} skeleton if
absent — CC throws if settings.json missing). type:'command', timeout:5. ~80% reuse.
Blockers.
beforeSubmitPromptcannot inject context (acceptable — UserPromptSubmit only persists).preCompactobservational only — "run compact_memory BEFORE host truncates" is best-effort.- Stop reads turn via
transcript_path(null if transcripts disabled) — handler must tolerate null and fail open. hooks.jsonmay not exist on fresh install —install.tsmust create skeleton, not throw.- Windows
.cmd-shim exec problem applies — thread--cli-pathto compiledhive-mind-cli dist/index.js. - Editing
hooks.jsonlikely needs a Cursor restart (reload semantics unverified across 1.7.x) — surface in install UX. - Exact
transcript_pathfile format undocumented — Stop summarizer must read defensively (don't assume JSONL).
Sources. cursor.com/docs/hooks (+ .md); blog.gitbutler.com/cursor-hooks-deep-dive;
aiengineerguide.com/til/cursor-agent-lifecycle-hooks; skywork.ai/blog/how-to-cursor-1-7-hooks-guide;
repo packages/{agent,shared}/src/tool-detection.ts, packages/hive-mind-hooks-claude-code/**,
packages/hive-mind-hooks-cursor/src/index.ts (stub).
2.2 Codex CLI — near-direct port — confidence: high
What it is. OpenAI's terminal coding agent CLI (codex), rooted at ~/.codex/config.toml. As of May 2026 it
ships a stable lifecycle-hooks system that deliberately mirrors Claude Code's schema (same event names,
stdin JSON, exit-0 contract, additionalContext injection).
Config surface. Write a standalone ~/.codex/hooks.json (JSON), not config.toml — keeps us out of the
user's TOML and away from protected notify/profile/model_providers keys. Shape mirrors CC's hooks block:
{ "hooks": { "SessionStart": [ { "matcher": "startup|resume", "hooks": [ { "type":"command", "command":"node \"<dist>/hooks/session-start.js\" --cli-path \"...\"" } ] } ], "UserPromptSubmit":[...], "Stop":[...], "PreCompact":[...] } }.
Hooks across config layers are additive (no override) → marker-tagged merge not required for correctness but
kept for byte-identical reversible uninstall. Pointer ~/.codex/hive-mind-install.json matches HOOK_POINTER_BY_TOOL.
Lifecycle mapping. All four native and field-compatible with the existing handlers:
- SessionStart (
startup|resume|clear|compact,source); injects via stdout text orhookSpecificOutput.additionalContext(exact shape session-start.ts already emits). - UserPromptSubmit (
prompt,turn_id,session_id,cwd) — existing handler already parsesprompt/session_id/cwd. - Stop (
last_assistant_message,turn_id,stop_hook_active). - PreCompact (
trigger=manual|auto).
Recommended approach. Promote stub to near-verbatim CC clone. Reuse as-is: @waggle/hive-mind-shim-core
entirely (tool-agnostic); src/hooks/{_shared,session-start,user-prompt-submit,stop,pre-compact}.ts essentially
unchanged (already parse snake_case session_id/prompt/cwd; session-start already emits the
hookSpecificOutput.additionalContext Codex honors). Minor edits: set HookEvent.source from 'claude-code'
→ 'codex'; add codex last_assistant_message/trigger keys to the existing multi-key pickStringFromObject
fallbacks. Rewrite install layer: paths.ts (~/.codex/hooks.json, pointer ~/.codex/hive-mind-install.json),
settings-merger.ts ({hooks:{Event:[{matcher,hooks:[...]}]}}, matcher "startup|resume|clear|compact" for
SessionStart / "" elsewhere, keep _hiveMindShim marker), install.ts/uninstall.ts/verify.ts (create
hooks.json if absent; delete-if-created vs restore-backup-if-existed). Keep --cli-path Windows quoting verbatim.
HOOK_EVENT_BY_BASENAME is identical. Do NOT use notify — it only fires agent-turn-complete (Stop subset),
JSON on argv not stdin, user-config-only, strictly weaker. Estimate ~1 day, dominated by install/merge/verify + tests.
Blockers.
- Field-name casing confirmed from docs but not from a live payload — add codex keys as fallbacks rather than assuming.
- Minimum Codex version shipping stable hooks not pinned ("stable as of May 2026", no version) — verify dynamically; too-old
codexmay silently ignore hooks.json. - CC installer hard-requires a pre-existing config; codex hooks.json is optional/standalone →
install.tsmust create-if-missing (behavioral fork, not a copy). - Admin lockdown
allow_managed_hooks_only = true(requirements.toml) can suppress user hooks —verifymust surface this so install doesn't silently no-op.
Sources. developers.openai.com/codex/{hooks,config-advanced,config-reference};
github.com/openai/codex/blob/main/docs/config.md; github.com/openai/codex/issues/8189;
repo detection + Wave 1 reference + packages/hive-mind-shim-core/src/cli-bridge.ts.
2.3 Codex Desktop — near-direct port (fold into Codex pkg) — confidence: high
What it is. OpenAI's native Codex desktop GUI (the "Codex app"), macOS + Windows (Linux waitlisted), running
Codex threads in parallel. Not a separate engine — same Codex runtime, same shared ~/.codex/config.toml as
CLI + IDE extension.
Config surface. Registers into the shared ~/.codex/ root — identical for CLI, IDE, and App. Use
~/.codex/hooks.json (cleaner additive-JSON merge) or inline [[hooks.<Event>]] TOML in config.toml. JSON shape:
{"hooks":{"<Event>":[{"matcher":"*","hooks":[{"type":"command","command":"node \"<dist>/hooks/<event>.js\"","commandWindows":"...","timeout":600}]}]}}.
Non-managed hooks require one-time user trust via the /hooks command (trust keyed by hook hash) before they execute.
Lifecycle mapping. SessionStart / UserPromptSubmit / Stop / PreCompact all native (PostCompact bonus); JSON on stdin.
Recommended approach. Build ONE @waggle/hive-mind-hooks-codex package serving both codex (CLI) and
codex-desktop (App) — they share ~/.codex/ entirely, so a separate codex-desktop installer is redundant. Make
hive-mind-hooks-codex-desktop a thin re-export, or key one installer on the shared config root for both ToolIds.
Port as in §2.2. Also fix tool-detection.ts: the current codexDesktopCandidatePaths are speculative/wrong
(%LOCALAPPDATA%/OpenAI/Codex.exe, /Applications/Codex.app/...; source comment admits "unreleased at time of
writing"). Prefer config-presence detection at ~/.codex/ over guessing the binary; correct
HOOK_POINTER_BY_TOOL['codex-desktop'] from '.config/Codex/...' → '.codex/hive-mind-install.json'. Add a
post-install note to run /hooks once to trust.
Blockers.
- Non-managed hooks are not auto-trusted — install is not fully silent; surface "run
/hooksto trust" (enterpriserequirements.tomlmanaged hooks bypass trust but that's an org path). - App settings page doesn't mention hooks; only the general
/codex/hooksdoc asserts the App honors them — runtime verification on an actual App install needed (CLI definitely fires). - On-disk desktop paths undocumented (mac
.dmg, Win Microsoft Store9PLM9XGG6VKS, Linux unreleased) — replace hardcoded guesses with config-presence detection. - Stop exit-2 "continues with stderr as a new prompt" (not a hard block) — harmless for fail-open exit-0 capture; ensure ported handler never writes stderr+exit-2.
Sources. developers.openai.com/codex/{hooks,app/settings,ide/settings,config-reference,app,changelog};
repo detection (speculative paths, wrong pointer) + packages/hive-mind-hooks-codex-desktop/src/index.ts (stub) + Wave 1 reference.
2.4 Hermes Agent — lifecycle-hooks-need-adapter — confidence: medium
What it is. Hermes Agent by Nous Research — a real MIT-licensed Python self-improving CLI/server agent (the
hermes binary, config under ~/.hermes/). NOT the Nous Hermes LLM model. Confirmed target by
docs/addictiveness-audit-2026-05-28/BENCHMARK-hermes.md.
Config surface. Config-driven YAML shell hooks in ~/.hermes/config.yaml under a top-level hooks: block (no
Python required). Each event key → list of { command, matcher?, timeout? (default 60, max 300) }. Scripts get
JSON on stdin, return JSON on stdout ({"context":"..."} to inject, {"decision":"block",...}, or {} for no-op)
— nearly identical to the hive-mind contract. Hooks live by convention under ~/.hermes/agent-hooks/. Pointer
~/.hermes/hive-mind-install.json already expected.
Lifecycle mapping.
- SessionStart → split:
on_session_start(observer-only, no injection) for "switch workspace" +pre_llm_callwithis_first_turn=true(returns{context:...}) for "inject recalled frames." - UserPromptSubmit →
pre_llm_call(fires once/turn before tool loop;user_message/conversation_history/is_first_turn) — fire-and-forget save. - Stop →
post_llm_call(after tool loop,assistant_response) for the per-turn important-frame summary; optionallyon_session_finalizefor end-of-session flush. - PreCompact → none. Hermes compacts internally (preflight >50% ctx, gateway auto-compress >85%) and flushes memory to disk first, but exposes no hook at that boundary. Approximate via opportunistic
compact_memoryfrom the Stop handler.
Recommended approach. Config-driven YAML shell-hook installer — cleanest target after CC itself. Reuse as-is:
@waggle/hive-mind-shim-core + the four handler bodies (same stdin-JSON/stdout-JSON, exit-0/fail-open contract;
port with payload-field remapping via pickStringField, e.g. user_message/is_first_turn/session_id).
Rewrite the install trio: paths.ts (~/.hermes/, config.yaml, pointer), settings-merger.ts (YAML merge
keyed by {on_session_start, pre_llm_call, post_llm_call}; add a YAML parser dep e.g. yaml; additive +
marker-tagged + preserve user hooks), install.ts (read-or-create — config may not exist; timestamped
byte-identical backup + reversible uninstall). Wire: SessionStart→on_session_start (+ pre_llm_call/first-turn
inject), UserPromptSubmit→pre_llm_call, Stop→post_llm_call. Drop the 4th hook (no PreCompact — document the
gap, don't invent). Finally add 'hermes' to HOOKS_COHORT in tool-launcher.ts and ship a real bin (currently stub).
Blockers.
- No PreCompact-equivalent — 4th hook cannot be ported, only approximated by opportunistic
compact_memoryfrom Stop. - Config is YAML, not JSON — YAML round-trip is not byte-identical for re-serialized output; mitigate by keeping a literal backup for uninstall rather than diff-merge fidelity.
- Existing pkg is a binless
export {}stub and'hermes'is excluded fromHOOKS_COHORT— both must change. - Context-injection asymmetry:
on_session_startis observer-only; injection ridespre_llm_call(is_first_turn)→ SessionStart handler must split into two registrations. - Source-level unverified: the exact
VALID_HOOKSallow-list for shell hooks (vs Python plugin hooks); docs-only, not read from implementation. Benchmark doc's star/version figures (170k stars, v0.14.0) read as possibly aspirational, unconfirmed. - Windows is early-beta (Linux/macOS/WSL2 first-class); Python-installed binary → PATH detection + launch UX weaker on Windows.
Sources. hermes-agent.nousresearch.com/docs/{user-guide/features/hooks, developer-guide/agent-loop, user-guide/features/skills, guides/build-a-hermes-plugin}; github.com/NousResearch/hermes-agent (+ hooks.md);
repo detection + launcher + docs/addictiveness-audit-2026-05-28/BENCHMARK-hermes.md + Wave 1 reference.
2.5 OpenClaw — lifecycle-hooks-need-adapter — confidence: medium
What it is. A self-hosted Node "Gateway" (Peter Steinberger / community, github.com/openclaw/openclaw)
bridging messaging surfaces (Discord, Slack, Telegram, WhatsApp, iMessage, …) to AI coding agents. CLI +
long-running daemon, not a CC fork or IDE, but it has its own openclaw CLI and a real internal hooks system.
Binary name + ~/.openclaw config dir verified correct; detector carries no model of the hooks subsystem.
Config surface. ~/.openclaw/openclaw.json (JSON5 — comments + trailing commas). Register hooks two ways:
(1) discovery-based (preferred) — drop ~/.openclaw/hooks/<name>/ with HOOK.md + handler.ts, or point
hooks.internal.load.extraDirs:["<abs>"] at an external dir; enable via openclaw hooks enable <name>. (2) legacy
hooks.internal.handlers[] (deprecated). Internal-hooks shape:
{ "hooks": { "internal": { "enabled": true, "entries": { "<name>": {"enabled":true,"env":{...}} }, "load": {"extraDirs":[...]} } } }.
Handlers are in-process TypeScript (export default async (event)=>{...}) — but MAY shell out
(execFileAsync("openclaw",[...])), so a hive-mind handler can spawn hive-mind-cli like CliBridge does.
(Distinct from the HTTP-webhook hooks.{enabled,token,path,mappings} block — a different subsystem.)
Lifecycle mapping.
- SessionStart →
agent:bootstrap(fires before workspace bootstrap files injected; exposes a mutablebootstrapFilesarray — first-class injection seam ≈ CCadditionalContext) orcommand:new(on/new);gateway:startupis process-level. - UserPromptSubmit →
message:received(every inbound channel message before agent processes;from/content/channelId/metadata) — direct save-prompt analogue. - Stop → approx. No single per-turn Stop.
message:sentfires per delivered outbound reply (0..N/turn); orbefore_agent_finalizeinspects the final answer during finalization. Maps ontomessage:sentbut turn boundaries are looser. - PreCompact →
session:compact:before(messageCount,tokenCount);session:compact:afterreports before/after — direct PreCompact analogue, idealcompact_memorypoint.
Recommended approach. Real integration via OpenClaw's internal hooks (all 4 events exist). Reuse
@waggle/hive-mind-shim-core as-is (CliBridge/logger/workspace-resolver/prompt-summarizer/importance-classifier/
frame-encoder all tool-agnostic). The four handler bodies port in spirit but must be re-authored as OpenClaw
handler.ts modules (export default async (event) => {...} switching on event.type/event.action, not reading
stdin JSON). Mapping: agent:bootstrap (push recalled frames into mutable bootstrapFiles) or command:new →
SessionStart; message:received → save temp frame; message:sent/before_agent_finalize → summarize+save;
session:compact:before → compact_memory. Rewrite the registration trio: paths.ts (~/.openclaw/ +
~/.openclaw/hooks/<name>/), settings-merger.ts (discovery-based: write hook directories with
HOOK.md+handler.ts and/or merge hooks.internal.load.extraDirs into JSON5 openclaw.json — no command-array
to splice), install.ts (back up openclaw.json, patch hooks.internal, openclaw hooks enable, drop the pointer,
byte-identical reversible uninstall). Keep fail-open as try/catch inside the handler (not process.exit(0)).
Blockers.
- No per-turn Stop —
message:sentis 0..N/turn,before_agent_finalizeis a plugin-hook → need a debounce/dedup or "last message:sent of a turn" heuristic. - Registration model incompatible with the reference: discovery-based TS handler files + JSON5, not a settings.json command-array → install trio is a rewrite, not a parameterization.
- JSON5 (comments + trailing commas) — naive
JSON.parse/stringifydestroys user comments; need JSON5-aware merge or restrict edits to writing hook dirs + minimalextraDirs. - Handlers are in-process TS loaded by the gateway → fail-open contract becomes "default-exported async handler that must not throw," not "thin stdin script, exit 0."
- Unverified: exact
handler.tsevent TS type, whetherexecFileAsyncis reliable under the gateway loop, whetheropenclaw hooks enableis required vs auto-discovery, and whetherbootstrapFilesmutation is the sanctioned injection path vscommand:new(docs prose + one example, not source-read). - OpenClaw drives arbitrary backend coding agents (incl. claude-code/codex) → gateway-layer capture may double-count if the backend also has hive-mind hooks → needs a provenance/dedup story.
Sources. docs.openclaw.ai/{automation/hooks, gateway/configuration-reference, cli/agent}; openclaw.ai;
github.com/openclaw/openclaw (PR #9761 hooks, Issue #3336); milvus.io overview; repo detection + stub.
2.6 Claude Desktop — mcp-bridge-only — confidence: high
What it is. Anthropic's first-party GUI desktop chat app for macOS + Windows (no official Linux client as of
2026). A desktop app — not a CLI or IDE. Its only extensibility surface is MCP servers (via
claude_desktop_config.json) and one-click .mcpb/.dxt Desktop Extension bundles. There is no hooks/settings.json surface.
Config surface. claude_desktop_config.json — macOS ~/Library/Application Support/Claude/, Windows
%APPDATA%\Claude\. Integration goes under top-level "mcpServers":
{ "mcpServers": { "hive-mind": { "command":"node", "args":["<memory-mcp dist/index.js>"], "env":{"HIVE_MIND_WORKSPACE_ID":"..."} } } }.
stdio transport for local servers; Streamable HTTP for remote. Alternative packaging: an .mcpb bundle (manifest
spec 0.3) for drag-into-Settings install. Note: HOOK_POINTER_BY_TOOL['claude-desktop'] = '.config/Claude/...'
is WRONG — not a real Claude Desktop config dir on any platform; needs fixing if a real installer ships.
Lifecycle mapping. All four → none. No SessionStart event (only a startup prompt Claude may invoke —
model-discretion, non-deterministic). No per-prompt hook (raw prompt never handed to the server on submit, so
"save every prompt" is impossible). No Stop/turn-completed event (no deterministic turn summarization). No exposed
compaction lifecycle (compact_memory only via manual or Waggle cron, never host-driven). The .mcpb manifest 0.3
exposes only tools/resources/prompts — no event-handler field — so a bundle can't register handlers either.
Recommended approach. Do NOT port the hook shim — there is nothing to register into. Replace the hooks
package with an MCP-bridge installer. Critical reuse: Waggle already ships the exact server —
packages/memory-mcp (src/index.ts + tools/{memory,awareness,identity,harvest,ingest,knowledge,wiki,workspace}.ts
resources/memory.ts) exposes the full hive-mind tool surface (recall_memory,save_memory, …) as a stdio MCP server. So the integration is a thin config patcher, not a new server: (1) portpaths.ts→ resolve the real config path (mac~/Library/Application Support/Claude/claude_desktop_config.json, Win%APPDATA%\Claude\...) — rewrite, don't reuse the wrong.config/Claudepointer. (2) New settings-merger → additively merge an entry undermcpServers(nothooks), marker-tag for reversible uninstall; the immutable-merge + timestamped-backup + pointer-file + byte-identical-uninstall shape ports cleanly even though the target key changes. (3) shim-core is mostly NOT reusable — CliBridge/runHook/readStdin/hook-handler scaffolding is dead weight; only the generic logger and the backup/pointer filesystem pattern carry over. (4) Optionally also produce an.mcpbbundle for one-click install. Honest §10/README framing: this captures memory on-demand (Claude voluntarily callingrecall_memory/save_memory) — strictly weaker than the every-turn deterministic capture of the CC shim. Mark the package "MCP-bridge, partial capture," do not imply hook parity.
Blockers.
- No lifecycle hook/event API — the 4-hook automatic-capture model is fundamentally unportable.
- MCP context is model-initiated, not server-pushed — no deterministic SessionStart inject, no raw prompt on submit, no turn on Stop → silent/automatic capture impossible.
.mcpbmanifest 0.3 exposes only tools/resources/prompts (no lifecycle field) — bundles can't register handlers.- Existing artifact conflict:
HOOK_POINTER_BY_TOOLuses a non-existent.config/Claude/...dir → detector's hook-installed check would be wrong; fix if a real installer ships. - Redundancy risk:
packages/memory-mcpalready provides the server → a separate hooks-claude-desktop package is mostly a config patcher. Confirm with PM whether to keep it as a package or fold the install into the existing launcher/MCP-registration flow before building. - PreCompact/
compact_memorycan't tie to host compaction — needs Waggle-side cron, out of band.
Sources. support.claude.com/.../local-mcp-servers-on-claude-desktop;
anthropic.com/engineering/desktop-extensions; github.com/modelcontextprotocol/mcpb;
blog.modelcontextprotocol.io/posts/2025-11-20-adopting-mcpb; mcpbundles.com/docs/concepts/mcpb-files;
code.claude.com/docs/en/hooks (CC hooks ≠ desktop app); github.com/desktop/desktop/issues/22138;
repo detection (wrong pointer) + packages/memory-mcp/** + stub.
3. Implementation Tiers
Tier A — near-direct port (reuse shim-core + handlers; rewrite only the 3 install modules + field renames)
Tools: Codex CLI, Codex Desktop, Cursor.
Rationale: All three have native first-party lifecycle hooks with a stdin-JSON / stdout-JSON / command-hook /
exit-0 model that is structurally identical to the Wave 1 reference. Codex's schema is a deliberate CC clone (events
match exactly); Cursor needs only payload-field renames and a separate hooks.json path. Codex CLI + Desktop share
~/.codex/ and collapse into one package. ~80% reuse, ~1 day each (Codex CLI is the anchor; Desktop is a thin
re-export; Cursor is a parallel clone).
Tier B — lifecycle-hooks-need-adapter (events exist but config format/registration model is a rewrite; one event degraded/missing)
Tools: Hermes Agent, OpenClaw.
Rationale: Both have real lifecycle events and the shim-core + handler bodies still reuse, but the install
layer is a genuine rewrite, not a parameterization — Hermes is YAML (no byte-identical round-trip; no PreCompact
event), OpenClaw is JSON5 + in-process TypeScript handler files (no stdin command-array; fail-open becomes try/catch;
looser Stop boundary). Both also have medium confidence (docs-only on key specifics) and require detector/cohort
plumbing changes (Hermes must be added to HOOKS_COHORT).
Tier C — mcp-bridge-only (no hook surface; register an MCP server; partial, on-demand capture)
Tools: Claude Desktop.
Rationale: No lifecycle hook API of any kind. The deliverable is an MCP-server config patcher wrapping the
already-built packages/memory-mcp, yielding voluntary model-initiated capture only — strictly weaker than the
every-turn deterministic capture of the shim. Must be labeled "partial capture." Open PM question: keep as a package
or fold into the existing MCP-registration flow.
Tier D — not-feasible-now
Tools: (none). Rationale: Every tool has at least a partial integration path. None is blocked outright at this time.
4. Recommended Implementation Order (easiest + highest-value first)
- Codex CLI (
hive-mind-hooks-codex) — highest reuse (schema is a CC clone), full 4-hook lifecycle, nativeadditionalContextinject. Build this first; it becomes the second reference shape (CC-clone-with-create-if-missing) for the rest of the cohort. - Codex Desktop (
hive-mind-hooks-codex-desktop) — near-free once Codex CLI lands: thin re-export over the same~/.codex/installer. Bundle thetool-detection.tsfix (config-presence detection + correct pointer) here. - Cursor (
hive-mind-hooks-cursor) — full lifecycle, near-verbatim port, only payload-field renames + a separatehooks.jsonpath + create-if-missing. High-value (Cursor is a widely used editor) and low-risk. - Hermes (
hive-mind-hooks-hermes) — first Tier-B: reuse handlers, rewrite install for YAML, drop PreCompact, add toHOOKS_COHORT, ship a real bin. Medium confidence — budget a live-payload verification spike. - OpenClaw (
hive-mind-hooks-openclaw) — most install-layer rework (JSON5 + in-process TS handlers, re-authored fail-open, Stop debounce, provenance/dedup story). Defer until a live OpenClaw install can validate the handler API. - Claude Desktop (
hive-mind-hooks-claude-desktop) — last, and gate it on a PM decision (package vs fold-into-launcher). It is a different deliverable (MCP bridge, partial capture), so don't let it block the four real hook ports. Fix the wrongHOOK_POINTER_BY_TOOLentry as part of whatever ships.
5. Key Risks
- Confidence asymmetry. Tier A (Codex×2, Cursor) is high-confidence and doc-corroborated. Tier B (Hermes, OpenClaw) is medium — key specifics (Hermes shell-hook
VALID_HOOKSallow-list; OpenClawhandler.tsevent type +execFileAsync-under-loop reliability +bootstrapFilesinjection sanction) are docs-only, not source-verified. Budget a live-payload/handler verification spike before committing Tier B estimates. tool-detection.tscarries known-wrong data.HOOK_POINTER_BY_TOOLfor claude-desktop (.config/Claude/...) and codex-desktop (.config/Codex/...) point at non-existent dirs; codex-desktop binary candidate paths are admitted guesses for an unreleased app. These must be corrected or the "is-it-installed" check lies. Prefer config-presence detection over binary-path guessing for the desktop apps.- Create-if-missing is a behavioral fork from the Wave 1 reference. The CC installer hard-requires a pre-existing config and throws if absent. Codex/Cursor/Hermes config files are optional/standalone and may not exist — every Tier A/B installer needs create-if-absent + the matching "delete-if-we-created vs restore-backup-if-existed" uninstall logic. Easy to get subtly wrong (orphaned files on uninstall).
- Not-silent installs. Codex (CLI + Desktop) non-managed hooks require a one-time
/hookstrust step; Cursor likely needs a restart forhooks.jsonto take effect. Neither is fully silent like CC — install UX must surface the manual step or the hook silently no-ops. - Degraded/missing events. Hermes has no PreCompact (approximate via opportunistic
compact_memory). Cursor PreCompact is observational (can't guarantee before-truncation). Cursor UserPromptSubmit can't inject. OpenClaw Stop is 0..N/turn (needs debounce). Document each gap rather than implying parity. - Config round-trip fidelity. Hermes YAML and OpenClaw JSON5 don't survive naive
parse→stringify(comments/ordering lost). Rely on literal byte-identical backups for uninstall rather than diff-merge fidelity; for OpenClaw, prefer writing hook directories and touching config minimally. - Claude Desktop is a category mismatch. Marketing/§10 must not imply hook parity — it is on-demand, model-discretion capture. There's also a redundancy decision (vs
packages/memory-mcp+ the existing launcher MCP-registration flow) that should be resolved by PM before any code is written. - OpenClaw double-counting. OpenClaw can drive claude-code/codex as backends; if those backends also have hive-mind hooks installed, the gateway-layer capture double-counts the same conversation. Needs a provenance/dedup story before shipping.
6. OSS-Mirror Implication
All seven hive-mind-hooks-* packages are part of the hive-mind OSS split (per CLAUDE.md §7.5) — the public
mirror at marolinik/hive-mind is generated from this monorepo via
git subtree split, so whatever lands in these packages is byte-identical in the OSS mirror and there is no
cross-repo drift to police.
Implications for this work:
- Everything built here ships publicly. The Codex/Cursor/Hermes/OpenClaw hook installers and the Claude Desktop
MCP bridge become part of the open-source
hive-mindsurface. That is consistent with the strategy (memory + harvest is the free-forever moat; broad AI-tool reach amplifies it) — but it means no proprietary/KVARK-gated logic belongs in these packages. The subtree-split filter (scripts/oss-subtree-split.sh) already excludesvault.ts,evolution-runs.ts,execution-traces.ts,improvement-signals.ts,compliance/**; the new hook packages have no such concerns (they only shell tohive-mind-cli) — keep it that way. @waggle/hive-mind-shim-coreis the shared, reused-as-is dependency across all Tier A/B ports — it too lives in the OSS split, so its tool-agnostic CliBridge/logger stay public. Reusing it (rather than per-tool copies) keeps the OSS mirror DRY and the subtree-split clean.- Per CLAUDE.md §7.5, do not resurrect the deprecated dual-repo sync workflows — the export is one-directional
(monorepo → mirror). Author everything in
packages/hive-mind-hooks-*; the mirror follows automatically.
This brief gates a human scoping decision. Tier A (Codex×2 + Cursor) is the safe, high-value first slice; Tier B needs a verification spike; Claude Desktop needs a PM package-vs-fold decision and an honest "partial capture" label.