From 2a7458cff61401be5e139add3d520cf7bacc0807 Mon Sep 17 00:00:00 2001 From: scotthavird Date: Fri, 10 Apr 2026 22:18:53 -0400 Subject: [PATCH 1/2] feat: capture all 25 Claude Code hook events (#44) Previously only 12 of 25 hooks were installed. Added the missing 13: - StopFailure, PermissionDenied - TaskCreated, TaskCompleted, TeammateIdle (agent teams) - InstructionsLoaded, ConfigChange, CwdChanged, FileChanged - PostCompact, WorktreeCreate, WorktreeRemove - Elicitation, ElicitationResult (MCP) Also updated README with complete event type table and headless mode documentation including the --bare limitation and --settings workaround. Refs #44 AI-Tool: claude-code AI-Session: d2758b26-b1c4-40fd-94cb-61f497c2110e --- README.md | 32 ++++++++++++++++++++++++++++++++ cmd/install.go | 47 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 5d9fa21..5808e8b 100644 --- a/README.md +++ b/README.md @@ -427,13 +427,45 @@ All events are normalized to this schema: | `prompt_submit` | User submitted a prompt | | `tool_pre` | Before tool execution | | `tool_post` | After tool execution | +| `tool_failure` | Tool execution failed | | `session_start` | Session started | | `session_end` | Session ended | +| `agent_response` | Agent completed a response turn | +| `agent_response_failure` | Response turn ended due to API error | +| `subagent_start` | Subagent spawned | +| `task_created` | Task created (agent teams) | +| `task_completed` | Task completed (agent teams) | +| `teammate_idle` | Agent team teammate went idle | +| `permission_request` | Permission prompt shown | +| `permission_denied` | Tool call denied by auto mode | +| `context_compact` | Context compaction triggered | +| `context_compact_done` | Context compaction completed | +| `worktree_create` | Git worktree created | +| `worktree_remove` | Git worktree removed | +| `instructions_loaded` | CLAUDE.md or rules file loaded | +| `config_change` | Configuration file changed | +| `cwd_changed` | Working directory changed | +| `file_changed` | Watched file changed on disk | +| `mcp_elicitation` | MCP server requested user input | +| `mcp_elicitation_result` | User responded to MCP elicitation | +| `notification` | System notification sent | | `shell_pre` | Before shell command (Cursor) | | `shell_post` | After shell command (Cursor) | | `file_read` | File read operation (Cursor) | | `file_edit` | File edit operation (Cursor) | +### Headless Mode (claude -p) + +PromptConduit hooks work in Claude Code's headless/print mode (`claude -p "..."`) without any changes. Hooks fire and capture events identically in both interactive and non-interactive sessions. + +**`--bare` mode limitation:** When running `claude --bare -p "..."`, Claude Code skips auto-discovery of hooks and settings, so PromptConduit hooks will not fire. To capture events in bare mode, explicitly pass your settings file: + +```bash +claude --bare -p "your prompt" --settings ~/.claude/settings.json +``` + +Note: `--bare` is expected to become the default for `-p` in a future Claude Code release. The `--settings` workaround ensures capture until that changes. + ## Development ### Prerequisites diff --git a/cmd/install.go b/cmd/install.go index 21b01b3..915a523 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -133,21 +133,40 @@ func buildClaudeCodeHooks(hookCmd string) map[string]interface{} { } return map[string]interface{}{ - // Core events + // Session lifecycle + "SessionStart": []map[string]interface{}{{"hooks": makeHook(5000)}}, + "SessionEnd": []map[string]interface{}{{"hooks": makeHook(5000)}}, + // Per-turn events "UserPromptSubmit": []map[string]interface{}{{"hooks": makeHook(5000)}}, - "PreToolUse": makeMatcherHook(5000), - "PostToolUse": makeMatcherHook(5000), - "PostToolUseFailure": makeMatcherHook(5000), // Tool execution failures - "SessionStart": []map[string]interface{}{{"hooks": makeHook(5000)}}, - "SessionEnd": []map[string]interface{}{{"hooks": makeHook(5000)}}, - // Agent events - "Stop": []map[string]interface{}{{"hooks": makeHook(5000)}}, // Agent completes response - "SubagentStart": makeMatcherHook(5000), // Subagent spawned - "SubagentStop": makeMatcherHook(5000), // Subagent completes - // Context and permission events - "PreCompact": makeMatcherHook(5000), // Context compaction - "PermissionRequest": makeMatcherHook(5000), // Permission dialogs - "Notification": makeMatcherHook(5000), // System notifications + "Stop": []map[string]interface{}{{"hooks": makeHook(5000)}}, // Agent completes response + "StopFailure": []map[string]interface{}{{"hooks": makeHook(5000)}}, // Turn ends due to API error + // Tool execution events + "PreToolUse": makeMatcherHook(5000), + "PostToolUse": makeMatcherHook(5000), + "PostToolUseFailure": makeMatcherHook(5000), + "PermissionRequest": makeMatcherHook(5000), + "PermissionDenied": makeMatcherHook(5000), // Auto mode denies a tool call + // Agent and task events + "SubagentStart": makeMatcherHook(5000), + "SubagentStop": makeMatcherHook(5000), + "TaskCreated": makeMatcherHook(5000), + "TaskCompleted": makeMatcherHook(5000), + "TeammateIdle": makeMatcherHook(5000), + // File and configuration events + "InstructionsLoaded": []map[string]interface{}{{"hooks": makeHook(5000)}}, // CLAUDE.md loaded + "ConfigChange": []map[string]interface{}{{"hooks": makeHook(5000)}}, + "CwdChanged": []map[string]interface{}{{"hooks": makeHook(5000)}}, + "FileChanged": []map[string]interface{}{{"hooks": makeHook(5000)}}, + // Context compaction events + "PreCompact": makeMatcherHook(5000), + "PostCompact": makeMatcherHook(5000), + "WorktreeCreate": makeMatcherHook(5000), + "WorktreeRemove": makeMatcherHook(5000), + // MCP events + "Elicitation": makeMatcherHook(5000), + "ElicitationResult": makeMatcherHook(5000), + // Notifications + "Notification": makeMatcherHook(5000), } } From eb6e09dae53eb40fc08a6ed8eba9ad8233402dd2 Mon Sep 17 00:00:00 2001 From: scotthavird Date: Fri, 10 Apr 2026 22:22:03 -0400 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20address=20PR=20review=20findings=20?= =?UTF-8?q?=E2=80=94=20hook=20wrapper=20types=20and=20README=20gap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PreCompact, PostCompact, WorktreeCreate, WorktreeRemove are session- level events with no tool context; use makeHook not makeMatcherHook - Add missing subagent_stop row to README event types table Refs #44 AI-Tool: claude-code AI-Session: d2758b26-b1c4-40fd-94cb-61f497c2110e --- README.md | 1 + cmd/install.go | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5808e8b..d46e830 100644 --- a/README.md +++ b/README.md @@ -433,6 +433,7 @@ All events are normalized to this schema: | `agent_response` | Agent completed a response turn | | `agent_response_failure` | Response turn ended due to API error | | `subagent_start` | Subagent spawned | +| `subagent_stop` | Subagent completed | | `task_created` | Task created (agent teams) | | `task_completed` | Task completed (agent teams) | | `teammate_idle` | Agent team teammate went idle | diff --git a/cmd/install.go b/cmd/install.go index 915a523..cae03f8 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -158,10 +158,10 @@ func buildClaudeCodeHooks(hookCmd string) map[string]interface{} { "CwdChanged": []map[string]interface{}{{"hooks": makeHook(5000)}}, "FileChanged": []map[string]interface{}{{"hooks": makeHook(5000)}}, // Context compaction events - "PreCompact": makeMatcherHook(5000), - "PostCompact": makeMatcherHook(5000), - "WorktreeCreate": makeMatcherHook(5000), - "WorktreeRemove": makeMatcherHook(5000), + "PreCompact": []map[string]interface{}{{"hooks": makeHook(5000)}}, + "PostCompact": []map[string]interface{}{{"hooks": makeHook(5000)}}, + "WorktreeCreate": []map[string]interface{}{{"hooks": makeHook(5000)}}, + "WorktreeRemove": []map[string]interface{}{{"hooks": makeHook(5000)}}, // MCP events "Elicitation": makeMatcherHook(5000), "ElicitationResult": makeMatcherHook(5000),