anotifier / guides / claude-code-notifications
[ GUIDE · CLAUDE CODE ]
Claude Code logo

Claude Code notifications: get alerted when it finishes or needs you

Claude Code fires two hook events you can alert on: Stop when it finishes a turn, and Notification when it needs your permission or input. Add both to ~/.claude/settings.json with a command that shows a banner, plays a sound or sends a push, or run npx anotifier@latest setup, the Claude Code notifier, to wire both for you. Ghostty, Kitty and iTerm2 also show a built-in desktop notification, and preferredNotifChannel can ring the terminal bell elsewhere. Below: which event fires when, banner, sound or phone, every option with configs, snooze and quiet hours, and fixes when nothing arrives.

Rather skip the manual setup? One command wires every agent you have installed to desktop toasts, phone push, and Slack, Discord or Telegram:

$ npx anotifier@latest setup

Updated 2026-10-16 · also see the Claude Code notifier and the full docs

Quick answer: what you want, which event, where to read more

You wantClaude Code eventRead this
An alert when Claude finishes a turnStopOption 2 below, or npx anotifier@latest setup
An alert when it needs permission or an answerNotification, matcher permission_promptPermission and waiting-for-input notifications
A sound, nothing elseStop and Notification, or preferredNotifChannelClaude Code notification sound
A push on your phoneAny hook, posting to ntfyPhone push with ntfy and the phone page
A message in Slack, Discord or TelegramAny hook, posting to a webhookSlack, Discord, Telegram
A real toast on Windows or WSLAny hook, plus a toast backendWindows and WSL notifications
A banner on macOS or LinuxAny hook, running osascript or notify-sendmacOS and Linux notifications
A warning before a usage limit or auto-compactNeither: a statusline command, not a hookUsage limit warning and auto-compact warning
Alerts that never arriveCheck the hook is registeredNotifications not working

Which Claude Code event fires when

Claude Code runs a hook when one of its lifecycle events happens. Two matter for alerts. Stop fires when Claude finishes responding. Notification fires when Claude Code sends a notification, and its payload names the kind in notification_type:

Event or typeFires whenGood for
StopClaude finishes responding. The payload includes last_assistant_message, the final replyThe done alert
Notification, permission_promptClaude needs you to approve a tool use and the prompt has waited about six secondsThe needs-permission alert
Notification, idle_promptClaude finished about 60 seconds ago and you haven't typed sinceA late reminder, not the done alert
Notification, elicitation_dialogAn MCP server opens a form and you haven't typed for about six secondsA question from a tool
Notification, auth_successAuthentication completesNothing: filter it out

An empty matcher runs the hook for every notification type, so a bare Notification hook also fires for auth_success and the rest. Set "matcher": "permission_prompt" to alert on approvals only. Because idle_prompt arrives about a minute after Stop, use Stop for the done alert. The permission notifications guide lists every type with its timing, including how Claude Desktop and the VS Code extension differ from the terminal.

Banner, sound or phone: pick one or all

ChannelWhat you getHow
Terminal bellA beep in the terminal, no text"preferredNotifChannel": "terminal_bell" (sound guide)
Desktop bannerA toast with a title and a line of textA hook that runs osascript, notify-send or PowerShell (Option 2)
Phone push (ntfy)A push on Android or iOS; free, no accountA hook that POSTs to a topic (Option 3)
Slack, Discord, TelegramA chat messageA webhook URL; anotifier has a format for each (Option 4)

Claude Code also has its own phone push. With Remote Control active, /config offers Push when Claude decides and Push when actions required, and the Claude app on iOS or Android gets the push. It needs a Pro, Max, Team or Enterprise plan; API keys are not supported (Remote Control docs). The hooks in this guide need no Remote Control session.

Option 1: Claude Code's built-in terminal notifications

When Claude finishes or pauses for a permission prompt and you appear to be away from the terminal, Claude Code sends a desktop notification, but by default only in Ghostty, Kitty, and iTerm2. In any other terminal, set preferredNotifChannel in ~/.claude/settings.json to ring the terminal bell instead:

{ "preferredNotifChannel": "terminal_bell" }
  • Ghostty and Kitty pass the notification to your OS notification center with no setup. iTerm2 needs Settings > Profiles > Terminal > Notification Center Alerts checked, with Send escape sequence-generated alerts enabled under Filter Alerts.
  • The notification reaches your local machine over SSH, so a remote session can still alert you.
  • Inside tmux, add set -g allow-passthrough on to ~/.tmux.conf, or the notification never reaches the outer terminal.

What you get: a beep or a plain banner on the machine you are sitting at, with no project name, no message content, and nothing on your phone. Terminals without the built-in notification, such as Warp or the VS Code integrated terminal, need the bell or a hook. For the bell, custom sounds, and turning them off, see the Claude Code notification sound guide; for what the hooks do inside the editor, see anotifier in VS Code.

