Guide

Five Claude Code hooks worth copying (with the settings.json to paste)

Five Claude Code hooks worth copying (with the settings.json to paste)

Hooks are the best under-used feature in Claude Code: shell commands that fire on lifecycle events, with the event as JSON on stdin. The docs tell you what they are; what most people want is five working recipes to steal. Here they are, roughly in the order of how much daily pain each one removes. (Prefer clicking to typing? The notification builder generates all of this from a form.)

1 · The "it needs you" ping — Notification

The highest-value hook in the file. Notification fires when the agent wants attention — above all, when it's waiting on a permission prompt you haven't seen:

"hooks": {
  "Notification": [{
    "hooks": [{ "type": "command",
      "command": "osascript -e 'display notification \"Claude needs you\" with title \"Claude Code\" sound name \"Glass\"'" }]
  }]
}

macOS shown; swap the command for notify-send on Linux or a BurntToast call on Windows. This single hook is the difference between "the agent stalled for 40 minutes" and "I heard a chime and typed y."

2 · The done chime — Stop

"Stop": [{
  "hooks": [{ "type": "command",
    "command": "afplay /System/Library/Sounds/Funk.aiff" }]
}]

Fires when the agent finishes its response. Pair a distinct sound with each agent and you can run several at once and know by ear which one came back.

3 · Discord (or Slack) when you're not at the desk — Stop + webhook

"Stop": [{
  "hooks": [{ "type": "command",
    "command": "jq -r '\"✅ Claude finished in \" + (.cwd // \"repo\")' | xargs -I{} curl -s -X POST -H 'Content-Type: application/json' -d '{\"content\":\"{}\"}' $DISCORD_WEBHOOK_URL" }]
}]

The hook gets session JSON on stdin — jq pulls what you want into the message. Same shape works for Slack webhooks and Telegram bots; the builder emits ready-made scripts for each so webhook URLs stay in your environment, not your settings file.

4 · Phone pings with zero infrastructure — Notification + ntfy.sh

"Notification": [{
  "hooks": [{ "type": "command",
    "command": "curl -s -d 'Claude is waiting for approval' ntfy.sh/your-secret-topic" }]
}]

Install the ntfy app, subscribe to your topic, done — approval prompts now buzz your pocket. You'll still have to walk back to the desk to answer, which is the honest limitation of the DIY route (and the gap remote control from your phone closes properly).

5 · The safety gate — PreToolUse

"PreToolUse": [{
  "matcher": "Bash",
  "hooks": [{ "type": "command",
    "command": "jq -e '.tool_input.command | test(\"rm -rf|drop table|force push\"; \"i\") | not' > /dev/null || (echo 'Blocked by policy hook' >&2; exit 2)" }]
}]

PreToolUse runs before the tool executes and can deny the call — a hook as a policy gate. The regex above is a blunt example; the pattern scales to "deny edits under migrations/," "require approval for anything touching .env," and the rest of your pre-approval policy. Blunt but local beats clever but forgotten.

Frequently asked questions

Where do Claude Code hooks go?

.claude/settings.json per project or ~/.claude/settings.json per user. Each entry: an event, an optional matcher, and a shell command that receives JSON on stdin.

Stop vs Notification — which do I wire first?

Notification. It fires when the agent is waiting on you — the unnoticed approval prompt is the single biggest time sink in agentic coding. Stop ("done") is the nice-to-have second.

Can a PreToolUse hook actually block a command?

Yes — it runs before execution and its exit code/output can deny the call. That's what makes it a policy gate rather than a logger.

Do I have to write these by hand?

No — the free notification builder generates the settings.json block and notify scripts for Discord, Slack, Telegram, ntfy.sh, and desktop toasts. No signup.

Where Backgrind fits

Everything above is the DIY version of what Backgrind does out of the box — it listens to these same hooks and turns them into an ambient pipeline: a chime plus an accent ring on the exact tab that needs you, clickable approve/deny right on the toast, escalation to your phone when you're away, and a policy engine where "always allow" is a granular saved rule instead of a regex in a JSON string. Start with the recipes; when you're running three agents at once, graduate.