Introduction
If you find yourself manually running the same setup and shutdown commands every time you open a terminal, setting up Claude code hooks will permanently reclaim that lost time. I used to waste ten minutes at the start of every session pulling the latest data files, checking my branch, and loading the right context, only to repeat a different set of checks at the end. Multiply that across a month, and it adds up to several days wasted on repetitive tasks that I should never have been doing.
A hook is essentially a script that fires automatically when the system reaches a defined point in its work—whether that is before a tool runs, after a task completes, or when a session initiates. Once you set them up, the administrative busywork around your actual work stops being your problem. This post is the practical reference I wish I had three months ago, covering the nine hook types, the traps to avoid, and a copy-paste list to help you start immediately.
Key Takeaways
- Claude code hooks fire scripts at fixed events (before a tool, after a tool, at session start, on notification, on stop) so the same setup and teardown work runs every time without you remembering it.
- There are nine hook types: SessionStart, SessionEnd, UserPromptSubmit, PreToolUse, PostToolUse, Notification, Stop, SubagentStop, and PreCompact.
- Useful Claude code hooks include auto-logging tool calls, blocking dangerous commands before they run, pulling fresh data at session start, and sending a phone notification when Claude needs input.
- Hooks live in settings.json under the “hooks” key. Each event takes an array of matchers, and each matcher runs one or more shell commands.
- A Claude Code Hooks notification setup routes Claude’s attention requests straight to Telegram, Slack, or your phone, so you stop sitting and watching the terminal.
- Best practice: keep hooks fast (under two seconds), log to a file you can grep later, and never put credentials in the hook command itself.
- Hooks plug into a bigger picture. Once Claude knows what to do before and after every task, you stop being the operator and start being the architect.
What Claude Code Hooks Actually Are
A Claude Code hook is a shell command the Claude Code harness runs automatically at a defined point in your session. You write the command. Claude calls it. The output and exit code feed back into the conversation.
That sentence carries a lot of weight, so look at it twice. Claude is doing the thinking. The hook is the wiring around the thinking. Before Claude runs a Bash command, before Claude edits a file, when Claude finishes a response, when the session starts, when the session ends, when Claude is stuck and needs your input. Every one of those moments is a fixed event in the harness lifecycle. A hook is what you bolt onto that event.
The configuration lives in settings.json. Settings can sit in three places: your user-level config (~/.claude/settings.json), your project-level config (.claude/settings.json, checked into the repo), or a local override (.claude/settings.local.json). Hooks defined at the user level apply across every project. Project-level hooks only fire inside that project. The hierarchy gives you a clean split: house rules sit at the user level (audit logging, danger-command blockers), project-specific rules sit in the repo (run this project’s linter, push to this branch).
What this gets you is consistency. The setup steps you forget half the time will run every time. The shutdown steps you skip when you are tired will run every time. The dangerous command pattern you have been meaning to block but have not got around to will get blocked every time. The shape of the thinking gets to stay the same. The mechanics around it stop being negotiable.
People who come at this from a developer background sometimes describe it as Git hooks for Claude Code. That is a reasonable shorthand. Git hooks fire on commits, pushes, and pulls. Claude code hooks fire on tool use, prompt submission, and session boundaries. Same idea, different surface area.

The Nine Hook Types and When They Fire
Nine events, roughly in the order you encounter them in a typical session.
SessionStart. Fires when a new Claude session begins. Anything you want primed before the first prompt: pull the latest from git, refresh a data file, print the current branch, load a status report. I have a SessionStart hook that pulls the latest from my Octavius repo and runs my daily data collection script if it has not run in the past six hours.
UserPromptSubmit. Fires after you submit a prompt, before Claude reads it. The output goes into Claude’s context as an additional system message, so this hook is where you inject extra context. Useful for things like the current date and time, the active branch, and your most recent commits. It is also a sensible place to log every prompt you ever send to a file, which becomes a searchable record later.
PreToolUse. Fires before any tool runs (Bash, Edit, Write, Read, Glob, Grep, and the rest). The hook receives the tool name and parameters as input. You can return an exit code that blocks the tool entirely. This is where you implement guard rails: block rm -rf patterns, block writes outside an allowed directory, block production database connections.
PostToolUse. Fires after a tool runs. The hook receives the tool result. You can use this to run linters on edited files, run tests, log the tool output, and kick off a follow-up script. PostToolUse is where most of the build-pipeline work happens.
Notification. Fires when Claude needs your attention. Permission requests, idle prompts, ambiguous decisions. This is the hook that powers a Claude Code hooks notification setup, the one that pings your phone when Claude is waiting on input so you do not have to sit and watch the terminal.
Stop. Fires when Claude finishes responding. Auto-commit. Send a summary message. Print elapsed time. Save a snapshot of the conversation.
SubagentStop. Fires when a subagent finishes its task (an Explore agent, a general-purpose agent). Aggregate the subagent’s output, log it, and route it onward.
PreCompact. Fires just before Claude compacts its context. Use this to save a full transcript before it gets summarised. Helpful when you are doing long sessions and want a permanent record.
SessionEnd. Fires when the session ends. Commit work in progress. Push to remote. Log total session length. Close the loop.
The configuration shape is the same across all of them. Each event takes an array of matchers. Each matcher names a tool or pattern and lists the commands to run. A small block of JSON. That is it.
For the canonical Claude code hooks reference, the official Anthropic documentation covers the full schema plus working examples for every event type. Read it once before you write your first hook. It will save you an hour of trial and error.

