Hook Configuration
Hook configuration decides which hooks run, when they run, and what happens when one fails.
A matcher picks the events. An if filter narrows them to some tool calls.
The timeout and onFailure fields set limits.
For example, "matcher": "Bash" with "if": "Bash(git push *)" runs a hook only for git push commands.
To disable hooks, set disableAllHooks or allowManagedHooksOnly. You can also remove the entry.
Example
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"if": "Edit(*.ts)",
"command": "bunx prettier --write \"$CLAUDE_PROJECT_DIR\"",
"timeout": 60,
"statusMessage": "Formatting"
}
]
}
]
}
}
The hook runs after an edit or write, but only for .ts files.
It can run for up to 60 seconds.
Matcher Rules
The matcher key is a string on a matcher group. It picks which occurrences of the event run the group.
| Matcher form | Status | What it does | Notes |
|---|---|---|---|
"*", "", or no matcher | Documented: An official docs page names this item. | Matches everything. | The group runs on every occurrence. |
Letters, digits, _, -, space, ,, | only | Documented: An official docs page names this item. | An exact string or a list. | Edit|Write and Edit, Write both match either name. mcp__ alone matches no tool. |
| Any other character | Documented: An official docs page names this item. | A JavaScript regular expression, not anchored. | Claude Code tests it with Reg. Use ^ and $ to match a whole name. |
File and Stop | Documented: An official docs page names this item. | A narrower exact set. | Only letters, digits, _, and | count as exact. A hyphen, space, or comma makes it a regex. |
| A matcher on an event with no matcher | Documented: An official docs page names this item. | Claude Code ignores it silently. | No error. |
Matcher Targets
The event decides what the matcher tests.
| Target | Status | Values | Events |
|---|---|---|---|
| Tool name | Documented: An official docs page names this item. | Bash, Edit|Write, mcp__.. Plugin MCP tools are mcp__. | Pre, Post, Post, Permission, Permission |
| Start source | Documented: An official docs page names this item. | startup, resume, clear, compact, fork. fork needs 2.1.214. | Session |
| CLI flag | Documented: An official docs page names this item. | init, maintenance | Setup |
| End reason | Documented: An official docs page names this item. | clear, resume, logout, prompt_, other | Session |
| Notification type | Documented: An official docs page names this item. | See Events. | Notification |
| Agent type | Documented: An official docs page names this item. | general-, Explore, Plan, or a custom name. A plugin name such as my- contains a colon, so it is a regex. Write ^my-. | Subagent, Subagent |
| Trigger | Documented: An official docs page names this item. | manual, auto | Pre, Post |
| Target model | Documented: An official docs page names this item. | The canonical name of to_, without [1m]. If Claude Code knows no canonical name, every hook runs. | Pre, Post |
| Config source | Documented: An official docs page names this item. | user_, project_, local_, policy_, skills | Config |
| Add source | Documented: An official docs page names this item. | slash_, register_ | Directory |
| File names | Documented: An official docs page names this item. | Literal names split on |. Claude Code filters by base name. The matcher also builds the watch list. | File |
| Error type | Differs: The official docs and the program disagree. The row says how. The docs list 12 values. The program type also includes verification_required. | rate_, overloaded, authentication_, oauth_, account_, billing_, invalid_, model_, server_, max_, cloud_, unknown. | Stop |
| Load reason | Documented: An official docs page names this item. | session_, nested_, path_, include, compact | Instructions |
| Command name | Documented: An official docs page names this item. | Skill or command names. | User |
| MCP server name | Documented: An official docs page names this item. | Names of configured servers. | Elicitation, Elicitation |
| No matcher | Documented: An official docs page names this item. | Always fires. | User, Post, Stop, Teammate, Task, Task, Worktree, Worktree, Message, Cwd |
The if Filter
if is a handler field. It holds one permission rule, such as Bash(git *) or Edit(*.ts).
| Item | Status | What it does | Notes |
|---|---|---|---|
if | Documented: An official docs page names this item. | Runs the handler only when the rule matches the tool call. | Only the five tool events read it. On any other event the hook never runs. You cannot use && or a list. |
| Bash patterns | Documented: An official docs page names this item. | Checked on each subcommand. | Claude Code removes a leading VAR=value. It also checks $() and backticks. If it cannot parse the command, the hook runs. |
| File patterns | Documented: An official docs page names this item. | For example Edit(src/. | Matches only src in the working directory. Use **/ for any depth. This changed in 2.1.214. |
Timeouts
timeout is a number of seconds.
If a hook reaches its timeout, Claude Code cancels it. Claude Code drops its output.
| Item | Status | What it does | Notes |
|---|---|---|---|
Default timeout | Documented: An official docs page names this item. | 600 seconds for command, http, mcp_. 30 for prompt. 60 for agent. | We did not search the program for each default. They come from the docs. |
| Lower defaults | Documented: An official docs page names this item. | 30 seconds on User, Pre, Post. 10 seconds on Message. | For command, http, mcp_. |
timeout under 1 second | Documented: An official docs page names this item. | On a prompt or agent hook, a timeout under 1 counts as 1 second. | Since 2.. The program takes the larger of timeout and 1. Other types are not changed. See Handlers. |
Session budget | Documented: An official docs page names this item. | 1.5 seconds shared by all hooks. | Claude Code raises it to the largest per-hook timeout in settings, up to 60 seconds. Plugin timeouts do not raise it. |
Pre timeout | Documented: An official docs page names this item. | A hook that reaches its timeout blocks the switch. | |
Pre timeout | Documented: An official docs page names this item. | A command, http, or mcp_ hook that reaches its timeout does not block. | Use on to block. An SDK callback that reaches its timeout does block. |
async | Undocumented: Only the program shows this item. It can change without notice. | A first reply of {"async": moves a command hook to the background. It also sets its time limit. | Default 15000 ms. Only the Agent SDK pages name it. See Agent SDK Hooks. |
Failure Handling
A hook fails when it cannot start or reaches its timeout. It also fails when it exits with a code other than 0 or 2, prints invalid JSON, or gets a non-2xx HTTP status.
| Item | Status | What it does | Notes |
|---|---|---|---|
on | Documented: An official docs page names this item. | The default. The action continues after a failure. | command and http handlers. |
on | Documented: An official docs page names this item. | A failure counts as exit 2. | The error text says blocking because on. |
on has no effect | Undocumented: Only the program shows this item. It can change without notice. | On async hooks and on Stop, Subagent, Task, Teammate. | The field text in the program says so. The Hooks Reference does not. |
| Windows without Git Bash | Documented: An official docs page names this item. | A shell-form Pre or Permission hook that fails can block. | Set shell:, or use exec form with on. |
Background process keeps stdout open | Documented: An official docs page names this item. | After an allow, this blocks the call with refusing to honor the suspect capture. | Redirect the output of background child processes. |
CLAUDE_ | Undocumented: Only the program shows this item. It can change without notice. | Your own hooks in user files must succeed. Claude Code drops their grant and rewrite fields. | Program messages: blocking because it is one of the user's own hooks. Affects Pre, Permission, Pre, User, User. |
Environment Variables for Hooks
| Variable | Status | What it does | Notes |
|---|---|---|---|
CLAUDE_ | Documented: An official docs page names this item. | The project root where the session started. | Stays fixed in a worktree. cwd in the input follows Claude. Claude Code also sets it for stdio MCP servers and plugin LSP. |
CLAUDE_, CLAUDE_ | Documented: An official docs page names this item. | The plugin install folder and data folder. | Claude Code replaces them in command and args. It also exports them. |
CLAUDE_ | Documented: An official docs page names this item. | A plugin user option. | Use it in shell form. ${user_ works only in exec form. |
CLAUDE_ | Documented: An official docs page names this item. | A file of export lines that later Bash commands load. | Append with >>. Claude Code sets it for Session, Setup, Cwd, File. It does not set it for PowerShell hooks. |
CLAUDE_ | Documented: An official docs page names this item. | The effort level of the turn. | Also visible in Bash. |
CLAUDE_ | Documented: An official docs page names this item. | "true" in remote web environments. | Unset in the local CLI. |
CLAUDE_ | Documented: An official docs page names this item. | The Remote Control session ID. | Set from 2.1.199 while connected. |
| Inherited environment | Documented: An official docs page names this item. | The parent environment minus OTEL_. | CLAUDE_ strips more. HIPAA sessions drop Anthropic credentials. |
CLAUDE_ | Documented: An official docs page names this item. | Does not exist. | Use Post and to_. |
CLAUDE_ | Documented: An official docs page names this item. | The Session budget. | See Environment Variables. |
CLAUDE_ | Documented: An official docs page names this item. | The most Stop continuations in a row. | Default 8. |
CLAUDE_ | Documented: An official docs page names this item. | Disables the permission_ notification in SDK hosts. | |
CLAUDE_ | Documented: An official docs page names this item. | Stops @ insertion. | |
CLAUDE_ | Documented: An official docs page names this item. | The Git Bash path on Windows. | |
MCP_ | Documented: An official docs page names this item. | How long an MCP hook waits for a server that is still connecting. | |
CLAUDE_ | Undocumented: Only the program shows this item. It can change without notice. | Runs function hooks on the main thread, not in a worker. | The program picks same- or worker. For mods. |
CLAUDE_ | Undocumented: Only the program shows this item. It can change without notice. | Disables hook forwarding in SDK and remote sessions. See Plugins and MCP. | |
DISABLE_ | Undocumented: Only the program shows this item. It can change without notice. | Skips the brief-mode check at the end of a turn. See Features and Toggles. | |
CLAUDE_ | Undocumented: Only the program shows this item. It can change without notice. | Sets how long a resume waits for Session hooks. See Sessions and Storage. |
Settings Keys and Trust
| Item | Status | What it does | Notes |
|---|---|---|---|
hooks | Documented: An official docs page names this item. | The event map. | Merges across levels. |
allowed | Documented: An official docs page names this item. | A URL allowlist for http hooks. | * is a wildcard. An empty array blocks all. Arrays merge across levels. |
http | Documented: An official docs page names this item. | A name allowlist for header values. | Claude Code intersects it with each hook's allowed. Arrays merge. |
| Workspace trust | Documented: An official docs page names this item. | Settings hooks wait for the trust dialog. | - and SDK sessions treat the folder as trusted. Hooks of project subagents need the dialog. |
/ menu | Documented: An official docs page names this item. | A read-only browser of your hooks. | Shows where each one comes from. |
| Debug output | Documented: An official docs page names this item. | claude -- writes hook activity. | CLAUDE_ adds matcher lines. |
The keys disableAllHooks and allowManagedHooksOnly disable hooks or limit them to managed ones. Their rows are on Hooks, Plugins, and Skills Settings.
Errors
Each row is a family of messages. The backticked text is the start that every message in the family shares. A row marked Various gathers the messages of one feature that do not share one start.
| Start of Message | Status | What It Means | Cases |
|---|---|---|---|
Unknown hook decision type, Unknown hook permission, Hook returned incorrect event name, Hook from ${…}, Hook "${…}", Hook input is over the size limit, prompt-, agent-, Session, This hook's matcher cannot be tested, The name that this hook's matcher, invalid hook matcher, hook '${…}' does not exist, script hook:, script hooks are not available, Forked dispatch requires | Undocumented: Only the program shows this item. It can change without notice. | Claude Code refused a hook, or a hook returned a value that is not valid. | Any of these cases applies. The decision type is not one of approve, block (or allow, deny, ask, defer for permission). The output names another event. The hook is prompt-type or agent-type, and the event has no conversation context. The hook needs bash or PowerShell, and Claude Code did not find the shell. The shell would parse the command in shell form again. |
| Various | Undocumented: Only the program shows this item. It can change without notice. | Hooks on this machine. Claude Code refused a request to list, run, or judge a hook on this machine. | Any of these cases applies. The machine disables hooks through its settings or policy. The machine has not settled its plugins yet. The machine has no such hook for that event. The machine runs only command hooks. A device hook template directory is unsafe, or Claude Code found no python3. |
Related Pages
- Hooks: the overview.
- Handlers: the fields of each handler type.
- Input and Output: exit codes and JSON fields.
- Environment Variables: the full variable list.
- Settings Files and Scopes: the settings keys.
Source: Hooks Reference and the settings schema (claude-code-settings.json).