Skip to content

[AI-70] CLI: Codex hook surface (codex-hook command + plugin install --codex) - #55

Merged
alexeyzimarev merged 11 commits into
mainfrom
capacitor/agent-05e74395770b4a
May 11, 2026
Merged

alexeyzimarev merged 11 commits into
mainfrom
capacitor/agent-05e74395770b4a

Conversation

@alexeyzimarev

Copy link
Copy Markdown
Member

Summary

  • Adds 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)
  • Adds kapacitor plugin install --codex (and remove --codex) writing ~/.codex/hooks.json (or <repo>/.codex/hooks.json with --project).
  • Extends kapacitor status to report installation state for both Claude and Codex hook surfaces.
  • Threads a real --vendor argument through kapacitor watch → WatcherManager.SpawnWatcher → SendTranscriptBatch, replacing the hardcoded "claude" left in place when AI-75 added the wire-protocol slot. Codex sessions now tag TranscriptBatch.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

  • Unit tests cover hook dispatch + URL mapping, plugin install/remove, status detection, watcher arg builder, inline drain vendor tagging (456/456 pass)
  • Integration tests pass (4/4)
  • AOT publish reports no IL3050/IL2026 warnings
  • Smoke: kapacitor plugin install --codex writes a valid hooks.json with all six events
  • Live integration smoke (start Codex, see session in dashboard) — gated on companion server PR

🤖 Generated with Claude Code

@linear

linear Bot commented May 10, 2026

Copy link
Copy Markdown

AI-70

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

CLI: Codex hook surface (codex-hook command + plugin install --codex)

✨ Enhancement 🧪 Tests 📝 Documentation

Grey Divider

Walkthroughs

Description
• 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
Diagram
flowchart 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"]
Loading

Grey Divider

File Changes

1. src/kapacitor/Commands/PluginCommand.cs ✨ Enhancement +193/-14

Add Codex hooks installation and removal support

• Refactored Install and Remove methods to dispatch to vendor-specific handlers
 (InstallClaude/RemoveClaude vs InstallCodex/RemoveCodex) based on --codex flag
• Added InstallCodexHooks and RemoveCodexHooks public methods that manage ~/.codex/hooks.json
 by writing/merging hook entries for all six Codex events
• Extracted shared WriteOpts JSON serializer and CodexHookEvents array as static fields
• Updated usage text to document [--codex] option

src/kapacitor/Commands/PluginCommand.cs


2. src/kapacitor/Commands/CodexHookCommand.cs ✨ Enhancement +151/-0

Implement Codex hook event dispatcher and router

• New static class implementing single-binary dispatcher for Codex hook events
• Handle method reads JSON payload from stdin, normalizes session_id GUID, injects home_dir
 and agent_host_id, then branches on hook_event_name
• SessionStart spawns watcher with vendor: "codex" after posting to /hooks/session-start/codex
• Stop kills watcher and drains transcript before posting to /hooks/session-end/codex
• PermissionRequest returns local {behavior: "allow"} stub after posting to
 /hooks/permission-request/codex
• UserPromptSubmit, PreToolUse, PostToolUse are silently swallowed (v1 informational events)

src/kapacitor/Commands/CodexHookCommand.cs


3. test/kapacitor.Tests.Unit/CodexHookCommandTests.cs 🧪 Tests +156/-0

Add comprehensive Codex hook command unit tests

• New test class with 7 unit tests covering hook dispatch logic
• Tests verify correct URL mapping (SessionStart → /hooks/session-start/codex, Stop →
 /hooks/session-end/codex)
• Tests confirm session_id normalization (dashes removed) and home_dir injection
• Tests verify PermissionRequest returns default allow decision via stdout
• Tests confirm informational events and unknown events are swallowed without HTTP requests
• Tests verify malformed JSON and missing fields are handled gracefully

test/kapacitor.Tests.Unit/CodexHookCommandTests.cs


View more (17)
4. src/kapacitor/WatcherManager.cs ✨ Enhancement +51/-28

Thread vendor parameter through watcher spawn and drain paths

• Extracted BuildSpawnArgs public method to construct watcher spawn arguments, accepting new
 vendor parameter (defaults to "claude")
