Hooks let you run your own code at key points during a Claude Code session. You can use hooks to log tool usage, send notifications, enforce policies, block dangerous commands, or integrate with external systems — all without modifying Claude’s behavior directly.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/VineeTagarwal-code/claude-code/llms.txt
Use this file to discover all available pages before exploring further.
How hooks work
A hook is a command (or HTTP request, or LLM prompt) associated with a lifecycle event. When the event fires, Claude Code runs your hook and optionally uses its output to influence behavior. For example:- A
PreToolUsehook can block a Bash command before it runs by exiting with code 2 - A
PostToolUsehook can log every file write to an audit trail - A
Notificationhook can send a desktop notification when Claude finishes working - A
Stophook can verify that tests pass before Claude completes a task
Hook events
The following events are available:| Event | When it fires |
|---|---|
PreToolUse | Before Claude runs any tool. Can block the tool by returning a non-zero exit code |
PostToolUse | After a tool succeeds |
PostToolUseFailure | After a tool fails |
Notification | When Claude Code emits a notification (for example, task complete or waiting for input) |
UserPromptSubmit | When you submit a message to Claude |
SessionStart | When a session begins |
SessionEnd | When a session ends |
Stop | When Claude finishes a response. Can block completion by exiting with code 2 |
StopFailure | When a Stop hook blocks completion and Claude retries |
SubagentStart | When a subagent (background task) starts |
SubagentStop | When a subagent completes |
PreCompact | Before context compaction runs |
PostCompact | After context compaction completes |
PermissionRequest | When Claude needs permission to use a tool (headless/async agents only) |
PermissionDenied | When a tool use is denied |
Setup | On Claude Code startup, before the session begins |
TeammateIdle | When a teammate agent becomes idle |
TaskCreated | When a background task is created |
TaskCompleted | When a background task completes |
Elicitation | When Claude requests additional information from the user |
ElicitationResult | After an elicitation request is answered |
ConfigChange | When settings change during a session |
WorktreeCreate | When a git worktree is created |
WorktreeRemove | When a git worktree is removed |
InstructionsLoaded | When CLAUDE.md instruction files are loaded |
CwdChanged | When the working directory changes |
FileChanged | When a file is modified on disk |
Hook configuration
Hooks are configured under thehooks key in any settings file. The structure is:
matcher field uses the same permission rule syntax as tool rules — for example, "Bash(git *)" matches only Bash commands that start with git.
Hook types
Command hook
Runs a shell command. This is the most common hook type.Must be
"command".Shell command to execute. Runs via your default shell (
bash unless overridden by the shell field).Shell interpreter. Defaults to
bash.Permission rule syntax to filter when this hook runs, for example
"Bash(git *)". Only runs if the tool call matches the pattern. Evaluated before spawning the process.Timeout in seconds for this specific command. Overrides the global hook timeout.
Custom message to show in the spinner while the hook is running.
When
true, the hook runs in the background without blocking Claude’s response.When
true, the hook runs once and is automatically removed after execution.HTTP hook
POSTs the hook input as JSON to an HTTP endpoint.Must be
"http".URL to POST the hook input JSON to.
Additional HTTP headers. Values may reference environment variables using
$VAR_NAME syntax. Only variables listed in allowedEnvVars are interpolated.Explicit list of environment variable names that may be interpolated into header values. Required for env var interpolation to work.
Permission rule syntax filter.
Timeout in seconds.
Prompt hook
Evaluates a prompt using a language model. The model’s response determines whether the hook allows or blocks the action.Must be
"prompt".Prompt to evaluate. Use
$ARGUMENTS as a placeholder for the hook input JSON.Model to use for this prompt hook. Defaults to a small fast model.
Permission rule syntax filter.
Timeout in seconds.
Agent hook
Runs an agentic verification using a multi-turn LLM query. The agent must call a structured output tool with{ "ok": true } or { "ok": false, "reason": "..." }.
Must be
"agent".Prompt describing what to verify. Use
$ARGUMENTS placeholder for hook input JSON.Model to use. Defaults to Haiku.
Timeout in seconds. Defaults to 60.
Hook input and output
Input
Claude Code passes context to your hook via stdin as a JSON object. The shape varies by event, but always includes:PostToolUse, the input also includes the tool output:
Output and exit codes
Your hook communicates back to Claude Code via stdout (for structured output) and exit code:| Exit code | Meaning for PreToolUse | Meaning for Stop |
|---|---|---|
0 | Allow the tool to run | Allow completion |
2 | Block the tool; show stdout to Claude as an error | Block completion; Claude retries with stdout as feedback |
| other | Error; tool runs anyway (non-blocking) | Non-blocking error |
PreToolUse hook exits with code 2, the stdout is sent back to Claude as the tool error message. Claude then decides how to proceed based on that message.
Using /hooks to configure hooks
Run /hooks in a Claude Code session to open the hooks management panel. From there you can:
- View all configured hooks grouped by event and source
- Add new hooks interactively
- Remove hooks you no longer want
Example: logging all tool uses
This hook appends every tool use to a log file:Example: blocking dangerous Bash commands
This hook blocksrm -rf commands before they run:
The full hook input JSON is available as stdin, not as
$CLAUDE_TOOL_INPUT. Read it with cat or pipe from stdin: read -r input; echo \"$input\" | jq -r '.tool_input.command'.Example: desktop notification when Claude finishes
This hook sends a desktop notification when Claude completes a response (macOS):notify-send:
Example: verify tests pass before completing
This agent hook verifies that the previous Bash command ran tests and all passed:Hook sources and precedence
Hooks are collected from multiple sources and merged:| Source | File | Display name |
|---|---|---|
| User settings | ~/.claude/settings.json | User |
| Project settings | .claude/settings.json | Project |
| Local settings | .claude/settings.local.json | Local |
| Managed settings | Platform-specific managed path | Managed |
Disabling hooks
To disable all hooks for a session or project, setdisableAllHooks: true in your settings:
allowManagedHooksOnly is set in managed settings, only hooks defined in the managed settings file are run. User, project, and local hooks are ignored.
Enterprise HTTP hook controls
Administrators can restrict which URLs HTTP hooks may target:allowedHttpHookUrls— only HTTP hooks targeting matching URLs are permitted. Supports*as a wildcard. If set to an empty array, no HTTP hooks are allowed.httpHookAllowedEnvVars— allowlist of environment variable names that HTTP hooks may interpolate into headers. If set, a hook’s effectiveallowedEnvVarsis restricted to the intersection with this list.