Option 2: a Stop and Notification hook you write yourself

Hooks are shell commands Claude Code runs on lifecycle events, configured under hooks in ~/.claude/settings.json. A minimal macOS example, one banner for Stop and one for Notification:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude finished\" with title \"Claude Code\"'"
          }
        ]
      }
    ],
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude needs your input\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
  • macOS: osascript banners come from Script Editor. If Script Editor has no notification permission, the command fails silently and macOS never asks. Run osascript -e 'display notification "test"' once, then allow Script Editor in System Settings > Notifications.
  • Linux: use notify-send "Claude Code" "Claude finished". It needs a desktop notification daemon, which headless servers, SSH sessions, and most containers lack; install libnotify-bin on Debian and Ubuntu if the command is missing.
  • Windows: Claude Code's docs use a PowerShell MessageBox, which is a dialog box and can open behind your terminal. A real toast needs a PowerShell module such as BurntToast. Inside WSL, powershell.exe must be reachable through Windows interop. Claude Code notifications on Windows and WSL covers both roads, Do not disturb, and fixes.

The hook receives a JSON payload on stdin: session_id, cwd, transcript_path, and for Notification the message and notification_type. Stop also carries last_assistant_message, so a script can put Claude's own words in the banner. Type /hooks in Claude Code to check what is registered. To alert only on approvals, add "matcher": "permission_prompt" to the Notification entry (see which event fires when).

Option 3: a push notification to your phone with ntfy

ntfy is a free, open-source push service with Android and iOS apps and no account. Install the app, subscribe to a topic name only you know, and make the hook POST to it:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -s -d 'Claude finished' -H 'Title: Claude Code' https://ntfy.sh/your-secret-topic"
          }
        ]
      }
    ]
  }
}

Because public ntfy.sh topics are guessable, send generic text only, or run your own ntfy server before putting conversation content in the body. The ntfy phone push guide covers topics, privacy and a self-hosted server.

Option 4: anotifier, all of the above in one command

npx anotifier@latest setup

The wizard detects Claude Code, registers the Stop and Notification hooks in ~/.claude/settings.json (backing the file up first), checks the desktop toast backend for your OS, and offers to create an ntfy topic for phone push. Restart Claude Code and you are done. It also works as a Claude Code plugin: /plugin marketplace add DevinoSolutions/anotifier-for-claude-codex-cursor then /plugin install anotifier@anotifier. The same setup covers Codex CLI, Cursor and Gemini CLI, and the webhook channel reaches Slack, Discord and Telegram.

  • Done alerts say what Claude said. For Claude Code the toast and the webhook carry the last assistant message, and the title names the project, as in my-app · Claude Code. ntfy stays generic by default because public topics are guessable; ntfy.richContent opts in.
  • Approvals are urgent, reminders are not. A permission_prompt arrives as an urgent "Needs your permission". The idle_prompt reminder is delivered at default priority. auth_success sends nothing, and a notification type Claude Code adds later still alerts.

Searching for ccnotify? Several unrelated Claude Code tools share that name, and none of them is anotifier. ccnotify: which one is which tells them apart and compares each with anotifier.

FeatureBuilt-inDIY hookanotifier
Desktop toastTerminal-dependentYes, fixed textYes, Windows · macOS · Linux · WSL
Phone pushNoWith a curl to ntfyYes, ntfy, generic by default
Slack / Discord / TelegramNoWrite the JSON yourselfYes, pick a format
Shows what the agent saidNoNoYes for Claude Code (toast + webhook)
Names the projectNoHard-code itYes, my-app · Claude Code in every title
Urgent for approvals, calm for doneNoTwo hooks, two scriptsYes, per-event priority
Click to focus the windowNoNoYes (Windows)
Every agent, one configNoRepeat per agentYes
Snooze / quiet hoursNoNoYes
Setup time1 setting10–20 min per agentOne command

anotifier is free, open source (AGPL-3.0), has zero dependencies, and uninstalls cleanly with anotifier uninstall. Full reference in the docs.

Quiet the noise: the idle reminder, snooze and quiet hours

Three controls in anotifier, none of which can stall Claude Code: the hook still exits successfully when a run is silenced.

  • Turn the idle reminder up or down. events.needs_input.idleReminderPriority sets the level for the idle_prompt reminder only (min, low, default, high or urgent). Permission prompts keep their own priority.
  • Snooze. anotifier snooze 2h silences every channel (toast, ntfy, webhook and the terminal bell) until it expires. 30m, 90s and a bare 45 (minutes) work too; anotifier snooze off cancels it, and anotifier status shows whether you are snoozed.
  • Quiet hours. A nightly window, off by default, in your machine's local time. It may span midnight, and it silences all channels or none.
{
  "quietHours": {
    "enabled": true,
    "from": "22:00",
    "to": "08:00"
  },
  "events": {
    "needs_input": {
      "idleReminderPriority": "low"
    }
  }
}

