Workbranch › Guides

Guide

How to use hooks in Claude Code

You want something to happen every time, such as formatting a file after Claude edits it or a ping when Claude is waiting for you, without hoping Claude remembers. Hooks do exactly that. This guide explains what they are, walks through a first hook, and shows where to put them.

Updated 30 October 2026

Quick answer: a hook is a shell command that Claude Code runs automatically at a fixed point, for example before a tool runs, after a file is edited, or when Claude needs your input. You add hooks under a hooks key in a settings file such as ~/.claude/settings.json (all projects) or .claude/settings.json (one project), then type /hooks to confirm Claude Code sees them.

Event names, file locations and behavior below come from Anthropic's Claude Code documentation as of October 2026. Claude Code updates often, so run claude update if something is missing.

What hooks are and why they help

Instructions in a prompt or a CLAUDE.md file are suggestions: Claude usually follows them, but it decides. A hook is different. Claude Code itself runs your command whenever the event fires, so the action is deterministic. Typical uses from Anthropic's guide:

Some of the most used events are SessionStart (a session begins or resumes), UserPromptSubmit (you send a prompt), PreToolUse (before a tool call, and it can block it), PostToolUse (after a tool call succeeds), Notification, Stop (Claude finishes responding), PreCompact and SessionEnd. The full list in the hooks reference is much longer.

Set up your first hook: a desktop notification

This example, adapted from Anthropic's walkthrough, alerts you on macOS whenever Claude Code needs your attention.

  1. Open ~/.claude/settings.json in a text editor. Create the file if it doesn't exist.
  2. Add a hooks object with a Notification entry. Inside it goes a list of matcher groups; each has a matcher (leave it as an empty string to fire on every notification) and a hooks list with one item of "type": "command".
  3. Set the command to osascript -e 'display notification "Claude Code needs your attention" with title "Claude Code"'. On Linux, Anthropic's example uses notify-send instead. Remember to escape the inner double quotes in JSON.
  4. If the file already has a hooks key, add Notification next to the existing events rather than replacing the whole object.
  5. In Claude Code, type /hooks. The hooks browser should list your new hook under Notification. Press Esc to go back.
  6. Ask Claude for something that needs permission and switch to another window. A notification should appear.

To fire only on some notifications, set the matcher to a type such as permission_prompt (a permission prompt has been waiting for about six seconds) or idle_prompt (Claude finished and you haven't typed for about a minute).

A second example: format files after edits

For a project hook, put the configuration in .claude/settings.json at the project root. Use the PostToolUse event with the matcher Edit|Write, so it only runs after file-editing tools. Anthropic's example command reads the edited path from the JSON Claude Code passes on standard input and hands it to Prettier: jq -r '.tool_input.file_path' | xargs npx prettier --write. It needs jq installed. A successful hook shows nothing in the conversation; you'll just see the file reformatted.

Where hooks are configured

LocationApplies toShared?
~/.claude/settings.jsonAll your projectsNo, only your machine
.claude/settings.jsonOne projectYes, can be committed
.claude/settings.local.jsonOne projectNo, kept out of git
Managed policy settingsWhole organizationSet by admins
A plugin's hooks/hooks.jsonWhile the plugin is enabledBundled with the plugin
Skill frontmatterThe rest of the session after the skill is invokedIn the skill file
Subagent frontmatterWhile that subagent runsIn the subagent file

To switch hooks off, set "disableAllHooks": true in a settings file. Hooks from managed settings keep running unless it is set there too.

How a hook talks back

When an event fires, Claude Code sends event details as JSON to your command's standard input. Your command answers with its exit code:

For finer control, exit 0 and print a JSON object instead. Pick one approach per hook.

Good to know

If it doesn't work

Keep track of what each session leaves open

The Workbranch plugin for Claude Code uses a session-start recap: in a folder linked to a Workbranch project, it shows what is still open when a session begins, and saying "save this to Workbranch" files the session's tasks, decisions and open questions into that project. See Workbranch for Claude. New to Claude Code? Start with getting started with Claude Code.

Sources

Frequently asked questions

Can Claude write a hook for me?

Yes. Anthropic's guide says you can describe the hook you want at the Claude Code prompt and ask Claude to add it to your settings. Check the result with /hooks afterwards.

Can a hook stop Claude even in bypass mode?

A PreToolUse hook that returns a deny decision blocks the tool in every permission mode, including bypassPermissions. That is what makes hooks useful for rules people can't switch off by changing modes.

Are there hooks that use a model instead of a script?

Yes. Besides shell commands, a hook can be an HTTP request, an MCP tool call, a single prompt evaluated by a Claude model, or an experimental agent hook with tool access.