Useful Claude Code Hooks for Real Business Operators
Common Claude Code hooks use cases, in roughly the order I would add them to a new workspace.
The audit log. PostToolUse, matcher Bash, command: echo "$(date -Iseconds) | $1" >> ~/.claude/bash-history.log. Now every Bash command Claude ever runs in your name is logged with a timestamp. A week later, when you want to know “did Claude actually run the database migration on Tuesday?”, you grep your log.
The danger blocker. PreToolUse, matcher Bash, command: a small shell script that checks for patterns like rm -rf /, DROP TABLE, git push --force and exits non-zero if it sees them. Claude reads the non-zero exit code as a block and refuses the tool call. This is your safety net for the day a prompt goes sideways.
The morning warm-up. SessionStart, no matcher, command: a script that pulls the latest from your repo, refreshes your daily metrics file, and prints a one-line status to stdout. Every session starts with fresh data. No more “wait, when was this file updated?”
The phone notification. Notification hook, command: a curl call to your Telegram bot API that sends “Claude needs you” to your phone with the current question attached. Walk away from the desk. Get the ping. Come back when it matters.
The auto-formatter. PostToolUse, matcher Edit|Write, command: run your project’s formatter or linter on the changed file. Prettier for JS. Black for Python. Whatever your stack uses. Code never lands in your repo unformatted again.
The test runner. PostToolUse, matcher Edit|Write, command: run the relevant test file. If tests fail, Claude reads the failure output and fixes its own work before you ask. This is one of my favourites because it removes a whole class of “wait, did that actually work?” moments.
The commit machine. Stop hook, command: stage all changes, commit with a message like claude session $(date +%Y-%m-%d-%H%M), push. Every session produces a clean commit you can review later.
The prompt logger. UserPromptSubmit hook, command: append the prompt to a daily log file. Two months from now you can see exactly what you asked for, in what order, on any given day. Useful for spotting patterns in what you keep delegating to Claude.
The compaction snapshot. PreCompact hook, command: save the full conversation transcript to a dated file before the summary kicks in. You get a permanent record of long sessions instead of a lossy summary.
For a starting point, a Claude Code hooks GitHub lookup turns up plenty of open-source repos with ready-to-paste configurations. The Anthropic docs include a working sample of every hook type. Start small. Pick two hooks. Get them firing. Add the next two next week.

Claude Code Hooks Best Practices
Lessons from running hooks in my own workspace for a few months.
Keep them fast. A hook that takes five seconds to run adds five seconds to every tool call. Multiply by the dozens of tool calls in a session, and you have just made Claude feel slow. Anything over two seconds, run it in the background and write the result to a file the next hook reads.
Log everything to a single place. Pick a directory like ~/.claude/logs/ and write every hook output there with a timestamp. When something feels off, grep your way through the logs. You cannot debug what you cannot see.
Never put credentials in the hook command itself. Settings.json lives in your repo or your home directory. Both can leak. Use environment variables or a secrets file with restricted permissions. Read the secret inside the hook script, not in the JSON.
Test the failure mode. What happens if your hook script returns exit code 1? Does Claude block the tool call? Is that what you wanted? Run the test deliberately. Find out before it happens for real.
Treat PreToolUse as a security layer, not a polishing layer. Use it to block. Anything decorative (formatting, logging, notifications) belongs in PostToolUse or Stop. PreToolUse runs in the path of every single tool call, so it needs to be fast and predictable.
Version your settings.json. Check the project-level hooks into the repo so the whole team gets them. Keep the user-level hooks in a private dotfiles repo so you can move to a new machine without losing them.
Start with two hooks, not twenty. Pick the two that matter most to your specific workflow. Get them solid. Add the next two next week. Hooks compound. A workspace with three solid hooks beats one with fifteen flaky ones.
The Claude Code hooks best practices list is short on purpose. Anything that does not appear on it is optional.

