diff --git a/.claude/hooks/HOOKS-README.md b/.claude/hooks/HOOKS-README.md index 9a70d30..52ba37a 100644 --- a/.claude/hooks/HOOKS-README.md +++ b/.claude/hooks/HOOKS-README.md @@ -1,32 +1,35 @@ # HOOKS-README contains all the details, scripts, and instructions for the hooks -## Hook Events Overview - [Official 19 Hooks](https://code.claude.com/docs/en/hooks) +## Hook Events Overview - [Official 22 Hooks](https://code.claude.com/docs/en/hooks) Claude Code provides several hook events that run at different points in the workflow: | # | Hook | Description | Options | |:-:|------|-------------|---------| -| 1 | `PreToolUse` | Runs before tool calls (can block them) | `async`, `timeout: 5000` | +| 1 | `PreToolUse` | Runs before tool calls (can block them) | `async`, `timeout: 5000`, `tool_use_id` | | 2 | `PermissionRequest` | Runs when Claude Code requests permission from the user | `async`, `timeout: 5000`, `permission_suggestions` | -| 3 | `PostToolUse` | Runs after tool calls complete successfully | `async`, `timeout: 5000`, `tool_response` | -| 4 | `PostToolUseFailure` | Runs after tool calls fail | `async`, `timeout: 5000`, `error`, `is_interrupt` | +| 3 | `PostToolUse` | Runs after tool calls complete successfully | `async`, `timeout: 5000`, `tool_response`, `tool_use_id` | +| 4 | `PostToolUseFailure` | Runs after tool calls fail | `async`, `timeout: 5000`, `error`, `is_interrupt`, `tool_use_id` | | 5 | `UserPromptSubmit` | Runs when the user submits a prompt, before Claude processes it | `async`, `timeout: 5000`, `prompt` | | 6 | `Notification` | Runs when Claude Code sends notifications | `async`, `timeout: 5000`, `notification_type`, `message`, `title` | | 7 | `Stop` | Runs when Claude Code finishes responding | `async`, `timeout: 5000`, `last_assistant_message`, `stop_hook_active` | | 8 | `SubagentStart` | Runs when subagent tasks start | `async`, `timeout: 5000`, `agent_id`, `agent_type` | | 9 | `SubagentStop` | Runs when subagent tasks complete | `async`, `timeout: 5000`, `agent_id`, `agent_type`, `last_assistant_message`, `agent_transcript_path`, `stop_hook_active` | | 10 | `PreCompact` | Runs before Claude Code is about to run a compact operation | `async`, `timeout: 5000`, `once`, `trigger`, `custom_instructions` | -| 11 | `SessionStart` | Runs when Claude Code starts a new session or resumes an existing session | `async`, `timeout: 5000`, `once`, `agent_type`, `model`, `source` | -| 12 | `SessionEnd` | Runs when Claude Code session ends | `async`, `timeout: 5000`, `once`, `reason` | -| 13 | `Setup` | Runs when Claude Code runs the /setup command for project initialization | `async`, `timeout: 30000` | -| 14 | `TeammateIdle` | Runs when a teammate agent becomes idle (experimental agent teams) | `async`, `timeout: 5000`, `teammate_name`, `team_name` | -| 15 | `TaskCompleted` | Runs when a background task completes (experimental agent teams) | `async`, `timeout: 5000`, `task_id`, `task_subject`, `task_description`, `teammate_name`, `team_name` | -| 16 | `ConfigChange` | Runs when a configuration file changes during a session | `async`, `timeout: 5000`, `file_path`, `source` | -| 17 | `WorktreeCreate` | Runs when agent worktree isolation creates worktrees for custom VCS setup | `async`, `timeout: 5000`, `name` | -| 18 | `WorktreeRemove` | Runs when agent worktree isolation removes worktrees for custom VCS teardown | `async`, `timeout: 5000`, `worktree_path` | -| 19 | `InstructionsLoaded` | Runs when CLAUDE.md or `.claude/rules/*.md` files are loaded into context | `async`, `timeout: 5000` | +| 11 | `PostCompact` | Runs after Claude Code completes a compact operation | `async`, `timeout: 5000`, `trigger`, `compact_summary` | +| 12 | `SessionStart` | Runs when Claude Code starts a new session or resumes an existing session | `async`, `timeout: 5000`, `once`, `agent_type`, `model`, `source` | +| 13 | `SessionEnd` | Runs when Claude Code session ends | `async`, `timeout: 5000`, `once`, `reason` | +| 14 | `Setup` | Runs when Claude Code runs the /setup command for project initialization | `async`, `timeout: 30000` | +| 15 | `TeammateIdle` | Runs when a teammate agent becomes idle (experimental agent teams) | `async`, `timeout: 5000`, `teammate_name`, `team_name` | +| 16 | `TaskCompleted` | Runs when a background task completes (experimental agent teams) | `async`, `timeout: 5000`, `task_id`, `task_subject`, `task_description`, `teammate_name`, `team_name` | +| 17 | `ConfigChange` | Runs when a configuration file changes during a session | `async`, `timeout: 5000`, `file_path`, `source` | +| 18 | `WorktreeCreate` | Runs when agent worktree isolation creates worktrees for custom VCS setup | `async`, `timeout: 5000`, `name` | +| 19 | `WorktreeRemove` | Runs when agent worktree isolation removes worktrees for custom VCS teardown | `async`, `timeout: 5000`, `worktree_path` | +| 20 | `InstructionsLoaded` | Runs when CLAUDE.md or `.claude/rules/*.md` files are loaded into context | `async`, `timeout: 5000`, `file_path`, `memory_type`, `load_reason`, `globs`, `trigger_file_path`, `parent_file_path` | +| 21 | `Elicitation` | Runs when an MCP server requests user input during a tool call | `async`, `timeout: 5000`, `mcp_server_name`, `message`, `mode`, `url`, `elicitation_id`, `requested_schema` | +| 22 | `ElicitationResult` | Runs after a user responds to an MCP elicitation, before the response is sent back to the server | `async`, `timeout: 5000`, `mcp_server_name`, `action`, `content`, `mode`, `elicitation_id` | -> **Note:** Hooks 14-15 (`TeammateIdle` and `TaskCompleted`) require the experimental agent teams feature. Set `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` when launching Claude Code to enable them. +> **Note:** Hooks 15-16 (`TeammateIdle` and `TaskCompleted`) require the experimental agent teams feature. Set `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` when launching Claude Code to enable them. ### Not in Official Docs @@ -34,8 +37,7 @@ The following items exist in the [Claude Code Changelog](https://github.com/anth | Item | Added In | Changelog Reference | Notes | |------|----------|-------------------|-------| -| `Setup` hook | [v2.1.10](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2110) | "Added new Setup hook event that can be triggered via `--init`, `--init-only`, or `--maintenance` CLI flags for repository setup and maintenance operations" | Not listed in official hooks reference page (17 hooks listed, Setup excluded) | -| `InstructionsLoaded` hook | [v2.1.69](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2169) | "Added `InstructionsLoaded` hook event that fires when CLAUDE.md or `.claude/rules/*.md` files are loaded into context" | Not listed in official hooks reference page. This hook is introduced in v2.1.69 and not v2.1.64 | +| `Setup` hook | [v2.1.10](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2110) | "Added new Setup hook event that can be triggered via `--init`, `--init-only`, or `--maintenance` CLI flags for repository setup and maintenance operations" | Not listed in official hooks reference page (21 hooks listed, Setup excluded) | | Agent frontmatter hooks | [v2.1.0](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#210) | "Added hooks support to agent frontmatter, allowing agents to define PreToolUse, PostToolUse, and Stop hooks scoped to the agent's lifecycle" | Changelog only mentions 3 hooks, but testing confirms **6 hooks** actually fire in agent sessions: PreToolUse, PostToolUse, PermissionRequest, PostToolUseFailure, Stop, SubagentStop. Not all 16 hooks are supported. | ## Prerequisites @@ -119,6 +121,9 @@ Edit `.claude/hooks/config/hooks-config.json` for team-wide defaults: "disableSubagentStartHook": false, "disableSubagentStopHook": false, "disablePreCompactHook": false, + "disablePostCompactHook": false, + "disableElicitationHook": false, + "disableElicitationResultHook": false, "disableSessionStartHook": false, "disableSessionEndHook": false, "disableSetupHook": false, @@ -326,7 +331,7 @@ Sends a prompt to a Claude model for single-turn evaluation. The model returns a } ``` -**Supported events:** PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, UserPromptSubmit, Stop, SubagentStop, TaskCompleted. **Command-only events (not supported for prompt/agent types):** ConfigChange, InstructionsLoaded, Notification, PreCompact, SessionEnd, SessionStart, Setup, SubagentStart, TeammateIdle, WorktreeCreate, WorktreeRemove. +**Supported events:** PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, UserPromptSubmit, Stop, SubagentStop, TaskCompleted. **Command-only events (not supported for prompt/agent types):** ConfigChange, Elicitation, ElicitationResult, InstructionsLoaded, Notification, PostCompact, PreCompact, SessionEnd, SessionStart, Setup, SubagentStart, TeammateIdle, WorktreeCreate, WorktreeRemove. ### `type: "agent"` @@ -356,7 +361,7 @@ POSTs JSON to a URL and receives a JSON response, instead of running a shell com } ``` -**Not supported for:** SessionStart, Setup events. Headers support environment variable interpolation with `$VAR_NAME`, but only for variables explicitly listed in `allowedEnvVars`. +**Not supported for:** ConfigChange, Elicitation, ElicitationResult, InstructionsLoaded, Notification, PostCompact, PreCompact, SessionEnd, SessionStart, Setup, SubagentStart, TeammateIdle, WorktreeCreate, WorktreeRemove (command-only events). Headers support environment variable interpolation with `$VAR_NAME`, but only for variables explicitly listed in `allowedEnvVars`. ## Environment Variables @@ -368,6 +373,8 @@ Claude Code provides these environment variables to hook scripts: | `$CLAUDE_ENV_FILE` | SessionStart only | File path for persisting environment variables for subsequent Bash commands. Use append (`>>`) to preserve variables from other hooks | | `${CLAUDE_PLUGIN_ROOT}` | Plugin hooks | Plugin's root directory, for scripts bundled with a plugin | | `$CLAUDE_CODE_REMOTE` | All hooks | Set to `"true"` in remote web environments, not set in local CLI | +| `${CLAUDE_SKILL_DIR}` | Skill hooks | Skill's own directory, for scripts bundled with a skill (since v2.1.69) | +| `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` | SessionEnd hooks | Override SessionEnd hook timeout in milliseconds. Prior to v2.1.74, SessionEnd hooks were killed after 1.5s regardless of configured `timeout`. Now respects the hook's `timeout` value, or this env var if set (since v2.1.74) | | `session_id` (via stdin JSON) | All hooks | Current session ID, received as part of the JSON input on stdin (not an environment variable) | ### Common Input Fields (stdin JSON) @@ -384,7 +391,7 @@ Every hook receives a JSON object on stdin containing these common fields, in ad | `agent_id` | string | Unique subagent identifier. Present when the hook fires inside a subagent context (since v2.1.69) | | `agent_type` | string | Agent type name (e.g. `Bash`, `Explore`, `Plan`, or custom). Present when using `--agent ` flag or inside a subagent (since v2.1.69) | -> **Note:** Hook-specific fields (e.g., `tool_name` for PreToolUse, `last_assistant_message` for Stop) are listed in the Options column of the [Hook Events Overview](#hook-events-overview---official-18-hooks) table above. +> **Note:** Hook-specific fields (e.g., `tool_name` for PreToolUse, `last_assistant_message` for Stop) are listed in the Options column of the [Hook Events Overview](#hook-events-overview---official-19-hooks) table above. ## Hooks Management Commands @@ -426,6 +433,9 @@ Matchers filter which events trigger a hook. Not all hooks support matchers — | `SessionStart` | `source` | `startup`, `resume`, `clear`, `compact` | `"matcher": "startup"` | | `SessionEnd` | `reason` | `clear`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` | `"matcher": "logout"` | | `PreCompact` | `trigger` | `manual`, `auto` | `"matcher": "auto"` | +| `PostCompact` | `trigger` | `manual`, `auto` | `"matcher": "manual"` | +| `Elicitation` | `mcp_server_name` | MCP server name | `"matcher": "my-mcp-server"` | +| `ElicitationResult` | `mcp_server_name` | MCP server name | `"matcher": "my-mcp-server"` | | `ConfigChange` | `source` | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` | `"matcher": "project_settings"` | | `UserPromptSubmit` | — | No matcher support | Always fires | | `Stop` | — | No matcher support | Always fires | @@ -473,9 +483,11 @@ Different hooks use different output schemas for blocking or controlling executi | PreToolUse | `hookSpecificOutput.autoAllow` | `true` — auto-approve future uses of this tool (since v2.0.76) | | PermissionRequest | `hookSpecificOutput.decision.behavior` | `allow`, `deny` | | PostToolUse, PostToolUseFailure, Stop, SubagentStop, ConfigChange | Top-level `decision` | `block` | -| TeammateIdle, TaskCompleted | Exit code 2 only | No JSON decision control | +| TeammateIdle, TaskCompleted | `continue` + exit code 2 | `{"continue": false, "stopReason": "..."}` — JSON decision control added in v2.1.70 | | UserPromptSubmit | Can modify `prompt` field | Returns modified prompt via stdout | | WorktreeCreate | Non-zero exit + stdout path | Non-zero exit fails creation; stdout provides worktree path | +| Elicitation | `hookSpecificOutput.action` + `hookSpecificOutput.content` | `accept`, `decline`, `cancel` — control MCP elicitation response | +| ElicitationResult | `hookSpecificOutput.action` + `hookSpecificOutput.content` | `accept`, `decline`, `cancel` — override user response before sending to server | ### Universal JSON Output Fields diff --git a/.claude/hooks/config/hooks-config.json b/.claude/hooks/config/hooks-config.json index d9dd6a0..a713f32 100644 --- a/.claude/hooks/config/hooks-config.json +++ b/.claude/hooks/config/hooks-config.json @@ -18,5 +18,8 @@ "disableWorktreeCreateHook": false, "disableWorktreeRemoveHook": false, "disableInstructionsLoadedHook": false, + "disablePostCompactHook": false, + "disableElicitationHook": false, + "disableElicitationResultHook": false, "disableLogging": true } diff --git a/.claude/hooks/scripts/hooks.py b/.claude/hooks/scripts/hooks.py index fcfab93..74a3130 100644 --- a/.claude/hooks/scripts/hooks.py +++ b/.claude/hooks/scripts/hooks.py @@ -3,7 +3,7 @@ Claude Code Hook Handler ============================================= This script handles events from Claude Code and plays sounds for different hook events. -Supports all 19 Claude Code hooks: https://code.claude.com/docs/en/hooks +Supports all 22 Claude Code hooks: https://code.claude.com/docs/en/hooks Special handling for git commits: plays pretooluse-git-committing.mp3 @@ -39,6 +39,7 @@ HOOK_SOUND_MAP = { "SubagentStart": "subagentstart", "SubagentStop": "subagentstop", "PreCompact": "precompact", + "PostCompact": "postcompact", "SessionStart": "sessionstart", "SessionEnd": "sessionend", "Setup": "setup", @@ -47,7 +48,9 @@ HOOK_SOUND_MAP = { "ConfigChange": "configchange", "WorktreeCreate": "worktreecreate", "WorktreeRemove": "worktreeremove", - "InstructionsLoaded": "instructionsloaded" + "InstructionsLoaded": "instructionsloaded", + "Elicitation": "elicitation", + "ElicitationResult": "elicitationresult" } # ===== AGENT HOOK EVENT TO SOUND FOLDER MAPPING ===== diff --git a/.claude/hooks/sounds/elicitation/elicitation.mp3 b/.claude/hooks/sounds/elicitation/elicitation.mp3 new file mode 100644 index 0000000..da47e90 Binary files /dev/null and b/.claude/hooks/sounds/elicitation/elicitation.mp3 differ diff --git a/.claude/hooks/sounds/elicitation/elicitation.wav b/.claude/hooks/sounds/elicitation/elicitation.wav new file mode 100644 index 0000000..d54d50e Binary files /dev/null and b/.claude/hooks/sounds/elicitation/elicitation.wav differ diff --git a/.claude/hooks/sounds/elicitationresult/elicitationresult.mp3 b/.claude/hooks/sounds/elicitationresult/elicitationresult.mp3 new file mode 100644 index 0000000..9242228 Binary files /dev/null and b/.claude/hooks/sounds/elicitationresult/elicitationresult.mp3 differ diff --git a/.claude/hooks/sounds/elicitationresult/elicitationresult.wav b/.claude/hooks/sounds/elicitationresult/elicitationresult.wav new file mode 100644 index 0000000..066b0c1 Binary files /dev/null and b/.claude/hooks/sounds/elicitationresult/elicitationresult.wav differ diff --git a/.claude/hooks/sounds/postcompact/postcompact.mp3 b/.claude/hooks/sounds/postcompact/postcompact.mp3 new file mode 100644 index 0000000..307513a Binary files /dev/null and b/.claude/hooks/sounds/postcompact/postcompact.mp3 differ diff --git a/.claude/hooks/sounds/postcompact/postcompact.wav b/.claude/hooks/sounds/postcompact/postcompact.wav new file mode 100644 index 0000000..b00c980 Binary files /dev/null and b/.claude/hooks/sounds/postcompact/postcompact.wav differ diff --git a/.claude/hooks/sounds/precompact/precompact.mp3 b/.claude/hooks/sounds/precompact/precompact.mp3 index 9ab824c..038ce49 100644 Binary files a/.claude/hooks/sounds/precompact/precompact.mp3 and b/.claude/hooks/sounds/precompact/precompact.mp3 differ diff --git a/.claude/hooks/sounds/precompact/precompact.wav b/.claude/hooks/sounds/precompact/precompact.wav index 3c284a8..e7338ad 100644 Binary files a/.claude/hooks/sounds/precompact/precompact.wav and b/.claude/hooks/sounds/precompact/precompact.wav differ diff --git a/.claude/settings.json b/.claude/settings.json index f614b56..b0f3822 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -78,7 +78,7 @@ }, "enableAllProjectMcpServers": true, "disableAllHooks": false, - "hooks": { +"hooks": { "PreToolUse": [ { "hooks": [ @@ -210,6 +210,19 @@ ] } ], + "PostCompact": [ + { + "hooks": [ + { + "type": "command", + "command": "python3 ${CLAUDE_PROJECT_DIR}/.claude/hooks/scripts/hooks.py", + "timeout": 5000, + "async": true, + "statusMessage": "PostCompact" + } + ] + } + ], "SessionStart": [ { "hooks": [ @@ -328,6 +341,32 @@ } ] } + ], + "Elicitation": [ + { + "hooks": [ + { + "type": "command", + "command": "python3 ${CLAUDE_PROJECT_DIR}/.claude/hooks/scripts/hooks.py", + "timeout": 5000, + "async": true, + "statusMessage": "Elicitation" + } + ] + } + ], + "ElicitationResult": [ + { + "hooks": [ + { + "type": "command", + "command": "python3 ${CLAUDE_PROJECT_DIR}/.claude/hooks/scripts/hooks.py", + "timeout": 5000, + "async": true, + "statusMessage": "ElicitationResult" + } + ] + } ] } }