Hook events
Each hook is keyed by an event name. The full list of available events is:| Event | When it fires |
|---|---|
PreToolUse | Before a tool call is executed |
PostToolUse | After a tool call completes successfully |
PostToolUseFailure | After a tool call fails |
Notification | When Claude Code emits a user-visible notification |
UserPromptSubmit | When the user submits a prompt |
SessionStart | At the start of a new session (also fires on resume, clear, compact) |
SessionEnd | When the session ends |
Stop | When Claude finishes a response turn |
StopFailure | When a response turn ends in error |
SubagentStart | When a sub-agent is spawned |
SubagentStop | When a sub-agent finishes |
PreCompact | Before context compaction |
PostCompact | After context compaction |
PermissionRequest | When a permission prompt is about to be shown |
PermissionDenied | When a permission request is denied |
Setup | Early one-time setup phase |
TeammateIdle | When a teammate agent becomes idle |
TaskCreated | When a background task is created |
TaskCompleted | When a background task completes |
Elicitation | When an elicitation is triggered |
ElicitationResult | When an elicitation result is received |
ConfigChange | When the configuration changes |
WorktreeCreate | When a git worktree is created |
WorktreeRemove | When a git worktree is removed |
InstructionsLoaded | When CLAUDE.md instructions are loaded |
CwdChanged | When the working directory changes |
FileChanged | When a watched file changes |
Configuring hooks
Hooks are defined in ahooks key in any Claude Code settings file:
- User settings:
~/.claude/settings.json - Project settings:
.claude/settings.json - Local settings:
.claude/settings.local.json - Managed settings:
/etc/claude-code/managed-settings.json(Linux) or MDM profile (macOS/Windows)
hooks object is a map from event name to an array of matcher objects. Each matcher optionally filters by a string pattern (e.g., a tool name) and contains an array of hook commands.
/hooks command inside a Claude Code session.
Hook types
Claude Code supports four hook types.command — shell command
command — shell command
Runs a shell command. The hook input is passed as JSON on stdin.
Exit codes for
| Field | Description |
|---|---|
command | Shell command string to execute |
shell | "bash" (default) or "powershell" |
timeout | Timeout in seconds (positive number) |
if | Permission rule syntax filter (e.g., "Bash(git *)") — hook runs only when the tool call matches |
statusMessage | Custom spinner message shown while the hook runs |
once | Run once and remove after first execution |
async | Run in the background without blocking |
asyncRewake | Run in background; exit code 2 wakes the model with a blocking error |
command hooks:0— success, execution continues2— blocks the operation and surfaces stderr to Claude as an error- Any other non-zero — shows stderr to the user only (non-blocking)
prompt — LLM prompt hook
prompt — LLM prompt hook
Evaluates a prompt with an LLM. Use
$ARGUMENTS in the prompt string to receive the hook input JSON.| Field | Description |
|---|---|
prompt | Prompt string; use $ARGUMENTS to inject hook input JSON |
model | Model to use (e.g., "claude-sonnet-4-6"); defaults to the small fast model |
timeout | Timeout in seconds |
if | Permission rule syntax filter |
statusMessage | Custom spinner message |
once | Run once and remove |
agent — agentic verifier hook
agent — agentic verifier hook
Runs a multi-turn LLM agent to verify a condition. The agent must call a structured output tool with
{ok: boolean, reason?: string}.| Field | Description |
|---|---|
prompt | Description of what to verify; use $ARGUMENTS for hook input JSON |
model | Model to use; defaults to Haiku |
timeout | Timeout in seconds (default 60) |
if | Permission rule syntax filter |
statusMessage | Custom spinner message |
once | Run once and remove |
http — HTTP webhook hook
http — HTTP webhook hook
POSTs the hook input JSON to a URL. Useful for sending events to external systems.
| Field | Description |
|---|---|
url | URL to POST the hook input JSON to |
headers | Additional headers; values may reference $VAR_NAME env vars |
allowedEnvVars | Explicit list of env var names allowed for interpolation in headers |
timeout | Timeout in seconds |
if | Permission rule syntax filter |
statusMessage | Custom spinner message |
once | Run once and remove |
Matcher patterns
Thematcher field on a hook entry filters which invocations trigger the hook. It is matched against values relevant to the event—most often the tool name for PreToolUse / PostToolUse events.
The if field inside an individual hook command provides finer-grained filtering using permission rule syntax (e.g., "Bash(git *)" or "Read(*.ts)"). A hook with an if condition only runs when the tool call matches that pattern.
Environment variables in hook scripts
Shell command hooks (type: "command") inherit the full process environment plus the following additional variables:
| Variable | Description |
|---|---|
CLAUDE_PROJECT_DIR | Absolute path to the project root directory |
CLAUDE_ENV_FILE | Path to a .sh file your hook can write export KEY=VALUE lines into, injected into subsequent Bash tool commands. Set for SessionStart, Setup, CwdChanged, and FileChanged events only. |
CLAUDE_PLUGIN_ROOT | Plugin or skill base directory (when the hook comes from a plugin or skill) |
CLAUDE_PLUGIN_DATA | Plugin data directory (when the hook comes from a plugin) |
CLAUDE_PLUGIN_OPTION_<KEY> | Plugin configuration option values (uppercased) |
When running inside GitHub Actions with
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB set, sensitive credentials (e.g., ANTHROPIC_API_KEY, AWS_SECRET_ACCESS_KEY) are stripped from the hook subprocess environment to prevent prompt-injection exfiltration.Example configurations
Use cases
- Audit logging — record every tool call to a file or SIEM system
- Policy enforcement — block specific commands (exit code 2 surfaces an error to Claude)
- Notifications — send Slack or webhook messages when sessions complete
- Environment setup — load
.envrcor inject credentials at session start viaCLAUDE_ENV_FILE - Quality gates — use
agenthooks to verify tests pass before allowing commits
Security considerations
allowManagedHooksOnly— when set totruein managed settings, only hooks from managed settings (MDM/managed-settings.json) run. User, project, and local hooks are silently ignored. This lets IT administrators restrict hook execution to approved scripts.disableAllHooks— setting this totruein any settings file disables all hooks and status line execution.allowedHttpHookUrls— an allowlist of URL patterns HTTP hooks may target. When set, HTTP hooks with non-matching URLs are blocked. Supports*as a wildcard (e.g.,"https://hooks.example.com/*").httpHookAllowedEnvVars— restricts which env vars HTTP hooks may interpolate into headers; the effective set is the intersection of this list and each hook’s ownallowedEnvVars.- Hook scripts should validate their inputs. The JSON input is controlled by Claude Code but may reflect user-supplied content.