Claude Code hook events
The reference lists more than thirty events. These are the ones most hooks use; a matcher narrows a hook to certain tools, files or sources.
| Event | When it fires | Common use |
|---|---|---|
SessionStart | A session begins or resumes | Load context, check the environment |
UserPromptSubmit | You submit a prompt, before Claude sees it | Add context, block sensitive prompts |
PreToolUse | Before a tool call runs; can block it | Block dangerous commands, protect files |
PermissionRequest | A tool call needs a permission decision | Auto-approve or deny specific prompts |
PostToolUse | After a tool call succeeds | Format, lint or test edited files |
Notification | Claude Code sends a notification | Desktop alerts when Claude needs you |
SubagentStart, SubagentStop | A subagent starts or finishes | Log or check delegated work |
Stop | Claude finishes responding | Check the task is really done |
PreCompact, PostCompact | Around context compaction | Save or re-inject key context |
FileChanged, CwdChanged | A watched file or the working directory changes | Reload environment, reformat files |
SessionEnd | The session ends | Clean up, write a log |
Where to put hooks
| Location | Scope | Shared |
|---|---|---|
~/.claude/settings.json | All your projects | No |
.claude/settings.json | One project | Yes, commit it |
.claude/settings.local.json | One project | No, gitignored |
| Managed policy settings | The whole organization | Admin-controlled |
Plugin hooks/hooks.json | While the plugin is enabled | Yes, with the plugin |
| Skill or subagent frontmatter | Once the skill is invoked, or while the subagent runs | Yes, in the file |
Claude Code hook examples, step by step
Add each block under the hooks key of a settings file; if the file already has a hooks object, add the event as a sibling key rather than replacing it. Run /hooks to confirm Claude Code loaded it. You can also ask Claude to write the hook for you.
Get a desktop notification when Claude needs you
A
Notificationhook in~/.claude/settings.json. This one usesosascripton macOS; usenotify-sendon Linux or PowerShell on Windows.{ "hooks": { "Notification": [ { "matcher": "", "hooks": [ { "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'" } ] } ] } }Auto-format every file Claude edits
A
PostToolUsehook with anEdit|Writematcher reads the edited path from the JSON on stdin withjqand runs Prettier on it. Put it in.claude/settings.jsonso the team shares it.{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" } ] } ] } }Block a dangerous command
A
PreToolUsehook onBashruns this script. Exit code 2 blocks the call, and what you write to stderr becomes Claude's feedback so it can change course. Exit 0 means no decision, so normal permissions still apply.#!/bin/bash # .claude/hooks/block-drop-table.sh, run as a PreToolUse hook on Bash INPUT=$(cat) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command') if echo "$COMMAND" | grep -q "drop table"; then echo "Blocked: dropping tables is not allowed" >&2 # becomes Claude's feedback exit 2 # 2 = block the action fi exit 0 # no decision: the normal permission flow appliesKeep Claude working until the task is done
A
Stophook of typepromptasks a model whether everything is finished. If it answersok: false, Claude keeps working with thereasonas its next instruction. This is the classic Stop hook example.{ "hooks": { "Stop": [ { "hooks": [ { "type": "prompt", "prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains to be done\"}." } ] } ] } }
How hooks decide what happens
- Input: each hook receives the event as JSON on stdin, such as the tool name and
tool_input, the session ID andcwd. - Exit 0: no objection. For a few events, such as
SessionStartandUserPromptSubmit, plain stdout is added to Claude's context. - Exit 2: block, where the event allows it. Stderr goes back to Claude or to you, depending on the event.
- JSON on stdout: finer control, such as
hookSpecificOutputwith a permission decision,updatedInputto rewrite a tool's input, oradditionalContext. - Other exit codes: usually a non-blocking error, unless the hook sets
onFailure: "block". - Matching hooks for one event run in parallel.
Command, prompt, agent and HTTP hooks
| Type | What runs | Default timeout |
|---|---|---|
command | A shell command | 10 minutes |
http | A POST of the event JSON to a URL; the response body works like command output | 10 minutes |
mcp_tool | A tool on a configured MCP server | 10 minutes |
prompt | A single model call that answers ok or not | 30 seconds |
agent | A subagent that can read files and run tools before deciding (experimental) | 60 seconds |
Hooks vs skills vs CLAUDE.md, and other gotchas
- CLAUDE.md and skills are instructions Claude usually follows; hooks always run. Put anything that must never be skipped in a hook.
PostToolUsecan't undo an action that already ran; usePreToolUseto stop it.Stopfires whenever Claude finishes a response, not only at the end of a task, and not on user interrupts.- Hooks can't run slash commands or call tools themselves; they talk back only through exit codes, stdout, stderr or JSON.
"disableAllHooks": trueturns hooks off; managed hooks still run unless the managed settings disable them too.- Hooks are local to your Claude Code setup. Organization-wide checks on every Claude product are a different feature: Claude inference hooks.
- A PreToolUse hook that filters test output is also one of the best ways to reduce token usage.
Hooks keep Claude Code in line. Crewmark keeps it working.
Hooks are what make an unattended agent safe: formatting, tests and guardrails run every time. Crewmark turns a Claude Code, Codex, DeepSeek Harness or OpenCode session into an AI employee with a role, a goal and working hours, and wakes it on a heartbeat to take the next issue from a board, with your project's hooks in place.
Commit your hooks
.claude/settings.jsonhooks load in the employee's session like in yours, so its edits get formatted and its risky commands blocked.Let the heartbeat start the work
During working hours the employee wakes every 15, 30 or 60 minutes in the same conversation; see how to make Claude Code proactive.
Answer only what needs you
It comments on its issues and messages you when it needs a decision. Read what an AI employee is.
Claude Code hooks FAQ
What are Claude Code hooks?
User-defined commands, HTTP calls or model checks that Claude Code runs automatically at lifecycle events, such as before a tool runs or when Claude finishes. They give deterministic control instead of relying on Claude to remember an instruction.
Where do I configure Claude Code hooks?
Under hooks in ~/.claude/settings.json (all projects), .claude/settings.json (shared with the team) or .claude/settings.local.json (just you). Plugins, skills and subagents can carry hooks too. Run /hooks to see what's loaded.
How do I block a command with a hook?
Use a PreToolUse hook with a Bash matcher. Read the command from the JSON on stdin, and exit with code 2 and a reason on stderr to block it; Claude sees the reason and adjusts.
What is a Stop hook?
A hook on the Stop event, which fires when Claude finishes responding. A prompt-type Stop hook can check whether the task is complete and, if not, send Claude back to work with a reason.
Hooks vs skills: what's the difference?
Skills are instructions and files Claude loads when relevant and usually follows. Hooks are code Claude Code runs every time an event fires, whatever Claude decides.
Why isn't my hook firing?
Check it appears in /hooks, that the event name and matcher are spelled exactly, that the script is executable, and that shell profile output isn't corrupting its JSON. Start Claude Code with a debug log to see what each hook did.
Are Claude Code hooks the same as inference hooks?
No. Claude Code hooks run on your machine for your sessions. Inference hooks are a Claude Enterprise feature that sends every prompt in the organization to a security server before Claude runs.
Checked against the Claude Code docs (hooks guide and hooks reference) on November 6, 2026.