Claude Code Hooks: How to Automate Your Workflow

David IyaDavid Iya June 30, 2026 8 min read
A hand stopping a chain of falling colored dominoes mid-fall, a metaphor for a Claude Code hook intercepting an action before it runs
Photo via Pexels

What a Claude Code hook is

A Claude Code hook is a shell command the app runs for you automatically at a fixed point in a session. The key word is automatically. You do not type a prompt to trigger it, and Claude does not choose to run it. The app itself fires the command the moment a set event happens, every single time, whether you remember it or not.

That distinction is the whole value. A prompt is something you have to remember to send. A hook is a rule the app enforces on your behalf. If your rule is format the code after every edit, a hook makes that happen on edit number one and edit number four hundred, with the same reliability, because it is wired into the session lifecycle rather than left to habit.

The hook clock: the four moments a hook can fire

Claude Code exposes several lifecycle events, but four of them cover almost everything a builder wants. We call these four the hook clock, because they mark the turning points of a single turn. Before you write a hook, the only real question is which moment on the clock you want to attach to.

  • UserPromptSubmit: fires the instant you send a message, before Claude reads it. Good for injecting context or catching a prompt you want to block.
  • PreToolUse: fires right before Claude runs a tool, like an edit or a shell command. This is the one moment where you can stop an action before it happens.
  • PostToolUse: fires right after a tool finishes successfully. This is where you react to a change, for example by formatting the file that was just edited.
  • Stop: fires when Claude finishes its turn and is about to hand control back to you. Good for a desktop notification, a log line, or a final check.

There are more events beyond these four, including ones for when a session starts and ends and when a tool fails, but the clock is where you should start. Match the job to the moment: react to a change with PostToolUse, prevent a change with PreToolUse, and you have covered most real workflows.

Where hooks live

Hooks are configured in a settings.json file, not in code. You have three places to put them, and the choice decides who the hook applies to.

  • Your home settings at ~/.claude/settings.json: the hook applies to every project you work on. Use this for personal rules like a notification when a turn ends.
  • Project settings at .claude/settings.json: the hook is checked into the repo and applies to everyone on the team. Use this for shared rules like formatting standards.
  • Local project settings at .claude/settings.local.json: the hook applies only to you on that project and is kept out of version control. Use this for machine-specific paths.

Inside the file, hooks live under a hooks key, grouped by event name. Each entry can carry a matcher that narrows it to specific tools, and a list of commands to run. The shape is the same for every event, so once you have written one hook you can write any of them.

Your first hook: auto-format after every edit

The hook that earns its keep fastest is a PostToolUse hook that formats code the moment Claude edits it. You stop asking Claude to run the formatter, you stop noticing messy diffs, and every file that leaves a session is already clean. Here is the shape in settings.json.

FieldValueWhat it does
EventPostToolUseRun the command after a tool completes.
matcherEdit|WriteOnly fire for edits and file writes, not for reads or searches.
typecommandRun a shell command (the only hook type).
commandyour formatter scriptThe command the app runs on each matching edit.

When the hook fires, Claude Code sends the details of the event to your command as JSON on standard input, including which file was touched. Your script reads that, formats the file, and exits. Point the command at a small script in your repo so the whole team gets the same behavior, and formatting stops being something anyone has to think about.

The guardrail hook: block a change before it happens

The second hook worth having is a PreToolUse guardrail. Because PreToolUse fires before the tool runs, it is the one place you can stop an action entirely. The classic use is protecting files you never want an agent to touch, like a production environment file or a lock file.

You attach the hook to PreToolUse with a matcher for edits, and your command inspects the incoming JSON to see which file is about to change. If it is on your do-not-touch list, the command blocks the edit. This turns a vague hope that the agent behaves into a hard rule the app enforces, which matters a lot more once you start letting Claude run with less supervision.

How a hook talks back

Every hook communicates in two directions, and understanding both is what lets you go past copy-paste examples. Inbound, the app hands your command a JSON payload on standard input describing the event: the session, the tool, the files involved, and more. Your script reads that to decide what to do.

Outbound, your command reports back through its exit code and its output. The simple version: exit zero and the session continues, exit non-zero on a blocking event and the action is stopped. The advanced version: print a JSON object to standard output to do more, such as denying a specific tool call, adding context to the conversation, or telling Claude to keep going with extra instructions. Start with exit codes and reach for JSON output when you need the control.