• --vendor flag is only appended to arguments when vendor != "claude" (omitted for default)
• Updated SpawnWatcher, EnsureWatcherRunning, and InlineDrainAsync signatures to accept
 vendor parameter
• InlineDrainAsync now sets TranscriptBatch.Vendor to vendor value when not "claude" (null
 otherwise)

src/kapacitor/WatcherManager.cs


5. test/kapacitor.Tests.Unit/PluginCommandCodexTests.cs 🧪 Tests +110/-0

Add Codex hooks install/remove unit tests

• New test class with 4 unit tests for Codex hooks installation and removal
• Tests verify all six Codex events are written with correct hook structure and `kapacitor
 codex-hook` command
• Tests confirm existing non-kapacitor entries are preserved during install
• Tests verify kapacitor entries are overwritten (timeout/command stay current after upgrade)
• Tests confirm removal clears all kapacitor entries while preserving others

test/kapacitor.Tests.Unit/PluginCommandCodexTests.cs


6. src/kapacitor/Commands/StatusCommand.cs ✨ Enhancement +62/-1

Extend status command to report hook installation state

• Added IsClaudePluginInstalled method to detect Claude plugin via
 enabledPlugins["kapacitor@kapacitor"] in settings
• Added IsCodexHooksInstalled method to detect Codex hooks by searching for kapacitor codex-hook
 command in hooks.json
• Extended HandleAsync to report hooks installation state for both Claude and Codex in status
 output
• Reformatted long auth status line for readability

src/kapacitor/Commands/StatusCommand.cs


7. test/kapacitor.Tests.Unit/StatusCommandHooksTests.cs 🧪 Tests +92/-0

Add hook detection unit tests for status command

• New test class with 8 unit tests for hook detection logic
• Tests verify Claude plugin detection when enabled/disabled and when file is absent
• Tests verify Codex hooks detection when kapacitor codex-hook command is present or absent
• Tests confirm graceful handling of malformed JSON and missing files

test/kapacitor.Tests.Unit/StatusCommandHooksTests.cs


8. src/kapacitor/Program.cs ✨ Enhancement +9/-2

Wire codex-hook command and vendor parameter through CLI

• Updated watch command usage text to document [--vendor claude|codex] option
• Added parsing of --vendor argument (defaults to "claude")
• Threaded watchVendor parameter through to WatchCommand.RunWatch call
• Added new case "codex-hook" branch that invokes CodexHookCommand.Handle with baseUrl and
 Console.In

src/kapacitor/Program.cs


9. src/kapacitor/Commands/WatchCommand.cs ✨ Enhancement +6/-4

Thread vendor parameter through watch command drain path

• Added vendor parameter to RunWatch method signature (defaults to "claude")
• Threaded vendor parameter through both DrainNewLines calls (periodic and final drain)
• Updated DrainNewLines signature to accept vendor parameter
• Replaced hardcoded "claude" string with vendor variable in SendTranscriptBatch invocation

src/kapacitor/Commands/WatchCommand.cs


10. test/kapacitor.Tests.Unit/HookForwardingTests.cs 🧪 Tests +38/-0

Add vendor parameter integration test for inline drain

• Added new test PostsCorrectBatch_with_codex_vendor_when_specified verifying that
 InlineDrainAsync with vendor: "codex" correctly sets vendor field in posted TranscriptBatch

test/kapacitor.Tests.Unit/HookForwardingTests.cs


11. test/kapacitor.Tests.Unit/WatcherManagerSpawnArgsTests.cs 🧪 Tests +40/-0

Add spawn arguments builder unit tests

• New test class with 3 unit tests for BuildSpawnArgs method
• Tests verify --vendor flag is omitted when vendor is "claude" (default)
• Tests verify --vendor codex is appended when vendor is "codex"
• Tests verify all spawn argument combinations (agent, cwd, skip-title, parent-pid) are correctly
 assembled

test/kapacitor.Tests.Unit/WatcherManagerSpawnArgsTests.cs


12. test/kapacitor.Tests.Unit/WatchCommandTests.cs 🧪 Tests +14/-0

Add watch command signature verification test

