Claude Code notifications on Mac know when it needs you

Claude Code pauses whenever it needs a permission, an answer or a plan approval, and when it is done. Here is how to find out on a Mac without watching the terminal.

Last updated: · Cadence Labs

Short answer

Add two hooks to ~/.claude/settings.json: a Notification hook, which runs when Claude Code needs your permission or has been waiting for input, and a Stop hook, which runs when it finishes a response. Have each one run osascript to post a macOS notification. The setup is below.

If you run several agents, a notification only tells you that one is waiting. Cadence shows every agent's state on a toolbar and lets you answer from one Inbox.

When Claude Code waits for you

Claude Code stops and waits in four situations:

In each case nothing happens until you answer. A long task that stopped on a permission prompt two minutes in is the most common way to lose an afternoon.

Option 1: the terminal bell

Claude Code can ring the terminal bell or send a terminal notification when it is waiting. Look for the notification setting in /config inside Claude Code; the available channels depend on your version and terminal.

What the bell does is up to your terminal. Terminal.app and iTerm2 can play a sound, flash the window, or badge and bounce the Dock icon when a bell rings in the background; look in the profile settings. In tmux, set -g monitor-bell on marks the window that rang.

The bell needs no scripts, but it is easy to miss and it does not say which project it came from.

Option 2: hooks and macOS notifications

Hooks are shell commands Claude Code runs at fixed points. Two of them cover what you want:

Step 1: write a small script

Save this as ~/.claude/hooks/notify.sh. It reads the event Claude Code sends on standard input, takes the message and the project folder, and posts a notification. It uses jq (brew install jq).

#!/bin/sh
input=$(cat)
msg=$(printf '%s' "$input" | jq -r '.message // "Finished"')
dir=$(printf '%s' "$input" | jq -r '.cwd // empty' | xargs basename)
osascript -e 'on run argv' \
  -e 'display notification (item 1 of argv) with title (item 2 of argv) sound name "Glass"' \
  -e 'end run' "$msg" "Claude Code: $dir"

Make it executable with chmod +x ~/.claude/hooks/notify.sh. Passing the text as arguments, instead of pasting it into the AppleScript, keeps quotes in Claude's message from breaking the command.

Step 2: register the hooks

Add this to ~/.claude/settings.json (merge it with anything already there):

{
  "hooks": {
    "Notification": [
      { "matcher": "", "hooks": [ { "type": "command", "command": "~/.claude/hooks/notify.sh" } ] }
    ],
    "Stop": [
      { "matcher": "", "hooks": [ { "type": "command", "command": "~/.claude/hooks/notify.sh" } ] }
    ]
  }
}

Step 3: test it

Start a new Claude Code session, since sessions load hooks when they start. Run /hooks to check that both are listed, then ask for something that needs a permission. If no banner appears, open System Settings → Notifications: notifications from osascript are listed under Script Editor, and a Focus mode can hide them.

Where notifications fall short

Hooks are a real improvement for one or two sessions. With more, a few gaps show up:

Option 3: Cadence's toolbar and Inbox

Cadence is a free macOS app that watches your coding agents and collects what they need from you.

Set it up

  1. Download Cadence. Agent features use your existing claude login.
  2. Start Claude Code from ⋯ → New agent… on the toolbar, or double-tap ⌥ and ask for the work with Talk.

For Claude Code agents it starts in a terminal, Cadence adds its own hook through Claude Code's --settings flag, so your ~/.claude/settings.json stays as it is. The hook records Claude's exact question or permission request, so the Inbox shows the full text instead of what fit on screen.

See state at a glance

The toolbar on the edge of your screen has one dot per agent: blue working, amber needs you, green done. The Inbox button shows how many agents are waiting. Since v0.5.3, when nothing needs you the toolbar folds into a small notch that shows only the dots, and it opens again when something lands in the Inbox.

Answer without switching windows

The Inbox lists every waiting card: questions with numbered options, plans with Approve the plan or Keep planning, and permission requests with Allow or Deny. Press 1 to 9 to answer, Space to type, or V to speak. A typed "no, use yarn instead" on a permission card denies it and passes your reason to the agent. Finished work arrives as a card with a short recap.

Sound and banners

In Settings → Agents, Text-to-speech reads agent completions and approval requests aloud (voice and rate are adjustable), and Notifications turns macOS notifications for agent events on or off.

Common questions

Why does my Claude Code hook not show a notification?

Check three things: the script is executable, you started a new session after editing settings, and macOS allows notifications from Script Editor, which is where osascript notifications come from. Focus modes can also hide them.

Can Claude Code notify me when it is done?

Yes. A Stop hook runs each time Claude Code finishes responding. Point it at the same script as the Notification hook, as shown above.

Does Cadence change my Claude Code settings?

No. Cadence passes its hook to the Claude Code sessions it starts with the --settings flag. Your own ~/.claude/settings.json and its hooks keep working.