Follow Discord
Sweep 22 Oct 2026 · 04:32Z Build v2.1.308 527 read Stable v2.1.308 Latest v2.1.308 Next v2.1.308 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Hooks reference changedhooks

Nearest release: v2.1.299, published 3 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 14 Oct 2026 03:30 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 14 Oct 2026 03:37 UTC.

Upstream edited
Recorded here
Lines+22added
Lines−3removed
From line 777 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits112to this page, all time

#### Hooks that start a background process

The whole hunk

from line 777, old and new numbered
/
lines

This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.

from line 777
777777 
778778Your hook's exit code tells Claude Code whether to continue with the action that triggered the hook, such as a tool call or a prompt. A run that finishes has one of three outcomes:
779779 
780* **Success**: your hook exits 0. Claude Code applies any [JSON output](#json-output) fields your hook printed, and the action goes ahead unless those fields block or deny it.
780* **Success**: your hook exits 0. Claude Code applies any [JSON output](#json-output) fields your hook printed, and the action goes ahead unless those fields block or deny it. [Hooks that start a background process](#hooks-that-start-a-background-process) covers the exception.
781781* **Blocking error**: your hook exits 2. On [events that can block](#exit-code-2-behavior-per-event), Claude Code stops the action.
782782* **Non-blocking error**: your hook exits with any other code, or fails in some other way, such as not starting or printing invalid JSON. The action goes ahead, and on events such as `PreToolUse` you see a `<hook name> hook error` notice in the transcript. If you want a failed hook to block the action, set [`onFailure: "block"`](#block-the-action-when-a-hook-fails).
783783 
from line 874
874874* A timed-out `command`, `http`, or `mcp_tool` hook doesn't block the tool call. The call continues through the normal [permission flow](/docs/en/permissions), so don't count on a stalled hook to act as a gate. To block the call when a `command` or `http` hook times out, set [`onFailure: "block"`](#block-the-action-when-a-hook-fails).
875875* An [Agent SDK callback hook](/docs/en/agent-sdk/hooks) that exceeds its timeout [blocks the tool call](#pretooluse).
876876 
877#### Hooks that start a background process
878 
879If your command hook makes its decision in a background process and exits, a deny that process prints after Claude Code has stopped reading doesn't block the tool call. For a hook that isn't [async](#run-hooks-in-the-background), Claude Code finishes reading the hook's output shortly after the hook's own process exits.
880 
881Print the decision before you start a background process, and redirect that process's stdout and stderr. If your script prints an allow, then starts a background process without redirecting that process's stdout and stderr, Claude Code blocks the tool call. The hook error includes `refusing to honor the suspect capture`.
882 
883This `PreToolUse` hook script prints the decision with `policy-check.sh`, then uploads metrics in the background:
884 
885```bash theme={null}
886#!/bin/bash
887"$CLAUDE_PROJECT_DIR"/.claude/hooks/policy-check.sh || exit $?
888"$CLAUDE_PROJECT_DIR"/.claude/hooks/upload-metrics.sh >/dev/null 2>&1 &
889```
890 
891The rest of the script does this:
892 
893* **`|| exit $?`**: makes the check's exit code the hook's own, so a check that exits 2 to deny still blocks. Otherwise the hook exits with the last line's code, which is 0.
894* **`>/dev/null 2>&1 &`**: runs `upload-metrics.sh` in the background with its output redirected, so it doesn't keep the hook's output open.
895 
896To test the script, make `policy-check.sh` exit 2, then trigger a tool call that the hook matches. The tool call is blocked.
897 
877898#### Block the action when a hook fails
878899 
879900On most events, when a hook fails or times out, Claude Code still carries out the action, so a policy hook with a wrong path or a crashing script lets everything through. To block the action instead, set `"onFailure": "block"` on a `command` or `http` hook. The default value is `"continue"`. Requires Claude Code v2.1.295 or later.
from line 1452
14311452 
14321453An [Agent SDK callback hook](/docs/en/agent-sdk/hooks) on `UserPromptSubmit` that reaches its timeout blocks the prompt with a message naming the hook and the timeout, because a callback there can be acting as a policy gate that must not fail open. The session continues. Before v2.1.208, a callback timeout on that event ended the turn with an execution error.
14331454 
1434If you press `Esc` in the terminal while `UserPromptSubmit` hooks are still checking a prompt, the text you typed goes back into the prompt box.
1435 
14361455#### UserPromptSubmit input
14371456 
14381457In addition to the [common input fields](#common-input-fields), UserPromptSubmit hooks receive the `prompt` field containing the submitted text. Pasted content that collapsed to a `[Pasted text #N]` placeholder arrives expanded in place. In sessions where Claude Code [marks pasted text for Claude](/docs/en/terminal-config#how-claude-treats-pasted-text), that expanded content sits between a `<pasted_content id="…">` line and a `</pasted_content id="…">` line, so account for those lines if your hook parses the prompt.
from line 4051
40324051 
40334052Print the JSON response alone on stdout or on one line of its own:
40344053 
4035* **Alone on stdout**: when the response is the only text on stdout, it can span several lines, such as pretty-printed `jq` output. Spanning several lines requires Claude Code v2.1.295 or later.
4036* **On one line of its own**: an async hook can print other text to stdout when the response fits on one line by itself, for example with `jq -c`.
4037 
4038Claude Code validates that JSON response against the same [output schema](#json-output) as synchronous hooks, and drops any field whose value has the wrong type, such as a `systemMessage` that isn't a string, instead of delivering it. Run with `--debug` to see a warning naming each dropped field.
4039 
4040Async hook completion notifications are suppressed by default. To see them, enable verbose mode with `Ctrl+O` or start Claude Code with `--verbose`.
4041 
4042### Run tests after file changes
4043 
4044This hook starts a test suite in the background whenever Claude writes a file, then reports the results back to Claude when the tests finish. Save this script to `.claude/hooks/run-tests-async.sh` in your project and make it executable with `chmod +x`:
4045 
4046```bash theme={null}
4047#!/bin/bash
4048# run-tests-async.sh
4049 
4050# Read hook input from stdin
4051INPUT=$(cat)
4052FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
4053 
4054# Only run tests for source files
4055if [[ "$FILE_PATH" != *.ts && "$FILE_PATH" != *.js ]]; then
4056 exit 0
4057fi
4058 
4059# Run tests and report results to Claude via additionalContext
4060RESULT=$(npm test 2>&1)
4061EXIT_CODE=$?
4062 
4063if [ $EXIT_CODE -eq 0 ]; then
4064 MSG="Tests passed after editing $FILE_PATH"
4065else
4066 MSG="Tests failed after editing $FILE_PATH: $RESULT"
4067fi
4068jq -nc
4054* **Alone on stdout**: when the response is the only text on stdout, it can span several lines, such as pretty-printed `jq` output. Spanning several lines requires Claude Code v2.1.295 or
Feedback