• Added new test class WatchCommandTests with single test verifying RunWatch method signature
 accepts vendor parameter with default value "claude"

test/kapacitor.Tests.Unit/WatchCommandTests.cs


13. src/Kapacitor.Core/CodexPaths.cs ✨ Enhancement +3/-3

Add UserHooksJson path constant for Codex hooks

• Converted Home from static readonly field to auto-property
• Added new UserHooksJson property resolving to ~/.codex/hooks.json
• Simplified Sessions property to use expanded path (no intermediate variable)

src/Kapacitor.Core/CodexPaths.cs


14. test/kapacitor.Tests.Unit/CodexPathsTests.cs 🧪 Tests +6/-0

Add CodexPaths.UserHooksJson test

• Added new test UserHooksJson_resolves_under_home_codex verifying path resolves to
 ~/.codex/hooks.json

test/kapacitor.Tests.Unit/CodexPathsTests.cs


15. src/Kapacitor.Core/Resources/help-codex-hook.txt 📝 Documentation +17/-0

Add help documentation for codex-hook command

• New help file documenting kapacitor codex-hook command
• Describes stdin JSON payload contract and event-to-route mapping
• Lists all six Codex events and their handling (forward, swallow, or return stub)
• Notes command is internal and wired via kapacitor plugin install --codex

src/Kapacitor.Core/Resources/help-codex-hook.txt


16. src/Kapacitor.Core/Resources/help-plugin.txt 📝 Documentation +10/-3

Update plugin help to document Codex support

• Updated title to reflect both Claude Code and Codex CLI support
• Expanded subcommand descriptions to cover both vendors
• Added --codex option documentation
• Added examples showing user-wide and project-scoped installation for both vendors

src/Kapacitor.Core/Resources/help-plugin.txt


17. src/Kapacitor.Core/Resources/help-usage.txt 📝 Documentation +3/-2

Update usage help for Codex hook support

• Updated plugin command descriptions to indicate support for both Claude and Codex
• Added codex-hook to hook commands section with brief description
• Updated help text to show [--codex] option availability

src/Kapacitor.Core/Resources/help-usage.txt


18. src/Kapacitor.Core/Resources/help-status.txt 📝 Documentation +7/-1

Update status help to document hook reporting

• Updated title to include "hook" status reporting
• Added "Reports" section documenting what each status line shows
• Added "Hooks" entry explaining Claude plugin and Codex hooks detection

src/Kapacitor.Core/Resources/help-status.txt


19. .mcp.json ⚙️ Configuration changes +8/-0

Add MCP configuration for Linear integration

• New MCP (Model Context Protocol) configuration file
• Registers Linear server as SSE endpoint for IDE integration

.mcp.json


20. docs/superpowers/plans/2026-05-10-ai-70-codex-hook-surface.md 📝 Documentation +2368/-0

AI-70 Codex hook surface implementation plan with TDD tasks

• Comprehensive implementation plan for AI-70 Codex hook surface feature, spanning CLI and server
 repos
• Defines wire contract mapping Codex events to Capacitor hook routes with vendor path-param routing
• Provides 12 sequential tasks with TDD discipline: failing test → minimal implementation →
 verification
• Includes cross-repo coordination (CLI PR can land first; server PR follows with integration tests)
• Covers CLI dispatcher (codex-hook), plugin install/remove (--codex), status reporting, watcher
 vendor threading, and server-side DTO loosening with vendor-aware handlers

