When Claude is responding in the background and you have moved on to something else, you don't need to keep checking on it. Claude Code can tell you itself: a terminal bell or desktop notification when it finishes or pauses for permission, a hook that runs any command you like (a sound, an OS notification, a message to your phone), or a push through the Claude app when the session is connected with Remote Control. Here is each option, with config you can paste.
The built-in notification
Claude Code fires a notification event when it finishes a task or stops for a permission prompt and you appear to be away from the terminal. What you see depends on your terminal (as of October 2026):
- Ghostty, Kitty and iTerm2 get a desktop notification by default. In iTerm2, also turn on forwarding: Settings, Profiles, Terminal, check Notification Center Alerts, then under Filter Alerts enable Send escape sequence-generated alerts.
- Every other terminal, including VS Code's integrated terminal and Warp, gets nothing until you choose a channel. The simplest is the terminal bell:
{
"preferredNotifChannel": "terminal_bell"
}Put that in ~/.claude/settings.json. If you run Claude Code inside tmux, add set -g allow-passthrough on to ~/.tmux.conf so notifications reach the outer terminal. Over SSH, Ghostty and Kitty forward the desktop notification to your own machine.
Notification hooks: when Claude needs you
A hook runs your own command at a point in Claude Code's lifecycle. The Notification event fires alongside the built-in notification, and a matcher picks which kinds you care about. The two that matter most:
| Matcher | Fires when |
|---|---|
permission_prompt | Claude needs approval and the prompt has waited about six seconds without you typing |
idle_prompt | Claude finished about 60 seconds ago, you haven't typed since, and no background agent is still running |
agent_needs_input, agent_completed | A background session needs you or finishes, while agent view (claude agents) is open |
On macOS, this shows a notification for both of the first two. Add it to ~/.claude/settings.json:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt|idle_prompt",
"hooks": [
{ "type": "command", "command": "osascript -e 'display notification \"Claude Code needs you\" with title \"Claude Code\"'" }
]
}
]
}
}If nothing appears on macOS, run osascript -e 'display notification "test"' once, then allow notifications for Script Editor in System Settings. On Linux, swap the command for notify-send 'Claude Code' 'Claude Code needs you' (from the libnotify-bin package on Debian and Ubuntu). Type /hooks in Claude Code to confirm the hook loaded.
The delays are deliberate, so you aren't pinged while you're at the keyboard. If you want to react the moment Claude asks for permission, use a PermissionRequest hook instead.
Stop hooks: the moment a turn ends
Stop runs every time Claude finishes responding. It doesn't run when you interrupt, and an API error fires StopFailure instead. The hook receives the final reply as last_assistant_message, so the notification can say what happened. Save this as ~/.claude/hooks/notify-stop.sh and make it executable with chmod +x:
#!/bin/bash
input=$(cat)
dir=$(jq -r '.cwd' <<<"$input")
msg=$(jq -r '.last_assistant_message // "Finished"' <<<"$input" | head -c 180)
[ "$(jq '.background_tasks | length' <<<"$input")" -gt 0 ] 2>/dev/null && exit 0
osascript -e 'on run argv' -e 'display notification (item 1 of argv) with title (item 2 of argv)' \
-e 'end run' "$msg" "Claude Code: ${dir##*/}"
exit 0Then register it:
{
"hooks": {
"Stop": [
{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-stop.sh" }] }
]
}
}Two details in that script are worth keeping. Passing the message as an argument (on run argv) means quotes in Claude's reply can't break the AppleScript. And the background_tasks check skips the notification when the turn ended while background work, such as a subagent, is still running and will wake the session again, which is often why Claude seems to keep working after its turn has ended.
Stop fires after every reply, including one-line answers. If that's too chatty, use the idle_prompt matcher above, which only fires when a finished session has sat untouched for a minute.
Send it to your phone: ntfy or Telegram
A desktop notification is useless once you've left the desk. Replace the osascript line in the script with a curl, and keep the rest.
ntfy needs no account: pick a hard-to-guess topic name (anyone who knows it can read it) and subscribe to it in the ntfy app.
curl -s -m 5 -H "Title: Claude Code: ${dir##*/}" -d "$msg" "https://ntfy.sh/$NTFY_TOPIC" >/dev/nullTelegram needs a bot token from @BotFather and your chat id:
curl -s -m 5 "https://api.telegram.org/bot$TG_BOT_TOKEN/sendMessage" \
-d chat_id="$TG_CHAT_ID" --data-urlencode text="Claude Code (${dir##*/}): $msg" >/dev/nullSet NTFY_TOPIC, or TG_BOT_TOKEN and TG_CHAT_ID, in your shell profile or at the top of the script. The -m 5 timeout keeps a slow network from holding up the hook.
Push through the Claude app with Remote Control
If you start sessions with claude --remote-control (or /remote-control), the Claude app can push to your phone without any scripts. Run /config and enable Push when actions required for permission prompts and questions, and Push when Claude decides for finished long tasks. Pushes are skipped while you're typing in the connected terminal. The remote control guide covers setup and limits.
When Claude keeps working in the background
Background work changes when notifications fire. A session doesn't send idle_prompt while its background subagents are still running. Background sessions you dispatch with claude --bg have no terminal of their own; while agent view is open, Claude Code notifies you when one of them needs input, finishes or fails, and fires the matching Notification hook. Close agent view and those notifications stop, though the sessions keep running.
Which option to use
- You're at the desk with one session: the built-in notification, or the terminal bell if your terminal doesn't show one.
- You want to know what happened, not just that something did: a
Stophook that includes the last message. - You've left the desk: Remote Control push if you sign in with a claude.ai plan, or an ntfy or Telegram hook, which also works with an API key or a cloud provider such as Bedrock.
- You're on Windows: Anthropic's hooks guide shows a
powershell.execommand that opens a message box; the ntfy and Telegramcurllines work in Git Bash and WSL.
Many sessions, one ping
Hooks are per machine and per tool. Once you have three Claude Code sessions, a Codex run and a cron job going, you want one place that says which one is waiting. Briefkin installs a hook in each agent on your computer and turns every session into a card: working, waiting on you, or done, with a one-line status of where it stands. It pings Telegram only when a session is waiting on you, and from a local Claude Code session that ended on a question you can reply right from that Telegram message. The docs show the one-command setup, and the dashboard guide compares the other ways to watch many sessions. For the full event list, see the hooks guide.
Questions
Why don't I get Claude Code notifications in my terminal?
By default Claude Code sends desktop notifications only in Ghostty, Kitty and iTerm2 (and iTerm2 needs forwarding turned on). In VS Code's terminal, Warp and others, set "preferredNotifChannel": "terminal_bell" in ~/.claude/settings.json or add a Notification hook.
How do I get notified when Claude Code finishes a task?
Add a Stop hook, which runs every time Claude finishes responding, or a Notification hook with the idle_prompt matcher, which fires about 60 seconds after Claude finishes if you haven't typed since. Either can run any command: a sound, a desktop notification or a curl to your phone.
Why does my Notification hook fire late?
It is meant to. permission_prompt waits until you haven't typed for about six seconds and idle_prompt about 60 seconds, so you aren't pinged while you're at the keyboard. To react the instant Claude asks for permission, use a PermissionRequest hook instead.
Can I get Claude Code notifications on my phone?
Yes. Remote Control can push through the Claude app, a hook can send a message to ntfy or a Telegram bot, and a board like Briefkin pings Telegram when any session is waiting on you.
Do notifications work over SSH or inside tmux?
Desktop notifications from Ghostty and Kitty reach your local machine over SSH. Inside tmux, add set -g allow-passthrough on to ~/.tmux.conf so notifications reach the outer terminal.