Claude Code notifications: hear when it’s waiting vs. when it’s done

“A session that is blocked looks exactly like a session that is done, so I open the wrong one first.” That line from a Claude Code feature request sums it up. Here is how to get a different signal for each.

By Aslan, Pet Island team · Updated Oct 26, 2026 · 4 min read

SHORT ANSWER

Claude Code already raises a notification when it finishes or waits for permission while you are away, but only Ghostty, Kitty and iTerm2 show it as a desktop notification by default. Elsewhere, set "preferredNotifChannel": "terminal_bell". For two different sounds, use a Notification hook with the permission_prompt matcher for “needs you” and a Stop hook for “done”.

What Claude Code does on its own

When Claude finishes a task or pauses for a permission prompt, and you appear to be away from the terminal, it fires a notification event. By default it turns that into a desktop notification only in Ghostty, Kitty and iTerm2. In Windows Terminal, the VS Code terminal, Warp and the rest, nothing visible happens unless you set it up.

The simplest fix is the terminal bell:

~/.claude/settings.jsonCopy
{
"preferredNotifChannel": "terminal_bell"
}

What the bell does is up to your terminal. In Windows Terminal, the bellStyle setting can be audible (the default), window, taskbar, all or none. With all, Windows Terminal plays a sound and flashes the taskbar icon.

  • iTerm2: Settings → Profiles → Terminal → check “Notification Center Alerts”, then Filter Alerts → enable “Send escape sequence-generated alerts”.
  • tmux: add set -g allow-passthrough on to ~/.tmux.conf, or notifications never reach the outer terminal.
  • Over SSH: the desktop notification travels back to your local machine, so remote sessions can still alert you.

The feature request for system notifications (#26581, 34 upvotes) was closed as already available, pointing to exactly this built-in notification. The request for a different signal for “waiting” and “finished” (#94373) is still open. That is where hooks come in.

Two events: Notification and Stop

  • Notification fires when Claude Code sends a notification. Its matcher is the notification type. The two you care about are permission_prompt (Claude needs you to approve a tool use and the prompt has waited about six seconds) and idle_prompt (Claude finished responding about 60 seconds ago and you haven’t typed since).
  • Stop fires whenever Claude finishes responding. It doesn’t fire when you interrupt; API errors fire StopFailure instead.

Hooks run alongside the built-in notification rather than replacing it, so you can keep both.

Windows: two different sounds

On Windows, hooks run in Git Bash, or PowerShell when Git Bash isn’t installed. Setting "shell": "powershell" removes the guesswork. This configuration plays a high double beep when Claude needs permission and a low beep when it is done:

%USERPROFILE%\.claude\settings.jsonCopy
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{ "type": "command", "shell": "powershell",
"command": "[Console]::Beep(1320, 150); [Console]::Beep(1320, 150)" }
]
}
],
"Stop": [
{
"hooks": [
{ "type": "command", "shell": "powershell",
"command": "[Console]::Beep(660, 300)" }
]
}
]
}
}

Console.Beep takes a frequency in hertz and a duration in milliseconds, and waits until the beep is over. Anthropic’s hooks guide also shows a Windows example that opens a message box with System.Windows.Forms; their own note is that it is a dialog rather than a notification and can open behind your terminal.

macOS and Linux

Anthropic’s docs use afplay on macOS:

~/.claude/settings.jsonCopy
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [{ "type": "command", "command": "afplay /System/Library/Sounds/Glass.aiff" }]
}
],
"Stop": [
{
"hooks": [{ "type": "command", "command": "afplay /System/Library/Sounds/Pop.aiff" }]
}
]
}
}

For a visible alert, osascript -e 'display notification "Claude needs you" with title "Claude Code"' on macOS, or notify-send "Claude Code" "Claude needs you" on Linux.

Details that save you an evening

  • Stop fires a lot. It fires every time Claude finishes responding, not only when a whole task is done. If that is too chatty, use the idle_prompt notification instead. It waits about a minute and only fires if you haven’t typed.
  • Read the event if you need it. The Notification input includes message, title and notification_type, so a script can show the actual request.
  • Agent view. If you run background sessions with claude agents, it notifies you through the same preferredNotifChannel when a session starts needing input, finishes or fails, and fires the Notification hook with the agent_needs_input or agent_completed type.
  • Terminal status. Terminals that implement the OSC 7501 status protocol can show whether each Claude Code session is working, waiting or done. Claude Code v2.1.295 or later reports it automatically.
  • Hook not firing on Windows? See Claude Code hooks not working on Windows. It is almost always the shell.

Seeing which session, and answering it

A sound tells you something happened. It doesn’t tell you which of your three terminals it came from, or what Claude wants to run. Pet Island gives every Claude Code session a place on a small island at the top of your screen: working, waiting for you, or done. A permission request arrives with the command or the diff, and you allow or deny it right there; questions and plans work the same way. One click jumps to the exact terminal when you want to look closer.

FAQ

Does Claude Code have notifications?

Yes. When it finishes or waits for permission while you are away, it fires a notification. Ghostty, Kitty and iTerm2 show it as a desktop notification by default; in other terminals set preferredNotifChannel to "terminal_bell" or add a Notification hook.

How do I get a sound when Claude Code is done?

Add a Stop hook that plays a sound, for example afplay on macOS or [Console]::Beep in PowerShell on Windows.

How do I tell “needs permission” apart from “finished”?

Use a Notification hook with the permission_prompt matcher for one sound and a Stop hook for another.

Why don’t I get notifications in Windows Terminal or VS Code?

Claude Code sends desktop notifications by default only in Ghostty, Kitty and iTerm2. Set preferredNotifChannel to "terminal_bell" or use a hook.

Do notifications work inside tmux?

Yes, after you add set -g allow-passthrough on to ~/.tmux.conf.

Sources

Every setting and behavior on this page was checked against these pages on October 26, 2026. Agents change fast; if something no longer matches, the official page wins.

KEEP READING

Answer every agent from the top of your screen.

Windows and Mac · 7 days free, then $8.99 once · $1 of every sale feeds street animals

Try Pet Island free