# 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//{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 `/.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": { "": [ { "command": "node \"\\dist\\hooks\\.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` (status `completed|aborted|error`, `loop_count`); completed turn read via base field `transcript_path`, not inline — minor handler change. - PreCompact → `preCompact` (rich usage stats) but **observational only** (stdout `{user_message}`, cannot block/reorder). `compact_memory` runs 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.` 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.** - `beforeSubmitPrompt` cannot inject context (acceptable — UserPromptSubmit only persists). - `preCompact` observational 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.json` may not exist on fresh install — `install.ts` must create skeleton, not throw. - Windows `.cmd`-shim exec problem applies — thread `--cli-path` to compiled `hive-mind-cli dist/index.js`. - Editing `hooks.json` likely needs a Cursor restart (reload semantics unverified across 1.7.x) — surface in install UX. - Exact `transcript_path` file 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 \"/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 or `hookSpecificOutput.additionalContext` (exact shape session-start.ts already emits). - UserPromptSubmit (`prompt`, `turn_id`, `session_id`, `cwd`) — existing handler already parses `prompt`/`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 `codex` may silently ignore hooks.json. - CC installer hard-requires a pre-existing config; codex hooks.json is optional/standalone → `install.ts` must create-if-missing (behavioral fork, not a copy). - Admin lockdown `allow_managed_hooks_only = true` (requirements.toml) can suppress user hooks — `verify` must 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.]]` TOML in config.toml. JSON shape: `{"hooks":{"":[{"matcher":"*","hooks":[{"type":"command","command":"node \"/hooks/.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 `/hooks` to trust" (enterprise `requirements.toml` managed hooks bypass trust but that's an org path). - App settings page doesn't mention hooks; only the general `/codex/hooks` doc 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 Store `9PLM9XGG6VKS`, 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_call` with `is_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; optionally `on_session_finalize` for 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_memory` from 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_memory` from 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 from `HOOKS_COHORT` — both must change. - Context-injection asymmetry: `on_session_start` is observer-only; injection rides `pre_llm_call(is_first_turn)` → SessionStart handler must split into two registrations. - **Source-level unverified:** the exact `VALID_HOOKS` allow-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//` with `HOOK.md` + `handler.ts`, or point `hooks.internal.load.extraDirs:[""]` at an external dir; enable via `openclaw hooks enable `. (2) legacy `hooks.internal.handlers[]` (deprecated). Internal-hooks shape: `{ "hooks": { "internal": { "enabled": true, "entries": { "": {"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 **mutable `bootstrapFiles` array** — first-class injection seam ≈ CC `additionalContext`) or `command:new` (on `/new`); `gateway:startup` is 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:sent` fires per delivered outbound reply (0..N/turn); or `before_agent_finalize` inspects the final answer during finalization. Maps onto `message:sent` but turn boundaries are looser. - PreCompact → `session:compact:before` (`messageCount`, `tokenCount`); `session:compact:after` reports before/after — direct PreCompact analogue, ideal `compact_memory` point. **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//`), `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:sent` is 0..N/turn, `before_agent_finalize` is 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/stringify` destroys user comments; need JSON5-aware merge or restrict edits to writing hook dirs + minimal `extraDirs`. - 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.ts` event TS type, whether `execFileAsync` is reliable under the gateway loop, whether `openclaw hooks enable` is required vs auto-discovery, and whether `bootstrapFiles` mutation is the sanctioned injection path vs `command: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":[""], "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) port `paths.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/Claude` pointer. (2) New settings-merger → additively merge an entry under `mcpServers` (not `hooks`), 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 `.mcpb` bundle for one-click install. **Honest §10/README framing:** this captures **memory on-demand** (Claude voluntarily calling `recall_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. - `.mcpb` manifest 0.3 exposes only tools/resources/prompts (no lifecycle field) — bundles can't register handlers. - **Existing artifact conflict:** `HOOK_POINTER_BY_TOOL` uses a non-existent `.config/Claude/...` dir → detector's hook-installed check would be wrong; fix if a real installer ships. - **Redundancy risk:** `packages/memory-mcp` already 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_memory` can'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) 1. **Codex CLI (`hive-mind-hooks-codex`)** — highest reuse (schema is a CC clone), full 4-hook lifecycle, native `additionalContext` inject. Build this first; it becomes the second reference shape (CC-clone-with-create-if-missing) for the rest of the cohort. 2. **Codex Desktop (`hive-mind-hooks-codex-desktop`)** — near-free once Codex CLI lands: thin re-export over the same `~/.codex/` installer. Bundle the `tool-detection.ts` fix (config-presence detection + correct pointer) here. 3. **Cursor (`hive-mind-hooks-cursor`)** — full lifecycle, near-verbatim port, only payload-field renames + a separate `hooks.json` path + create-if-missing. High-value (Cursor is a widely used editor) and low-risk. 4. **Hermes (`hive-mind-hooks-hermes`)** — first Tier-B: reuse handlers, rewrite install for YAML, drop PreCompact, add to `HOOKS_COHORT`, ship a real bin. Medium confidence — budget a live-payload verification spike. 5. **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. 6. **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 wrong `HOOK_POINTER_BY_TOOL` entry as part of whatever ships. --- ## 5. Key Risks 1. **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_HOOKS` allow-list; OpenClaw `handler.ts` event type + `execFileAsync`-under-loop reliability + `bootstrapFiles` injection sanction) are docs-only, not source-verified. Budget a live-payload/handler verification spike before committing Tier B estimates. 2. **`tool-detection.ts` carries known-wrong data.** `HOOK_POINTER_BY_TOOL` for **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. 3. **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). 4. **Not-silent installs.** Codex (CLI + Desktop) non-managed hooks require a one-time `/hooks` trust step; Cursor likely needs a restart for `hooks.json` to take effect. Neither is fully silent like CC — install UX must surface the manual step or the hook silently no-ops. 5. **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. 6. **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. 7. **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. 8. **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`](https://github.com/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-mind` surface. 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 excludes `vault.ts`, `evolution-runs.ts`, `execution-traces.ts`, `improvement-signals.ts`, `compliance/**`; the new hook packages have no such concerns (they only shell to `hive-mind-cli`) — keep it that way. - **`@waggle/hive-mind-shim-core` is 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.*