Skip to main content
Hooks let you run custom logic before or after Claude Code invokes a tool. You can use them to log every tool call, block dangerous operations, auto-approve safe patterns, post results to a webhook, or run an LLM sub-agent to verify intent.

What hooks are

A hook is a shell command, HTTP request, LLM prompt, or agentic verifier attached to a hook event (such as PreToolUse) and optionally filtered by a matcher (such as "Bash"). When the event fires, Claude Code runs all matching hooks in the order they appear in your settings. Hooks are configured under the hooks key in any settings.json file — user, project, or local. See Settings for file locations.

Hook events

The following hook events are available:

Hook types

Each hook entry specifies a type field that determines how it runs.
Runs a shell command. The most common hook type.

Configuration in settings.json

Hooks are nested under the hooks key. Each top-level key is a hook event; its value is an array of matcher objects:
Each matcher object has:

Hook execution flow

1

Tool call initiated

Claude decides to call a tool (e.g. Bash(git status)).
2

PreToolUse hooks run

All matching PreToolUse hooks execute in order. Hook receives the tool name and input as JSON via environment variables.
3

Tool executes

If no hook blocked the call, the tool runs.
4

PostToolUse hooks run

All matching PostToolUse hooks execute. Hook receives the tool output in addition to name and input.

Hook environment

For command hooks, the following environment variables are available:

Blocking a tool call

A PreToolUse hook can block a tool call by exiting with a non-zero exit code. Claude receives an error and does not execute the tool.

Example hooks

Hook sources

Hooks can come from multiple sources, resolved in priority order:
When allowManagedHooksOnly: true is set in managed settings, only hooks from the managed policy file run. User, project, and local hooks are ignored.

Disabling hooks

To disable all hooks and status line execution for a session or globally:
You can also use bare mode (--bare CLI flag or CLAUDE_CODE_SIMPLE=1) to skip hooks entirely along with other non-essential features.