docs/superpowers/plans/2026-05-10-ai-70-codex-hook-surface.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented May 10, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Repo-wide MCP server enabled ✓ Resolved 🐞 Bug ⛨ Security
Description
This PR commits a root .mcp.json that configures an external MCP server
(https://mcp.linear.app/sse). The daemon’s agent orchestration explicitly reads/uses
repo-committed .mcp.json to enable MCP servers, so this change can unexpectedly prompt/enable
third‑party network access for all users of the repo, unrelated to AI-70.
Code

.mcp.json[R1-7]

+{
+  "mcpServers": {
+    "linear-server": {
+      "type": "sse",
+      "url": "https://mcp.linear.app/sse"
+    }
+  }
Evidence
.mcp.json adds an external MCP server; the daemon reads .mcp.json from the worktree and uses it
for MCP server approval, and it explicitly preserves repo-committed .mcp.json entries when
overlaying user config—so committing this file affects runtime behavior for all consumers of the
repo.

.mcp.json[1-8]
src/Kapacitor.Daemon/Services/AgentOrchestrator.cs[1016-1057]
src/Kapacitor.Daemon/Services/AgentOrchestrator.cs[1102-1150]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The PR commits a repo-root `.mcp.json` that configures a third-party MCP server. The daemon/agent orchestration reads `.mcp.json` from the worktree and uses it to enable/approve MCP servers, meaning this repo change can unexpectedly enable third-party network integrations for anyone using the repo.

### Issue Context
This PR is about Codex hooks, not MCP defaults. If the intent is to document an MCP server, it should be provided as an example file or user-local config.

### Fix Focus Areas
- .mcp.json[1-8]
- src/Kapacitor.Daemon/Services/AgentOrchestrator.cs[1016-1057]
- src/Kapacitor.Daemon/Services/AgentOrchestrator.cs[1102-1150]

### Suggested fix
- Remove `.mcp.json` from the repo (or rename to something like `.mcp.json.example` and ensure tooling doesn’t auto-load it).
- If `.mcp.json` must exist in-repo, gate it behind explicit developer opt-in and document it.
- Add a trailing newline to the file if it remains committed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Spawn args not safely quoted ✓ Resolved 🐞 Bug ☼ Reliability
Description
WatcherManager.BuildSpawnArgs interpolates vendor directly into the argument string without
quoting/escaping. If vendor ever contains spaces or crafted values (e.g., future user-controlled
input), the spawned watcher can receive malformed arguments or unintended extra flags.
Code

src/kapacitor/WatcherManager.cs[R40-46]

+        if (parentPid is { } ppid && ppid > 1) {
+            arguments += $" --parent-pid {ppid}";
+        }
+
+        if (vendor != "claude") {
+            arguments += $" --vendor {vendor}";
+        }
Evidence
BuildSpawnArgs constructs a single argument string for ProcessStartInfo and quotes some values
(transcriptPath, cwd) but not vendor; this inconsistency makes the spawn path fragile if
vendor ever deviates from simple tokens like claude/codex.

src/kapacitor/WatcherManager.cs[16-47]
src/kapacitor/WatcherManager.cs[51-72]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Watcher spawning builds a string of CLI arguments and appends `--vendor {vendor}` without quoting/escaping.

### Issue Context
Even if today `vendor` is typically `claude`/`codex`, this is a low-cost hardening change that avoids future breakage if `vendor` becomes user-controlled or gains new values.

### Fix Focus Areas
- src/kapacitor/WatcherManager.cs[16-47]
- src/kapacitor/WatcherManager.cs[51-72]

### Suggested fix
- Quote/escape vendor similarly to cwd:
 - `arguments += $" --vendor \"{EscapeArg(vendor)}\"";`
- Or (better) stop building a single argument string and use `ProcessStartInfo.ArgumentList` to avoid parsing/quoting issues entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. hooks.json parsing can throw ✓ Resolved 🐞 Bug ☼ Reliability
Description
InstallCodexHooks/RemoveCodexHooks and IsCodexHooksInstalled assume hooks[*] entries are
objects and that command is a string; JsonNode indexers and GetValue<string>() will throw on
unexpected shapes. This turns common “user edited hooks.json” cases into silent failures
(install/remove returns false; status incorrectly reports not installed).
Code

src/kapacitor/Commands/PluginCommand.cs[R216-228]

+                foreach (var entry in entries) {
+                    if (entry is null) continue;
+
+                    var hasKapacitorCommand = entry["hooks"] is JsonArray inner && inner.Any(h =>
+                        h?["command"]?.GetValue<string>()?.Contains("kapacitor codex-hook") == true);
+
+                    if (!hasKapacitorCommand) {
+                        preserved.Add(entry.DeepClone());
+                    }
+                }
+
+                preserved.Add((JsonNode)kapacitorEntry);
+                hooks[evt] = preserved;
Evidence
PluginCommand indexes entry["hooks"] and calls GetValue<string>() without verifying node
types; if entries are not objects or command is not a JSON string, the indexer / GetValue throws
and the outer catch returns false. StatusCommand uses the same pattern and will also
throw/misreport.

src/kapacitor/Commands/PluginCommand.cs[181-237]
src/kapacitor/Commands/StatusCommand.cs[106-134]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Codex hooks install/remove and status detection can throw on slightly malformed/unexpected `~/.codex/hooks.json` shapes because they use `JsonNode` indexers and `GetValue<string>()` without type checks.

### Issue Context
These commands read user-controlled JSON. They should be tolerant of unexpected node types (non-object entries, non-string `command` fields) and treat them as non-matches rather than failing the whole operation.

### Fix Focus Areas
- src/kapacitor/Commands/PluginCommand.cs[181-237]
- src/kapacitor/Commands/PluginCommand.cs[245-283]
- src/kapacitor/Commands/StatusCommand.cs[106-134]

### Suggested fix
- Before indexing, ensure shapes:
 - `entry is JsonObject entryObj`
 - `entryObj["hooks"] is JsonArray inner`
 - `hook is JsonObject hookObj` (or `JsonValue`) and safely extract `command`.
- Prefer `JsonValue.TryGetValue<string>(out var cmd)` over `GetValue<string>()`.
- Keep the current try/catch, but avoid exceptions for non-matching shapes so install/remove/status can still succeed when unrelated entries are malformed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Hook payload type crash ✓ Resolved 🐞 Bug ☼ Reliability
Description
CodexHookCommand.Handle only catches JSON parse failures, but then uses GetValue<string>() on
fields like hook_event_name and session_id without type checks. If Codex (or future payload
versions) sends these as non-strings, the hook process will terminate with an unhandled exception.
Code

src/kapacitor/Commands/CodexHookCommand.cs[R34-46]

+        if (node is null) return 0;
+
+        var eventName = node["hook_event_name"]?.GetValue<string>();
+
+        if (string.IsNullOrWhiteSpace(eventName)) return 0;
+
+        // Normalize session_id to dashless GUID, inject home_dir, and tag the
+        // agent host id when running inside a daemon-spawned agent. Mirrors
+        // the Claude hook path in Program.cs but without the disabled-session
+        // and plan_content branches (those are Claude-specific).
+        NormalizeGuidField(node, "session_id");
+
+        node["home_dir"] = PathHelpers.HomeDirectory;
Evidence
After JsonNode.Parse succeeds, GetValue<string>() calls occur outside the try/catch;
JsonNode.GetValue<T> throws when the underlying JSON type doesn’t match T, which would crash the
hook process rather than returning the intended best-effort 0.

src/kapacitor/Commands/CodexHookCommand.cs[22-61]
src/kapacitor/Commands/CodexHookCommand.cs[144-150]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`CodexHookCommand` intends to be best-effort but can still crash on type mismatches because it uses `GetValue<string>()` outside the parse try/catch.

### Issue Context
Hook payloads are external input. Even if Codex currently guarantees types, defensive handling prevents hard failures on schema drift.

### Fix Focus Areas
- src/kapacitor/Commands/CodexHookCommand.cs[22-61]
- src/kapacitor/Commands/CodexHookCommand.cs[144-150]

### Suggested fix
- Replace `node[...].GetValue<string>()` with a safe extractor, e.g.:
 - `static string? TryGetString(JsonNode node, string name)` that checks `node[name] is JsonValue v && v.TryGetValue<string>(out var s)`.
 - Or use `node[name]?.ToString()` but only if you accept non-string JSON values being stringified.
- Consider wrapping the entire `Handle` body (after reading stdin) in a broad try/catch and returning 0 on any exception, consistent with the “never crash the host” intent.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread .mcp.json Outdated
alexeyzimarev and others added 2 commits May 11, 2026 10:21
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>
@alexeyzimarev
alexeyzimarev merged commit c6e1922 into main May 11, 2026
4 checks passed
@alexeyzimarev
alexeyzimarev deleted the capacitor/agent-05e74395770b4a branch May 11, 2026 10:29
alexeyzimarev added a commit that referenced this pull request May 13, 2026
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant