How do Claude Code hooks work?
Hooks are shell commands Claude Code runs automatically before or after its actions—like auto-formatting after every file edit or running lint before a commit. You define them in settings.json under events such as PreToolUse or PostToolUse, with a matcher for which tool triggers them. A hook can also filter or block an action, giving you deterministic control.
Why — the first-principles explanation
An AI is probabilistic—it usually does what you want, but not always. Hooks make certain steps deterministic. Instead of hoping Claude remembers to format your code, you attach a hook that runs the formatter every single time, guaranteed, because it's a plain shell command the harness executes, not a suggestion the model might skip.
Hooks fire on events in Claude Code's loop. The main ones are PreToolUse (before Claude runs a tool like Bash or Edit) and PostToolUse (after). Each hook has a matcher that says which tool it applies to—for example, only run before `Bash` commands. When the event fires and the matcher matches, Claude Code runs your command, passing the action's details as JSON on standard input.
The powerful part is that a hook can change the outcome. A PreToolUse hook can inspect the command Claude is about to run and rewrite it, allow it, or block it by returning a small JSON decision. That's how you enforce policy—say, filtering a test command to show only failures, or refusing edits to protected files. Because it's just a script, a hook can do anything your shell can: format, lint, log, notify, or gate. You're wiring guaranteed behavior into Claude's workflow.
An example that makes it click
Think of a factory conveyor belt with sensors. Every time a box (Claude's action) passes a checkpoint, a sensor (the hook) does its job automatically—one stamps the box, another weighs it and rejects any that are too heavy. Claude doesn't have to remember to stamp; the sensor always fires. A PreToolUse hook is the sensor before the box moves; PostToolUse is the one right after. And the reject arm—that's a hook blocking an action it doesn't like.
How to do it
- Open your settings file (`~/.claude/settings.json` for global, or project settings).
- Add a `hooks` section with an event key such as `PreToolUse` or `PostToolUse`.
- Set a `matcher` (e.g. `"Bash"` or `"Edit"`) to choose which tool triggers the hook.
- Under `hooks`, add a `command` entry pointing to your script or inline shell command.
- Make any script executable (`chmod +x`), then test by running an action that matches the trigger.
- For gating, have the hook return JSON with a permission decision (allow/deny) or an updated input.
Key facts
- Hooks are shell commands Claude Code runs before or after its actions (as of 2026-07).
- Common events include PreToolUse (before a tool runs) and PostToolUse (after).
- A matcher selects which tool triggers the hook, e.g. Bash or Edit.
- Claude Code passes the action details to the hook as JSON on standard input.
- A PreToolUse hook can allow, block, or rewrite an action by returning a JSON permission decision.
Anthropic's agentic coding tool that works in your terminal.
Affiliate link — we may earn a commission at no cost to you.▶ The 60-second explainer (script)
How do Claude Code hooks work? Hooks are shell commands that run automatically before or after Claude's actions—and they solve a real problem. An AI usually does what you ask, but not always. Hooks make certain steps guaranteed, because they're plain scripts the system runs, not suggestions the model might forget. They fire on events. The two big ones are PreToolUse—before Claude runs a tool like Bash or Edit—and PostToolUse, right after. Each hook has a matcher that picks which tool triggers it. So you can auto-format code after every edit, or run lint before every commit, every single time. The really powerful part: a PreToolUse hook can inspect what Claude's about to do and allow it, block it, or rewrite it—by returning a little JSON decision. That's how you enforce rules, like refusing edits to protected files or trimming test output to just the failures. You set them up in settings dot json, with an event, a matcher, and a command. Because it's just a script, a hook can do anything your shell can.
What authoritative sources say
People also ask
What can I do with a Claude Code hook?
Auto-format after edits, run lint before commits, filter noisy output, log actions, send notifications, or block risky actions.
Where do I configure hooks?
In your settings.json (global at ~/.claude/settings.json or per project), under a `hooks` section keyed by event.
What are PreToolUse and PostToolUse?
Events that fire before and after Claude runs a tool. PreToolUse can also allow, block, or rewrite the action.
Can a hook stop Claude from doing something?
Yes. A PreToolUse hook can return a JSON decision that denies the action or replaces its input.