Claude Code Hooks: 5 Automations That Doubled My Productivity
I've been using Claude Code for a few months now. The biggest win isn't how smart it is — it's how obedient. It does whatever you tell it. The problem is you have to keep telling it the same things.
Like formatting code after every edit. Or not touching .env files. Or remembering project conventions after context compression. You can handle all of this manually, sure. But it gets old fast.
That's where Hooks come in.
What Are Hooks
Hooks are shell commands that run at specific points in Claude Code's lifecycle. Think of them like Git hooks, but for your AI coding assistant. Instead of relying on the LLM to remember to do something, you make it deterministic — the hook fires every time, no exceptions.
You can:
- Auto-format files after Claude edits them
- Block dangerous commands before they execute
- Send desktop notifications when Claude needs input
- Re-inject context after the conversation gets compressed
My 5 Daily Hooks
These are the hooks I actually use every day. They go in ~/.claude/settings.json (global) or .claude/settings.json in your project root (project-specific).
1. Desktop Notifications: Stop Staring at the Terminal
This was the first hook I set up. I'd kick off a task in Claude Code, switch to my browser to look something up, and five minutes later realize Claude had been waiting for my input the whole time.
With notifications, I get a system alert the moment Claude finishes or needs permission. Instant context switch.
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
Linux uses notify-send, macOS uses osascript -e 'display notification "Claude Code needs you" with title "Claude Code"', Windows uses PowerShell.
The empty matcher fires on all notification types. You can narrow it down:
permission_prompt: Claude needs you to approve a tool callidle_prompt: Claude finished and is waiting for your next instructionauth_success: Authentication completed
2. Auto-Format: No More Manual Prettier
Claude writes code fast, but the formatting doesn't always match your project's style. I used to manually run prettier --write after every edit. Now it just happens.
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
PostToolUse fires after tool calls. The Edit|Write matcher means it only runs after file edits. jq extracts the file path from the hook's JSON input and passes it to prettier.
The beauty of this: whatever Claude touches gets formatted automatically. No relying on the LLM to "remember" to run prettier. It just works.
3. Protect Sensitive Files: Don't Let Claude Touch .env
I learned this one the hard way. Asked Claude to refactor a project and it "helpfully" reformatted the environment variables in .env — broke the whole thing.
Now I have a PreToolUse hook that checks the target file before any edit:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
The script is straightforward:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
Exit codes:
0: Allow, proceed2: Deny, Claude sees your stderr message and adjusts
This hook saved me multiple times. Once Claude tried to delete node_modules and reinstall to fix a dependency issue — on a monorepo that takes 20 minutes to install. Blocked.
4. Context Injection: Don't Lose Your Mind After Compression
When conversations get long, Claude Code compresses the context window. Important details get lost — project conventions, current task, branch name, whatever you discussed 50 messages ago.
A SessionStart hook with a compact matcher re-injects this info after every compression:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
The reminder file looks like:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
The cat output goes straight into Claude's context. It's like restoring memory after a reset.
Pro tip: use git log --oneline -5 as the command. After compression, Claude sees your last 5 commits and knows where you left off.
5. Auto-Approve Plan Mode: Stop Clicking Confirm
Claude Code's plan mode shows you the execution plan before starting. Every time, you have to click "yes, proceed." Gets tedious.
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
This only auto-approves ExitPlanMode — switching from planning to execution. All other permission prompts (file writes, shell commands) still require manual approval.
Warning: Don't use .* or leave the matcher empty. That auto-approves everything, including arbitrary shell commands. Claude could run rm -rf / and you'd never know.
Hook Lifecycle Events
Those 5 hooks cover the most common events, but Claude Code supports way more:
SessionStart: Session begins or resumesUserPromptSubmit: You submit a prompt, before Claude processes itPreToolUse: Before a tool call (can block it)PostToolUse: After a tool call succeedsPostToolUseFailure: After a tool call failsNotification: When Claude sends a notificationStop: When Claude finishes respondingConfigChange: When config files changeCwdChanged: When the working directory changesFileChanged: When watched files change on diskPreCompact/PostCompact: Before/after context compressionPermissionRequest: When a permission dialog appearsSubagentStart/SubagentStop: Subagent lifecycleSessionEnd: When the session ends
Each event passes JSON data to your script via stdin. Your script can return control instructions via stdout.
Advanced: Prompt and Agent Hooks
Beyond command hooks (shell commands), there are two advanced types:
Prompt Hooks
Use an LLM to make judgments. For example, have another model review your prompt for safety before Claude processes it:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
Good for security audits and quality checks where you need "understanding" rather than "rule matching."
Agent Hooks
Multi-turn conversations with tool access. More powerful than prompt hooks — can call tools, do multi-step reasoning. Still experimental.
Honestly, I don't use these much. Command hooks cover 90% of use cases. But for enterprise Claude Code deployments, prompt hooks for security auditing are valuable.
HTTP Hooks: Webhook Notifications
Instead of running shell commands, hooks can fire HTTP requests directly. Useful for Slack, Feishu, or DingTalk notifications:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
Cleaner than command hooks for simple notifications — no script needed, just declare the HTTP request in config.
Hooks + MCP
Hooks and MCP are separate extension mechanisms, but they work together. If you have an MCP server with code review tools, you can call it with an mcp_tool hook:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
Every time Claude writes a new file, it automatically triggers code review via your MCP service. More reliable than writing "review every file" in CLAUDE.md — hooks execute deterministically.
My Complete Config
Here's my actual project-level .claude/settings.json:
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | |
| 59 | |
Note the 2>/dev/null || true on the format hook — if prettier doesn't support a file type, it fails silently instead of breaking Claude's workflow.
Where to Put Hooks
Three levels:
~/.claude/settings.json: Global, all projects.claude/settings.jsonin project root: Project-specific.claude/settings.local.json: Local, not in git
My recommendation:
- Notifications → global (you always want them)
- Formatting → project-specific (different projects, different formatters)
- File protection → global (every project should protect
.env) - Context injection → project-specific (each project has different conventions)
Debugging Hooks
Hooks that misbehave fail silently. A few debugging tricks:
- Type
/hooksin Claude Code to see registered hooks - Run your command manually to verify it works
- Add
set -xto shell scripts for execution traces - Use
jqto validate your JSON config
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
Gotchas
Path Issues
Hooks don't always run in your project directory. Use absolute paths, or cd in your script.
jq Isn't Universal
The PostToolUse hooks often use jq to parse JSON. Linux usually has it, macOS with Homebrew has it, but some CI environments don't. Check first.
Exit Code 2 vs 1
In hooks, exit 2 means "deny the operation." exit 1 means "the script errored." Don't mix them up.
Parallel Execution
Multiple hooks matching the same event run in parallel, not sequentially. One hook denying doesn't stop the others. The most restrictive result wins: deny > defer > ask > allow.
Hooks vs CLAUDE.md vs Skills
People ask: should I use a hook or write a rule in CLAUDE.md?
The difference is determinism. Writing "run prettier after every edit" in CLAUDE.md means Claude will probably do it. Maybe 90% of the time. Hooks are 100% — if the condition matches, the command runs.
My rule:
- Enforceable rules (file protection, formatting, security) → Hooks
- Guidelines (code style, architecture preferences) → CLAUDE.md
- Reusable workflows (language-specific dev flows, testing strategies) → Skills
All three work together. Hooks handle "must do," CLAUDE.md handles "should do," Skills handle "how to do well."
Wrapping Up
Hooks are one of Claude Code's most underrated features. They're not flashy, but they eliminate a ton of repetitive work and prevent dangerous mistakes.
I'm at the point where if something can be a hook, it is a hook. Claude focuses on what it's good at — understanding requirements, writing code, making architectural decisions. Formatting, file protection, notifications — that's all hooks.
Planning to experiment with prompt hooks for code review next. Will write that up when I have something worth sharing.