Hooks, skills, and subagents: which one to reach for

Hooks are one of several ways to shape Claude Code, and they are not always the right one. The rule of thumb: a hook is for something that must happen automatically and deterministically, every time, no judgment involved. Formatting on save and blocking a protected file are perfect hooks because there is nothing to decide.

When the job needs judgment or a lot of reasoning, you want a different tool. A repeatable expert task belongs in a subagent, and a packaged capability with its own instructions belongs in a skill. If you are weighing these against each other, our guide on [when to use skills, subagents, MCP, and hooks](/blog/claude-code-skills-subagents-mcp-hooks-when-to-use) walks through the decision, and our piece on [Claude Code subagents](/blog/claude-code-subagents) covers the delegation side in depth.

A starter setup you can copy this week

Here is a concrete way to get value from hooks on your next project. It takes about fifteen minutes the first time and then runs forever.

  1. Add a PostToolUse hook matched to Edit and Write that formats the changed file, so every edit lands clean.
  2. Add a PreToolUse hook matched to Edit and Write that blocks changes to a short list of protected files, so an agent can never overwrite your secrets or lock files.
  3. Add a Stop hook that sends you a desktop notification, so you know the moment a long turn is done and can step away without babysitting it.
  4. Put the formatting and protection hooks in the project's .claude/settings.json so your whole team inherits them, and keep the notification hook in your personal ~/.claude/settings.json.
  5. Once these feel natural, pair them with the commands you run by hand, covered in our guide to [slash commands you use every day](/blog/claude-code-slash-commands-you-use-every-day).

The pattern to internalize is simple: hooks turn your good intentions into rules the app keeps for you. Anything you keep reminding Claude to do, or keep hoping it will not do, is a candidate for a hook.

Learn this with us

Inside Claude Code Club we share the hooks that actually earn their place, from formatters to guardrails to notifications, and help each other wire them up without breaking a workflow. Start with the [curriculum](/curriculum) or join us at https://www.skool.com/claudecodeclub/about and bring the one thing you keep reminding Claude to do.

Frequently asked questions

What is a hook in Claude Code?

A hook is a shell command that Claude Code runs automatically at a set point in a session, such as before a tool runs or right after an edit. You do not trigger it with a prompt and Claude does not decide to run it: the app fires it every time the event happens. Hooks are configured in a settings.json file and work in both the desktop app and the terminal.

When do Claude Code hooks fire?

Hooks fire at fixed lifecycle moments. The four most useful are UserPromptSubmit when you send a message, PreToolUse right before Claude runs a tool, PostToolUse right after a tool finishes, and Stop when Claude ends its turn. There are additional events for session start and end and for tool failures, but those four cover most everyday automation.

How do I set up a Claude Code hook?

Add it to a settings.json file: ~/.claude/settings.json for every project, .claude/settings.json to share it with your team, or .claude/settings.local.json for just you on one project. Under the hooks key, choose the event, add an optional matcher to target specific tools, and give it a command to run. The app passes your command a JSON payload on standard input describing the event.

Can a hook stop Claude from doing something?

Yes, if you attach it to a blocking event like PreToolUse, which fires before the tool runs. Your command can block the action by exiting with a non-zero status or by returning a JSON object that denies it and explains why. This is how you protect files you never want touched, because the reason is fed back to Claude so it understands the boundary.

Last reviewed by David Iya on June 30, 2026

David Iya

Written by

David Iya

Forbes 30 Under 30 · Y Combinator

Keep reading

Claude CodeAI Agents

Claude Code Subagents: How to Actually Use Them

A subagent is a second Claude Code instance that runs a job in its own context window and reports back. Here is what Claude Code subagents are, the three jobs they do well, how to spawn and build your own, and what the June 2026 update changed.

David Iya 8 min
Read article
Claude CodeAgencies

How to Run Multiple Client Projects at Once in Claude Code

Juggling several clients in Claude Code does not have to mean a dozen scattered windows. Here is the client cockpit method: one repo and one CLAUDE.md per client, one view to see every job, and the guardrails that keep client work from bleeding together.

Duncan Rogoff 8 min
Read article

Ready to build it yourself?

Join Claude Code Club, the #1 community for learning claude code, for $9/month.

← Back to the blog