EN JA
Download free

Claude Code Hooks Reference

Checked against the official docs on September 20, 2026

Everything you need on one page when writing a hook: the full event list with the values each matcher accepts, the fields every hook gets on stdin, the settings.json and statusLine shapes, and what exit codes mean. The last section documents the per-session state file that AgentManager derives from these events, for anyone who wants to read it from their own scripts. To generate a config instead of writing one, use the hooks builder.

Hook events

Claude Code currently defines 33 hook events. The third column lists what the matcher field filters on for that event, with example values. Events marked “—” ignore the matcher and always fire. A matcher made of plain names separated by | is an exact match; anything containing regex characters is treated as a JavaScript regular expression. An empty matcher matches everything.

EventFires whenMatcher filters on
Session lifecycle
SessionStartA session starts or resumeshow it started startup|resume|clear|compact|fork
SetupRuns for --init / --maintenance setupsetup trigger init|maintenance
UserPromptSubmitYou submit a prompt, before Claude reads it
UserPromptExpansionA slash command expands into a prompt
StopThe main agent finishes its response
StopFailureThe turn ends because of an API errorerror type rate_limit|overloaded|authentication_failed|billing_error|max_output_tokens|unknown
NotificationClaude Code needs your attention (permission prompt, idle…)notification type permission_prompt|idle_prompt|elicitation_dialog|agent_needs_input
SessionEndThe session terminateswhy it ended clear|resume|logout|prompt_input_exit|other
Tools and permissions
PreToolUseBefore a tool call runs (can block it)tool name Bash|Edit|Write|mcp__.*
PermissionRequestA tool call needs a permission decisiontool name Bash|Edit|Write
PermissionDeniedAuto mode denied a tool calltool name Bash|Edit|Write
PostToolUseAfter a tool call succeedstool name Bash|Edit|Write|mcp__.*
PostToolUseFailureAfter a tool call failstool name Bash|Edit|Write
PostToolBatchA batch of parallel tool calls has all resolved
MessageDisplayAn assistant message is displayed
Subagents and tasks
SubagentStartA subagent is spawnedagent type general-purpose|Explore|Plan
SubagentStopA subagent finishesagent type general-purpose|Explore|Plan
TaskCreatedA task is created
TaskCompletedA task is marked completed
TeammateIdleAn agent-team teammate is about to go idle
Context, config, model
PreCompactBefore the context is compactedtrigger manual|auto
PostCompactAfter compaction completestrigger manual|auto
InstructionsLoadedA CLAUDE.md or rules file is loadedload reason session_start|nested_traversal|path_glob_match|include|compact
ConfigChangeA settings file changes during the sessionconfig source user_settings|project_settings|local_settings|policy_settings|skills
PreModelSwitchBefore a model switch (can block it)target model .*opus.*
PostModelSwitchAfter the session model changestarget model .*opus.*
ElicitationAn MCP server asks you for inputMCP server name my-server
ElicitationResultYou answered an MCP elicitationMCP server name my-server
Workspace
CwdChangedThe working directory changes
DirectoryAddedA directory is added with /add-dirhow it was added slash_command|register_repo_root
FileChangedA watched file changes on diskfile names (literal, | separated) .envrc|.env
WorktreeCreateA git worktree is being created
WorktreeRemoveA git worktree is being removed
Older versions reject the whole file. Claude Code before 2.1.101 ignores a settings file that contains an event name it does not know, which silently disables every hook and permission in that file. Check claude --version before adding recent events such as StopFailure or PostCompact.

What every hook receives on stdin

Each hook command gets one JSON object on stdin. These fields are present for every event; each event adds its own on top (for example tool_name and tool_input on the tool events, notification_type on Notification, error_type on StopFailure, reason on SessionEnd).

FieldMeaning
session_idStable ID for the Claude Code session. Use it as the key for anything you persist.
hook_event_nameThe event name from the table above. Branch on this when one script handles several events.
cwdWorking directory of the session at the time the hook fired.
transcript_pathPath to the session's JSONL transcript.
prompt_idID of the user prompt the current turn belongs to.
scratchpad_dirSession-specific temp directory.
permission_modeCurrent permission mode (default, plan, acceptEdits, bypassPermissions…).
effortCurrent reasoning effort setting.
agent_id, agent_typeSet when the hook fires inside a subagent. Absent for the main agent.

