Session, Prompt, and Turn Hook Events
Session Events
These events fire when a session starts or ends, and when its settings, files, or folders change.
SessionStart
Fires when a session starts or resumes.
Interactive starts run it in the background, but the first reply waits for it.
Exit 2 shows stderr to you only.
Handlers: command and mcp_tool (skipped when Claude Code starts).
| Field | Status | Direction | What it does |
|---|---|---|---|
source | Documented: An official docs page names this item. | Input | How the session began: startup, resume, clear, compact, fork. This is the matcher. |
model | Documented: An official docs page names this item. | Input | The active model ID. Can be missing, for example after /. |
agent_ | Documented: An official docs page names this item. | Input | The agent name from --. Optional. |
session_ | Documented: An official docs page names this item. | Input | The custom title. Present only when one exists. |
seconds_, context_, prompt_, estimated_ | Documented: An official docs page names this item. | Input | The cost of a stale resume. Only for resume and fork with an earlier reply. Needs 2.1.251. |
additional | Documented: An official docs page names this item. | Output, in hook | Text before the first prompt. Plain stdout works too. |
initial | Documented: An official docs page names this item. | Output | The first user message. Only in -. From a plugin it works only if the plugin was installed before the start. |
session | Documented: An official docs page names this item. | Output | Sets the title. Works for startup, resume, fork. Same as /. |
watch | Documented: An official docs page names this item. | Output | Absolute paths for File to watch. |
reload | Documented: An official docs page names this item. | Output | Scans the skill and command folders again. Use it after a hook installs skills. |
Setup
Fires for --init-only, or for --init or --maintenance with -p. It does not fire on a normal start.
--init-only also runs SessionStart with startup.
Handler: command only.
| Field | Status | Direction | What it does |
|---|---|---|---|
Setup event | Gated: Works only behind a flag or a server gate. Fires only with the --init-only, --init, or --maintenance CLI flags. | Event | See the flags above. |
trigger | Documented: An official docs page names this item. | Input | init or maintenance. It is also the matcher. |
additional | Differs: The official docs and the program disagree. The row says how. Docs: Claude Code drops all JSON fields of Setup on every exit code. The program output schema lists additionalContext for Setup. | Output | Treat it as not delivered. A probe with -- found it never reached the model request (Probes). |
CLAUDE_ | Documented: An official docs page names this item. | Environment | Persists environment variables, as for Session. |
SessionEnd
Fires when a session ends.
The budget is 1.5 seconds for all hooks together. Exit 2 shows stderr to you. Claude Code drops JSON.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
reason | Documented: An official docs page names this item. | Input | Why it ended: clear, resume, logout, prompt_, other. This is the matcher. |
InstructionsLoaded
Fires when CLAUDE.md or a .claude/rules/*.md file loads.
It runs async and has no decision. It does not fire for an AGENTS.md file read directly.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
file_ | Documented: An official docs page names this item. | Input | The absolute path of the file. |
memory_ | Documented: An official docs page names this item. | Input | User, Project, Local, or Managed. |
load_ | Documented: An official docs page names this item. | Input | session_, nested_, path_, include, compact. This is the matcher. |
globs, trigger_, parent_ | Documented: An official docs page names this item. | Input | Extra data for lazy and include loads. globs is only for path_. |
ConfigChange
Fires when a settings, managed policy, or skill file changes.
It does not fire for server-managed or MDM changes.
Exit 2 or decision: "block" stops the change, except for policy_settings.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
source | Documented: An official docs page names this item. | Input | user_, project_, local_, policy_, skills. This is the matcher. |
file_ | Documented: An official docs page names this item. | Input | The changed file. Optional. |
decision, reason | Documented: An official docs page names this item. | Output | block keeps the old settings. Nobody sees reason. Claude Code drops system and continue. |
CwdChanged
Fires when a shell command in the main conversation changes the directory.
It has no matcher and cannot block.
Claude Code clears CLAUDE_ENV_FILE at the next event.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
old_, new_ | Documented: An official docs page names this item. | Input | The two directories. |
watch | Documented: An official docs page names this item. | Output, in hook | Replaces the dynamic watch list. An empty array clears it. system shows as a short notice. Claude Code drops continue. |
FileChanged
Fires when a watched file changes on disk.
A file watcher drives it, not tool calls.
The matcher names the files to watch, and Claude Code filters by base name.
It cannot block.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
file_ | Documented: An official docs page names this item. | Input | The absolute path. |
event | Documented: An official docs page names this item. | Input | change, add, or unlink. |
watch | Documented: An official docs page names this item. | Output, in hook | Replaces the dynamic watch list. The watcher starts only when something names a file. |
DirectoryAdded
Fires after /add-dir, or after the SDK register_repo_root request.
It runs in the background with a 600 second timeout.
It does not fire for --add-dir, /permissions, or a directory Claude Code already knows.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
directory | Documented: An official docs page names this item. | Input | The absolute path. |
source | Documented: An official docs page names this item. | Input | slash_ or register_. This is the matcher. system goes to Claude for slash_ and to the debug log otherwise. |
Prompt and Turn Events
These events fire around a turn: when you send a prompt, while text shows, when Claude Code sends a notification, and when Claude stops.
UserPromptSubmit
Fires when you submit a prompt, before Claude reads it.
It has no matcher. It also fires for scheduled tasks, background subagent reports, and messages from other sessions.
The default timeout is 30 seconds.
Exit 2 blocks the prompt. Claude Code adds plain stdout as context.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
prompt | Documented: An official docs page names this item. | Input | The text. A typed / arrives as typed, not expanded. Pasted text arrives expanded. |
source | Undocumented: Only the program shows this item. It can change without notice. | Input | Who made the prompt: user, sdk, system, loop_, schedule_, poll_. May be missing. |
session_ | Documented: An official docs page names this item. | Input | The custom title, only when one exists. |
decision, reason | Documented: An official docs page names this item. | Output | block stops the prompt. You see reason. Claude Code does not add it to context. |
additional | Documented: An official docs page names this item. | Output, in hook | Context placed next to the prompt. |
session | Documented: An official docs page names this item. | Output | Sets the session title. |
suppress | Documented: An official docs page names this item. | Output | Omits the prompt text from the block message. Otherwise the block message ends with Original prompt:. Claude Code writes the message to the transcript. |
UserPromptExpansion
Fires when a typed command expands into a prompt.
The matcher is command_name.
It covers typing /skill, which skips PreToolUse.
Exit 2 blocks. Plain stdout is context.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
expansion_ | Documented: An official docs page names this item. | Input | slash_ or mcp_. |
command_, command_, prompt | Documented: An official docs page names this item. | Input | The command parts and the raw line. |
command_ | Documented: An official docs page names this item. | Input | Where the command came from, such as plugin. Optional. |
decision, reason | Documented: An official docs page names this item. | Output | block stops the expansion. |
additional, suppress | Documented: An official docs page names this item. | Output, in hook | As in User. |
MessageDisplay
Fires while assistant text streams, once for each batch of finished lines.
It has no matcher. The timeout is 10 seconds.
It only changes what you see. The transcript and Claude keep the original.
In -p mode it runs once with the full text.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
turn_, message_ | Documented: An official docs page names this item. | Input | UUIDs of the turn and the message. message_ is stable for the whole message. |
index, final | Documented: An official docs page names this item. | Input | The position of the batch. final is true on the last one. |
delta | Documented: An official docs page names this item. | Input | The new lines. Whole lines, except in the final batch. |
display | Documented: An official docs page names this item. | Output, in hook | Text shown in place of delta. If the hook fails, the original shows. Claude Code drops system and continue. |
Notification
Fires when Claude Code sends a notification.
The matcher is the notification type.
It runs even if desktop notifications are off.
Claude Code ignores the exit code and stderr, but terminalSequence still works.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
message, title, notification_ | Documented: An official docs page names this item. | Input | The text, an optional title, and the type. |
permission_ | Documented: An official docs page names this item. | Type | A prompt waited about 6 seconds. Seen live in the interactive screen (2.1.305) with the message Claude needs your permission. |
idle_ | Documented: An official docs page names this item. | Type | The session was idle for about 60 seconds. Both depend on typing and running agents. Seen live: the message was Claude is waiting for your input, about 60 seconds after the turn ended (the config key message sets the 60 seconds, default 60000). |
auth_, elicitation_, elicitation_, elicitation_, elicitation_ | Documented: An official docs page names this item. | Type | Auth finished, and the steps of an MCP question. The two dialog types wait 6 seconds. Seen live in the interactive screen: all four elicitation_ values (messages Claude Code needs your input for the two dialogs, Elicitation response for server "probe":, and MCP server "probe" confirmed elicitation el-). auth_ needs a login and was not seen. |
agent_, agent_ | Documented: An official docs page names this item. | Type | Background session events in agent view. agent_ for a teammate setup question needs 2.1.248. agent_ was seen live for the auto mode classifier billing notice (message Auto mode has a classifier billing notice to acknowledge) that shows the first time auto mode runs with a custom base URL. agent_ was not seen (it needs a background session). |
quota_, quota_, quota_ | Documented: An official docs page names this item. | Type | Usage limit wait events. Need 2.1.234. Not seen live: they need a login. |
plugin_ | Undocumented: Only the program shows this item. It can change without notice. | Type | The mod call $. sends it. Seen live: the hook got message, title, and notification_, even with no notification channel. |
auth_ | Undocumented: Only the program shows this item. It can change without notice. | Type | Sent after the OAuth token exchange, when saving the credentials fails. Not seen live. Message: Claude Code login needs attention:, or Claude Code login needs attention:. |
worker_ | Undocumented: Only the program shows this item. It can change without notice. Gated: Works only behind a flag or a server gate. Set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 or use --agent-teams | Type | Sent by the team lead's inbox poller when a teammate asks for permission. Needs agent teams and at least one teammate. It fires only when the lead is idle and shows no dialog. Seen live: the message was A subagent needs permission for Bash, with no title. A normal permission_ followed when the dialog showed. The message <worker> needs network access to <host> comes from the program and was not run. |
push_ | Undocumented: Only the program shows this item. It can change without notice. Gated: Works only behind a flag or a server gate. The PushNotification tool is behind a server-side flag that is off by default | Type | Sent with the message from the Push tool. Skipped when the config is off (config_) or the user is present (user_). Setting CLAUDE_ disables the presence check. Seen live: the input had the common fields, message, and notification_, with no title. When skipped, the hook does not fire (from the program, not run). |
computer_ | Undocumented: Only the program shows this item. It can change without notice. Gated: Works only behind a flag or a server gate. Needs a Pro or Max plan, a server flag, and not HIPAA | Type | Not seen live. Message when computer use starts: Claude is using your computer · press Esc to stop (or Ctrl+C). |
computer_ | Undocumented: Only the program shows this item. It can change without notice. Gated: Works only behind a flag or a server gate. Needs a Pro or Max plan, a server flag, and not HIPAA | Type | Not seen live. Sent at the end of a turn that sent computer_. Message when computer use ends: Claude is done using your computer. |
Seen live: push_notification and worker_permission_prompt. See Probes for how we triggered them.
These come from the program and were not seen live:
auth_storage_failurefires only after a real OAuth login. A probe cannot point the token request at a local server. On macOS the save goes to the real keychain, so we did not run it.computer_use_enterandcomputer_use_exitfire when the program takes the computer-use lock. The program seems to take it only for tools that act on the screen, so we did not run this. The probe enabled the built-in computer-use server, but its listing and wait calls did not fire the hook.- We did not run the network form of
worker_permission_prompt.
The program also lists model_refusal_fallback as a type. The probe found no code that sends a Notification with it (a reading of the program, not a live result). The same name is a system message subtype (see Stream JSON) for a retry on a fallback model after a refusal. The program runs Notification hooks for each type that it sends before it chooses a notification channel.
Stop
Fires when the main agent finishes. It does not fire on a user interrupt.
It has no matcher.
Exit 2 or decision: "block" keeps Claude working.
The cap is 8 continuations in a row. CLAUDE_CODE_STOP_HOOK_BLOCK_CAP sets it.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
stop_ | Documented: An official docs page names this item. | Input | true when a stop hook already continued the turn. Check it to avoid loops. |
last_ | Documented: An official docs page names this item. | Input | The text of the final reply. Use it instead of the transcript. |
background_ | Documented: An official docs page names this item. | Input | Tasks still running. Each has id, type, status, description, and some of command, agent_, server, tool, name by type. Claude Code cuts text at 1000 characters. |
session_ | Documented: An official docs page names this item. | Input | Scheduled wakeups. Each has id, schedule, recurring, prompt. |
decision, reason | Documented: An official docs page names this item. | Output | block stops Claude from stopping. You must give reason. It becomes the next instruction. |
additional | Documented: An official docs page names this item. | Output, in hook | Feedback that continues the turn. Claude Code labels it Stop hook feedback, not an error. |
StopFailure
Fires instead of Stop when the turn ends on an API error.
The matcher is error.
Claude Code ignores output and the exit code, but terminalSequence works.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
error | Differs: The official docs and the program disagree. The row says how. The docs list 12 values. The type SDKAssistantMessageError also includes verification_required. | Input | The error type. See the list on Configuration. |
error_ | Documented: An official docs page names this item. | Input | More detail. Optional. |
last_ | Documented: An official docs page names this item. | Input | The rendered API error text. It is not Claude's own words, unlike in Stop. |
Related Pages
- Hook Events: all 33 events and where each one is documented.
- Input and Output: common fields, decisions, and exit codes.
- Configuration: matchers and timeouts.