How Hooks Plug Into a Bigger System
This is the part that matters to me as a founder, not as a developer. Hooks are not the goal. The goal is a business that does not need you in the room for every micro-decision. Hooks are one mechanism that helps get you there.
I describe Octavius as building an AI brain and an AI workforce for founder-led businesses. The brain is the thinking layer. The workforce is the doing layer. Hooks live inside the doing layer. They are the bit of wiring that says “when this happens, also do this”. A daily data refresh hook means the brain always has current numbers. A notification hook means you only get pulled in when you are genuinely needed. An audit log hook means there is a record of what got done in your name.
Take it further. The Stop hook can post a one-line summary of what Claude just did to a Telegram channel you check on your phone. The SessionStart hook can run a script that emails you yesterday’s metrics before you have got out of bed. The PostToolUse hook can write to a database the same numbers you would otherwise be pulling manually from a CRM. None of this is exotic. All of it is the same idea repeated: turn a recurring action into a script that fires automatically.
This is how a working business gets less dependent on the founder. Not by replacing the founder. By moving every recurring action into a script that fires automatically. Each hook is one specific recurring action moved out of your head and into the system. Most founders I talk to already have ten or twenty such actions in mind. They have been meaning to set them up for a year. Hooks are how you actually do it. If you want the bigger framing, my post on the system that runs your business covers how the wiring layer fits inside the thinking layer, and how to think about AI automation for your business without ending up with sixteen tools that do not talk to each other.
If you read this and think “I have no idea where to start”, that is the right answer. The starting point is not a list of hooks. The starting point is an honest map of what you do before and after every Claude session that you wish you did not have to do. Then you write that down. Then you turn each line of the list into a hook. Once a week. Twelve weeks later, your work is unrecognisable.
I built a full version of this for my own business. Daily metrics are pulled automatically. Morning brief on my phone. Audit log of every command. Auto-commit on session end. The wiring runs in the background. I get to think about strategy. The system handles the rest. There is a longer write-up of how the same idea applies to multiple agents in my piece on AI agents for small business.
Conclusion
Claude Code hooks are the small wiring that lets a Claude Code workspace stop being a chat interface and start being a workshop. Before tool calls. After tool calls. Session boundaries. Notifications. Each one is an event you can attach a script to. Each script is a small piece of busywork moved permanently out of your head.
You do not need to set up all nine on day one. Start with the audit log and the danger blocker. Add the morning warm-up next week. Add the phone notification the week after. By the time you have five hooks running, your day looks different.
The bigger picture is the same one I write about constantly. Stop being the operator. Become the architect. Hooks are one of the simplest places to start.

Book a Discovery Call
If you want help mapping which hooks would matter most in your specific business (and which to ignore), book a 30-minute Discovery Call with me. I will talk you through what you are doing manually right now, where Claude Code or another AI tool could take over the wiring, and what a sensible first step looks like. No pitch deck, no slide carousel. Book here: 30-minute Discovery Call.
Frequently Asked Questions
What are Claude Code hooks?
Claude code hooks are shell commands you configure to run automatically at fixed events in a Claude Code session. The events include tool use (before and after), session start, session end, prompt submission, and Claude attention requests. You define them in settings.json under the “hooks” key. They are the way to make the same setup and shutdown work happen every time without you remembering it.
How do I add a hook to Claude Code?
Edit settings.json (either user-level at ~/.claude/settings.json or project-level at .claude/settings.json). Add a “hooks” key. Under it, name the event (like “PreToolUse” or “Stop”). Each event takes an array of matchers, and each matcher names a tool plus a list of commands to run. The Anthropic docs include a working sample for every event type.
Where do Claude Code hooks live in settings.json?
Under the “hooks” key, organised by event name. Settings can live in three places: ~/.claude/settings.json for user-level rules, .claude/settings.json inside your project for project-specific rules, and .claude/settings.local.json for personal overrides not checked into git. User-level hooks apply everywhere. Project-level hooks only fire inside that repo.
Can Claude Code hooks block dangerous commands?
Yes. A PreToolUse hook receives the tool name and parameters before the tool runs. If your hook script exits with a non-zero code, Claude reads that as a block and refuses to run the tool. This is how you build guard rails against patterns like rm -rf / or production database writes. The block is genuine, not advisory, and it runs every time without exception.
What is the difference between PreToolUse and PostToolUse hooks?
PreToolUse fires before the tool runs. Its job is to validate, block, or modify the request. PostToolUse fires after the tool finishes. Its job is to react to the result: run a linter, kick off tests, log the output, send a notification. PreToolUse is your safety net. PostToolUse is your build pipeline. Use both for different reasons.
Can I send a notification when Claude Code needs my attention?
Yes. The Notification event fires when Claude requests permission or input. A Claude Code hooks notification configuration typically calls a script that posts to Telegram, Slack, or your phone’s push service. Now you can walk away from the terminal and get a ping when Claude is genuinely stuck, instead of sitting and watching for the prompt to appear.
Are Claude Code hooks safe to use?
They run as shell commands on your machine, so they have full access to your filesystem and credentials. Treat them like any other automation. Never paste a hook from an untrusted source without reading it first. Keep secrets in environment variables, not in the hook command. Test the failure mode deliberately. With those precautions, hooks are safe and useful.
About Octavius
Titus Mulquiney is the founder of Octavius AI, where he builds AI brains and AI workforces for founder-led businesses stuck running everything out of their own head. Twenty years in marketing, ex-Sony product manager, ex-GM Zeal NZ. Based in Auckland, working with operators across NZ, Australia, and the US. Connect on LinkedIn.