Put that in ~/.anotifier/config.json. Snooze and quiet hours work independently, and either one alone silences the run. The docs list every config key.

When nothing arrives

  1. Restart Claude Code after changing hooks, then type /hooks and confirm the hook is listed under Stop and Notification.
  2. Built-in notifications only appear in Ghostty, Kitty and iTerm2. Elsewhere set preferredNotifChannel to terminal_bell or add a hook; inside tmux turn on allow-passthrough.
  3. Expect delays by design: permission_prompt waits about six seconds and each keystroke defers it, and idle_prompt comes about 60 seconds after Claude finishes.
  4. With anotifier, anotifier status shows which tools are wired and whether you are snoozed, anotifier test fires a test notification (add toast, ntfy, webhook, bell or both to test one channel), and anotifier doctor diagnoses each channel.
  5. On Windows or WSL see the Windows and WSL fixes; on macOS or Linux see macOS and Linux notifications. The troubleshooting guide works through the rest in order.

Claude Code notification questions

How do I get a notification when Claude Code finishes?

Add a Stop hook to ~/.claude/settings.json that runs a notification command. Stop fires when Claude finishes responding. Or run npx anotifier@latest setup, which registers the Stop and Notification hooks and wires a desktop toast, a terminal bell and optional phone push.

How do I get notified when Claude Code needs permission?

Add a Notification hook with "matcher": "permission_prompt". It fires once an approval prompt has waited about six seconds, so a prompt you answer right away does not ping you. anotifier sends it as an urgent "Needs your permission" alert. The permission notifications guide covers every notification type.

Can I get Claude Code notifications on my phone?

Yes, two ways. A hook can post to ntfy, a free push service with Android and iOS apps and no account; anotifier creates the topic for you. Or use Claude Code's own mobile push: with Remote Control active, enable Push when Claude decides or Push when actions required in /config. That needs a Pro, Max, Team or Enterprise plan.

Why does the notification arrive a minute late or not at all?

The idle_prompt notification is sent about 60 seconds after Claude finishes, and only if you haven't typed since, so alerting on Notification alone feels a minute late. Use a Stop hook for the done alert. If nothing arrives, restart Claude Code, check /hooks, and run anotifier doctor; the built-in desktop notification only works in Ghostty, Kitty and iTerm2.

Can I send Claude Code alerts to Slack, Discord or Telegram?

Yes. anotifier posts to a Slack, Discord or Telegram webhook, or to any HTTP endpoint with an optional Authorization header. Set webhook.format to slack, discord, telegram or generic. The Slack, Discord and Telegram pages have the steps.

How do I silence Claude Code notifications at night?

With anotifier, run anotifier snooze 8h to silence every channel for a while, or enable quietHours in ~/.anotifier/config.json for a nightly window such as 22:00 to 08:00. Both silence the toast, ntfy, webhook and terminal bell together, and neither can stall Claude Code.

Does this work with Codex, Cursor and Gemini CLI too?

Yes. One anotifier setup wires Claude Code, Codex CLI, Cursor and Gemini CLI to the same channels. Codex alerts on Stop and PermissionRequest, Gemini CLI on AfterAgent and Notification, and Cursor when a run finishes only, because it has no needs-input event.

Can I get a notification with what Claude actually said?

Yes. The hook payload includes the transcript path. anotifier reads the last assistant message (or the question, for needs-input events) from it and puts that in the toast and webhook body, with the project name in the title. ntfy stays generic unless you set ntfy.richContent.

Does this work when Claude Code runs inside VS Code?

Yes. Hooks are part of Claude Code itself and fire identically in the VS Code extension and the integrated terminal. anotifier adds click-to-focus on Windows so the toast brings the right window forward.

Will notifications slow Claude Code down?

Not noticeably. Claude Code waits for the hook to exit, and anotifier sends every channel in parallel, each with its own 5 to 7 second timeout. It registers its hook with a 10-second timeout (Claude Code's default for command hooks is 600 seconds) and always exits 0, so it can never stall a session.

Can Claude Code play a sound when it finishes?

Yes. Set preferredNotifChannel to terminal_bell for the terminal bell, or add a Stop hook that plays a sound file, such as afplay /System/Library/Sounds/Glass.aiff on macOS. The notification sound guide has commands for Linux and Windows.

Try it

One command wires Claude Code and every other agent you have installed.

npx anotifier@latest setup

Other guides