How to Get Claude Code Notifications on macOS
You kick off a task, switch to Slack, and come back ten minutes later to find Claude Code finished nine minutes ago — or worse, that it's been sitting on a permission dialog the whole time. Here's how to get notified the moment a session needs you, from a one-line setting to custom hooks to a full status monitor.
The two moments that matter
Claude Code blocks on you in two distinct situations, and they need different urgency:
- Waiting for input mid-task — a tool-permission prompt ("run this command?"), a plan waiting for approval, or a clarifying question. The session is stalled until you answer; every unnoticed minute is pure loss.
- Finished responding — the turn is done and the next prompt is yours. Less urgent, but it's the signal to come back and review.
Both are exposed through Claude Code hooks:
the Notification event fires when Claude needs your attention (for permission
prompts, shortly after the dialog appears unanswered — quick approvals don't spam you), and
the Stop event fires when Claude finishes a response.
Option 1: native notifications from your terminal
Before writing any scripts, check your terminal — Claude Code can post macOS desktop notifications through Ghostty, Kitty, and iTerm2 when it's waiting for you.
- Ghostty / Kitty — works out of the box; just allow notifications for the app when macOS asks.
- iTerm2 — enable it first: Settings → Profiles → Terminal → check “Send Notification Center alerts”, and allow iTerm2 notifications in macOS System Settings.
Apple's stock Terminal.app has no such integration — for that, use the bell or hooks below.
Option 2: the terminal bell
Claude Code can ring the terminal bell when it needs attention. One line in
~/.claude/settings.json:
{
"preferredNotifChannel": "terminal_bell"
}
Most terminals turn the bell into something visible: Terminal.app badges the tab, iTerm2 can post a notification for it, and tmux marks the window with a bell indicator. Crude, but it works everywhere and needs no scripts.
Option 3: custom macOS notifications via hooks
No extra tools needed — macOS's built-in osascript can post to Notification Center.
1. Create two small scripts
mkdir -p ~/.claude/scripts
cat > ~/.claude/scripts/notify-waiting.sh <<'EOF'
#!/bin/bash
# Claude Code "Notification" hook: a session needs your input.
osascript -e 'display notification "A session is waiting for your input" with title "Claude Code" sound name "Glass"'
EOF
cat > ~/.claude/scripts/notify-done.sh <<'EOF'
#!/bin/bash
# Claude Code "Stop" hook: a session finished responding.
osascript -e 'display notification "Finished responding" with title "Claude Code"'
EOF
chmod +x ~/.claude/scripts/notify-waiting.sh ~/.claude/scripts/notify-done.sh
2. Register them in ~/.claude/settings.json
Add a hooks section (or merge into your existing one). This applies to every
project; use a project's .claude/settings.json instead to scope it.
{
"hooks": {
"Notification": [
{
"hooks": [
{ "type": "command", "command": "$HOME/.claude/scripts/notify-waiting.sh" }
]
}
],
"Stop": [
{
"hooks": [
{ "type": "command", "command": "$HOME/.claude/scripts/notify-done.sh" }
]
}
]
}
}
Start a new Claude Code session (hooks are read at startup), ask for something that runs a tool you haven't allowlisted, and leave the permission dialog unanswered for a few seconds — a notification should appear.
Optional refinements
- Show the actual message. Hooks receive a JSON payload on stdin whose
messagefield describes what Claude wants. If you have jq installed:#!/bin/bash msg=$(jq -r '.message // "Needs your input"') osascript -e "display notification \"${msg//\"/\\\"}\" with title \"Claude Code\"" - Include the project. The payload's
cwdfield tells you which checkout the session lives in — useful once you run more than one (see managing multiple sessions). - Richer banners.
terminal-notifier(Homebrew) supports custom icons and click actions, ifosascript's plain banners feel too spartan. - Check Notification Center settings. If nothing appears, System Settings →
Notifications: your terminal (or Script Editor, which owns
osascriptbanners) must be allowed to notify, and macOS Focus modes silence banners by default.
Where notifications fall short
This setup is genuinely useful — we recommend it to everyone. But banners have structural limits you'll hit as usage grows:
- They're events, not state. A banner slides away after a few seconds. "Is anything waiting on me right now?" has no answer — you're back to checking terminals.
- They don't scale with session count. Three parallel sessions produce a stream of look-alike banners. Which session? Which project? Was that one already handled?
- No answer-and-return path. The banner doesn't take you to the right terminal pane — you still hunt for the tab.
- Approval isn't detected. Hooks fire when the prompt appears, not when you answer it, so a "waiting" you built state on top of goes stale (more on that in the hooks status guide).
The alternative: a persistent status window
AgentManager approaches the same problem as state you can glance at rather than events that interrupt you. It's a macOS menu bar app that keeps a small always-on-top window listing every Claude Code session with a status lamp — waiting, running, done, idle:
- The window surfaces by itself when a session starts waiting (with an optional cat meow instead of a banner sound) and hides when everything's clear — no Notification Center involved.
- Waiting rows show what kind of answer is needed — approval, plan review, or a choice.
- Clicking a row jumps to the exact terminal pane — iTerm2, Terminal.app, Ghostty, VS Code-family (tmux: status tracking only, no pane jump yet).
- Approvals are detected the moment you answer, so "waiting" lamps clear immediately instead of going stale.
Setup is one click (it registers its hooks for you, and they're cleanly removable). It also
coexists with the osascript setup above — hooks compose, so you can keep banners for
Stop and let the window handle waiting states.
Never miss a waiting session
AgentManager surfaces the moment any Claude Code session needs you — free to use, no account required.