Repository navigation
[AI-70] CLI: Codex hook surface (codex-hook command + plugin install --codex) - #55
Conversation
Review Summary by QodoCLI: Codex hook surface (codex-hook command + plugin install --codex)
WalkthroughsDescription• Implements kapacitor codex-hook command as a single dispatcher for Codex hook events, mapping Codex's hook vocabulary to Capacitor's canonical hook routes (SessionStart → /hooks/session-start/codex, Stop → /hooks/session-end/codex, PermissionRequest → /hooks/permission-request/codex) • Adds kapacitor plugin install --codex and remove --codex to write/manage ~/.codex/hooks.json with all six Codex events • Extends kapacitor status to report installation state for both Claude and Codex hook surfaces • Threads real --vendor argument through kapacitor watch → WatcherManager.SpawnWatcher → SendTranscriptBatch, replacing hardcoded "claude" and enabling Codex sessions to tag TranscriptBatch.vendor = "codex" end-to-end • Adds comprehensive unit tests (456 passing) covering hook dispatch, URL mapping, plugin install/remove, status detection, watcher arg builder, and inline drain vendor tagging • Updates help documentation for codex-hook, plugin, status, and watch commands • Adds MCP configuration for Linear IDE integration Diagramflowchart LR
A["Codex Hook Events"] -->|"stdin JSON"| B["CodexHookCommand.Handle"]
B -->|"SessionStart"| C["POST /hooks/session-start/codex"]
B -->|"Stop"| D["POST /hooks/session-end/codex"]
B -->|"PermissionRequest"| E["POST /hooks/permission-request/codex"]
B -->|"Informational"| F["Swallow"]
C -->|"spawn watcher"| G["WatcherManager with vendor=codex"]
G -->|"drain transcript"| H["TranscriptBatch.vendor=codex"]
I["plugin install --codex"] -->|"write"| J["~/.codex/hooks.json"]
J -->|"register"| K["CodexHookCommand dispatcher"]
L["status command"] -->|"detect"| M["Claude plugin + Codex hooks"]
File Changes1. src/kapacitor/Commands/PluginCommand.cs
|
Code Review by Qodo
1.
|
The .mcp.json was leaked in from local session config and configures the Linear MCP server globally. The daemon's AgentOrchestrator reads repo-committed .mcp.json to enable MCP servers, so committing this file would silently turn on third-party network access for everyone using the repo. Unrelated to AI-70.
- PluginCommand.InstallCodexHooks/RemoveCodexHooks and StatusCommand.IsCodexHooksInstalled: use type-safe pattern matching instead of JsonNode indexers + GetValue<string>(). A malformed user-edited hooks.json no longer turns into a silent install/remove/detection failure. Factored out internal helper EntryReferencesKapacitorCodexHook shared by both commands. - CodexHookCommand.Handle: extract a TryGetString helper and route every payload-field read through it, so a schema drift (e.g., non-string hook_event_name) returns 0 instead of crashing the host process. - WatcherManager.BuildSpawnArgs: quote --vendor like other args. Addresses Qodo findings #2, #3, #4 on PR #55. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: document Codex hook installation Aligns README with PR #55 (AI-70). Setup is Claude-only, so Codex users have no in-README path to discovery. Adds a short subsection under setup covering kapacitor plugin install --codex (user-wide and --project), the corresponding remove command, and that kapacitor status reports both hook surfaces. Updates the "What it records" line to acknowledge Codex sessions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: note Codex --project trust prompt; status is user-wide Addresses Qodo review findings on #61: - kapacitor status only checks user-wide hook locations (ClaudePaths.UserSettings, CodexPaths.UserHooksJson), so --project installs report as not installed. README now says so and tells users to inspect the repo's .claude/settings.local.json or .codex/hooks.json directly. - Codex --project installs need the .codex directory trusted before hooks run. PluginCommand.InstallCodex itself prints this note; the README now mirrors it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
kapacitor codex-hook— single dispatcher for Codex hooks. Maps Codex's hook vocabulary onto Capacitor's canonical hook routes:SessionStart→ POST/hooks/session-start/codex(spawns watcher with--vendor codex)Stop→ POST/hooks/session-end/codex(Codex has no separate session-end hook per AI-67 spike)PermissionRequest→ POST/hooks/permission-request/codex(returns local{behavior: "allow"}stub for v1)UserPromptSubmit/PreToolUse/PostToolUse→ swallowed (informational; no server route in v1)kapacitor plugin install --codex(andremove --codex) writing~/.codex/hooks.json(or<repo>/.codex/hooks.jsonwith--project).kapacitor statusto report installation state for both Claude and Codex hook surfaces.--vendorargument throughkapacitor watch→WatcherManager.SpawnWatcher→SendTranscriptBatch, replacing the hardcoded"claude"left in place when AI-75 added the wire-protocol slot. Codex sessions now tagTranscriptBatch.vendor = "codex"end-to-end (live watcher path and inline drain).Server-side route changes (path-param vendor segment + DTO loosening) land separately in the kapacitor-server repo (companion PR).
Test plan
kapacitor plugin install --codexwrites a valid hooks.json with all six events🤖 Generated with Claude Code