Claude Code Hooks Examples: Automate Linting, Tests, and Deploys
What You’ll Learn
- How Claude Code hooks work in real projects
- Ready-to-use hook examples for linting, tests, and deploy checks
- Which hook events map best to which automation tasks
- How to keep hook automation useful without making it slow or annoying
- What to commit at project scope versus what to keep local
If you are searching for real Claude Code hooks examples, the main thing to understand is that hooks are not just “extra config.” They are the deterministic layer around Claude Code.
That matters because prompts are suggestions. Hooks are behavior.
Claude Code’s official docs show that hooks can run at key lifecycle points like PreToolUse, PostToolUse, Stop, Notification, and SessionStart. That means you can automatically run commands, block risky actions, and enforce project rules without relying on the model to remember every instruction perfectly.
This guide focuses on the most useful hook examples for engineering workflows:
- lint after edits
- run tests before a turn finishes
- block risky deploy commands
- send notifications when long tasks end
Where Claude Code Hooks Live
Claude Code supports hook configuration in settings files.
The most practical locations are:
~/.claude/settings.jsonfor your personal machine-wide hooks.claude/settings.jsonfor project-scoped hooks shared with the repo
If a team should benefit from the automation, I prefer project scope.
Example 1: Run Linting After File Edits
This is the first hook I would add to many repos.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npm run lint"
}
]
}
]
}
}
Why it works well:
- it maps directly to file modification events
- it catches issues immediately
- it removes one repetitive manual step
If your lint command is heavy, replace it with a more targeted script that checks only changed files.
Example 2: Run Typecheck or Tests on Stop
The Stop event is a good fit for cheap validation that should happen before the turn ends.
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "npm run typecheck"
}
]
}
]
}
}
If your project has a fast targeted test suite, you can use that instead:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "npm test -- --runInBand"
}
]
}
]
}
}
The key is to keep the hook fast enough that it stays part of the workflow instead of becoming a source of drag.
Example 3: Block Dangerous Deploy or Shell Commands
If you want Claude Code to avoid specific deploy commands or destructive shell patterns, use PreToolUse on Bash.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block-deploy-risks.sh"
}
]
}
]
}
}
And a simple script:
#!/bin/bash
COMMAND=$(jq -r '.tool_input.command')
if echo "$COMMAND" | grep -Eq 'vercel --prod|git push --force|rm -rf'; then
jq -n '{
decision: "block",
reason: "Blocked risky deploy or destructive command by project hook."
}'
exit 0
fi
exit 0
This is one of the most useful Claude Code hook examples because it turns “please be careful” into something enforceable.
Example 4: Send Notifications When Claude Needs You
The Notification hook is useful for longer tasks or background-like waits.
For example, on macOS you might trigger a notification command when Claude needs input or finishes work. The official docs use this kind of example to demonstrate hook setup.
The specific command varies by OS, but the important point is that hooks can make Claude Code much easier to use in longer sessions.
Example 5: Run a Deploy Checklist Instead of Auto-Deploying
A common temptation is to use hooks to trigger production deploys automatically.
I usually prefer a guardrail step instead.
For example, before allowing a deploy command, run a script that checks:
- current branch
- test status
- presence of required environment variables
- whether the repo is clean enough for release
This is safer than turning hooks into a blind deployment robot.
Best Practices for Claude Code Hooks
If you want your hooks to stay useful, these are the habits that matter most:
Keep commands fast
Hooks that are too slow become friction.
Use hooks for rules, not judgment
Run formatters, tests, and blockers in hooks. Leave architectural judgment to human review.
Prefer project scope for shared workflows
If the automation is part of the team’s process, put it in .claude/settings.json.
Avoid over-automating deployments
Deploy guardrails are good. Blind deploy automation is much riskier.
Final Thought
The best Claude Code hooks examples are not flashy. They are the ones that remove repetitive steps and enforce deterministic rules that matter to the team.
Lint after edits. Typecheck on stop. Block dangerous commands before they run. That small layer of hook automation can make Claude Code feel much more reliable in real engineering workflows.
If you need help designing Claude Code hook systems, AI workflow guardrails, or automation around developer tooling, take a look at my portfolio: voidcraft-site.vercel.app.