Claude Code Hooks: Automate the Checks You Run by Hand
TL;DR
You run the same checks by hand every session - format this, run the tests, do not let it delete that. Hooks turn those into automatic rules that fire on the right event. Learn the five hook events (PreToolUse, PostToolUse, UserPromptSubmit, Stop, SessionStart), what each is for, and paste in a starter config so the checks run themselves.
What a hook actually is
A hook is a command that Claude Code runs automatically when a specific thing happens - a tool is about to run, an edit just landed, a session starts. Instead of you remembering to format, test, and check for dangerous commands, you write the rule once and it fires every time. Hooks live in your settings and run locally.
The five events worth knowing
- PreToolUse - runs before a tool executes. Use it to block dangerous commands before they can touch anything (return a non-zero exit to stop the action).
- PostToolUse - runs after a tool succeeds. The classic use is auto-formatting every file the moment it is edited, so your code is always clean.
- UserPromptSubmit - runs when you send a message. Use it to inject context automatically - the current branch, an open ticket, project rules.
- Stop - runs when Claude finishes responding. A good place to run your test suite so you know immediately if something broke.
- SessionStart - runs when a session opens. Use it to brief Claude on the state of things - what is in progress, what changed since last time.
A starter config
Add hooks to your settings file. The shape below shows a formatter on every edit and a guard before Bash runs. Exact field names can vary by version, so run /help or check the current docs to confirm the schema for your install - then adapt this.
json{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "prettier --write $CLAUDE_FILE_PATHS" }
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "./scripts/guard-bash.sh" }
]
}
]
}
}The guard script reads the command about to run and exits non-zero if it matches something you never want to run unattended. That single rule turns 'please be careful' into an actual wall.
How to roll it out
- 1Start with PostToolUse formatting - it is safe, instantly useful, and shows you how hooks fire.
- 2Add a PreToolUse guard for the commands you never want run without you looking.
- 3Add a Stop hook that runs your tests once you have a test suite worth running.
- 4Only then reach for UserPromptSubmit and SessionStart - they are powerful but easier to get wrong.
Common questions
Do hooks run in the cloud or on my machine?
Locally. A hook is just a command Claude Code runs on your machine when an event fires, using your files and your tools. Nothing about the hook itself leaves your computer.
Can a hook actually stop Claude from doing something?
Yes. A PreToolUse hook that exits with a non-zero status blocks the tool action from running. That is exactly how you stop dangerous commands before they touch anything.
What is the difference between a hook and just telling Claude the rule?
A rule in your instructions is a request the model can forget or misapply. A hook is code that runs every single time the event fires, no memory required. Use instructions for judgment, hooks for the checks that must never be skipped.
Will hooks slow down my session?
Only by however long the command takes. A formatter is milliseconds; a full test suite is longer, so put slow checks on the Stop event rather than on every edit. Match the check to how often it needs to run.
Want the hooks starter config, ready to paste in?
Get 650+ plug-and-play skills, MCPs & prompts, plus 5,000+ builders - $9/mo, cancel anytime.
Join the Club