settings.json schema

Hooks live under the top-level hooks key in any of ~/.claude/settings.json (user), .claude/settings.json (project, committed) or .claude/settings.local.json (project, ignored by git). Files merge; a hook defined in several files runs from each.

{
  "hooks": {
    "<EventName>": [
      {
        "matcher": "<optional filter>",
        "hooks": [
          { "type": "command", "command": "<shell command>", "timeout": 600 }
        ]
      }
    ]
  }
}
KeyMeaning
matcherOptional. Filters by the value in the events table. Omit it, or leave it empty, to match everything.
hooks[].typecommand runs a shell command. Other handler types exist (http, mcp_tool, prompt, agent); this page and the builder cover command.
hooks[].commandShell command, run with your user's environment. $HOME and other variables expand.
hooks[].timeoutSeconds before the hook is killed. Default 600; 30 for UserPromptSubmit, PreModelSwitch and PostModelSwitch; 10 for MessageDisplay. All SessionEnd hooks share a 1.5-second budget.

statusLine schema and its stdin

The status line is a separate top-level key with exactly one slot. Its command runs after every assistant response and receives data that hooks never see: context-window usage and rate-limit state.

{
  "statusLine": {
    "type": "command",
    "command": "<shell command>",
    "padding": 0,
    "refreshInterval": 5,
    "hideVimModeIndicator": false
  }
}
stdin fieldMeaning
session_id, versionSession ID and Claude Code version.
model.id, model.display_nameThe model currently in use.
workspace.*Current and project directories.
cost.*Cumulative cost and duration counters for the session.
context_window.used_percentageShare of the context window in use. Also remaining_percentage, total_input_tokens, context_window_size, current_usage.
rate_limits.five_hour, rate_limits.seven_dayEach has used_percentage and resets_at (epoch seconds).

Exit codes

Exit codeEffect
0Success. stdout is shown in verbose mode, or parsed as JSON on events that accept structured output.
2Blocks the action on events that support blocking (PreToolUse, UserPromptSubmit, PermissionRequest, PreModelSwitch, Stop, SubagentStop…). stderr is fed back to Claude as the reason.
otherNon-blocking error. stderr is shown to you; the action continues.

AgentManager session state file

AgentManager's hook reduces the events above to one JSON file per session at ~/.claude/agent-manager/sessions/<session_id>.json. The file is rewritten in place on every event, so treat a parse failure as “read again”, not as corruption. The derivation rules are described in Tracking Claude Code session status with hooks.

FieldTypeMeaning
session_idstringClaude Code session ID. Same as the file name.
statestringOne of waiting, done, processing, idle, error.
waiting_kindstring | nullWhy the session is waiting: approval (permission prompt), plan (plan approval), choice (a question to answer). Null unless state is waiting.
error_reasonstring | nullThe StopFailure error type when state is error: rate_limit, overloaded, authentication_failed, billing_error, max_output_tokens, unknown.
cwdstringWorking directory reported by the latest event.
labelstringDisplay name shown in the app: the last path component of cwd.
host_bundle_id, host_bundle_chainstring | null, arrayBundle ID of the terminal app hosting the session, and the process ancestry used to find it.
iterm_session_id, tmux_pane_idstring | nullIdentifiers used to focus the exact pane when you click the session.
owner_pid, owner_started_atint, stringPID and start time of the claude process. Both are compared to detect a dead session whose PID was reused.
created_at, updated_at, state_sinceISO 8601 stringWhen the file was first written, last written, and when state last changed.
active_subagent_ids, subagent_seen_idsarray of stringSubagents currently running, and every subagent seen this session.
main_stopped, main_waitingboolInternal flags: the main agent has emitted Stop; the main agent is blocked on a prompt.
agent_input_pending_idsarray of stringSubagents that raised agent_needs_input and have not been answered.

A second file, ~/.claude/agent-manager/stats/<session_id>.json, is written by the statusLine pass-through. It carries the context_window, rate_limits and model objects from the status-line stdin unchanged, plus a marker when PreCompact has fired. The status-line command you had before installing is preserved in ~/.claude/agent-manager/statusline-original.json and still runs.

Skip the script, keep the state

AgentManager installs the hook and the status-line pass-through for you, registers the events it needs, and shows every Claude Code session on a live board. Free to use, no account.

macOS 13 or later — the free plan shows up to 2 sessions at once