When Claude Code waits for you
Claude Code stops and waits in four situations:
- A permission request. It wants to run a shell command, edit a file or use a tool your settings do not allow yet.
- A question. It asks you to pick between options before it goes on.
- A plan. In plan mode it waits for you to approve the plan or keep planning.
- Done. It finished the turn and is waiting for your next message.
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:
Notificationruns when Claude Code needs permission to use a tool, or when your input has been idle for a while.Stopruns when Claude Code finishes responding.
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:
- A banner says something is waiting, but you still find the right tab and scroll back to see the question.
- Banners pile up in Notification Center with no sense of which ones you already handled.
- Nothing shows the overall state: which agents are working, which are done, which are stuck.
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
- Download Cadence. Agent features use your existing
claudelogin. - 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.