Claude Code notifications: get told when it finishes or needs you, on your desktop, phone or Telegram

Dmitriy Solodukha · checked against Caprock v0.140.1

Get a Claude Code notification when it finishes or waits for approval: the built-in alert, Notification hooks, phone push, Telegram, and Caprock's free alerts.

Claude Code already tells you when it finishes or needs permission: in iTerm2, Ghostty and Kitty it sends a desktop notification, and in any other terminal you set preferredNotifChannel to "terminal_bell" or add a Notification hook. For your phone, Remote Control sends push notifications; for Telegram, use a Channels plugin or a hook that calls your own bot.

The built-in notification: terminal bell, iTerm2, Ghostty, Kitty

When Claude finishes a task or stops at a permission prompt and you seem to be away from the terminal, Claude Code fires a notification. With the default setting, "auto", it is a desktop notification in iTerm2, Ghostty and Kitty, a bell in Terminal.app only when its audible bell is off, and nothing anywhere else — Windows Terminal, Warp and VS Code's terminal included.

To get a bell in any terminal, add this to ~/.claude/settings.json, or pick Local notifications in /config:

{
  "preferredNotifChannel": "terminal_bell"
}
  • The other values: iterm2, iterm2_with_bell, kitty, ghostty and notifications_disabled.
  • Over SSH the notification still reaches your own machine. Ghostty and Kitty pass it to the OS with no setup; iTerm2 needs forwarding turned on: Settings → Profiles → Terminal, check Notification Center Alerts, then Filter Alerts → Send escape sequence-generated alerts.
  • Inside tmux add set -g allow-passthrough on to ~/.tmux.conf, or the notification never leaves tmux.
  • Still silent: check that the terminal app has notification permission in your OS settings.

A notification hook for macOS, Linux and Windows

A Notification hook runs your own command, in any terminal, next to the built-in notification rather than instead of it. It runs even with notifications_disabled. This is Anthropic's macOS example, for ~/.claude/settings.json:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
  • Linux: notify-send 'Claude Code' 'Claude Code needs your attention'. It needs a notification daemon, which SSH sessions and containers usually lack; on Debian and Ubuntu it comes in libnotify-bin.
  • Windows: a PowerShell dialog box, which can open behind the terminal:
"command": "powershell.exe -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code needs your attention', 'Claude Code')\""
  • macOS shows nothing? osascript notifies through Script Editor. Run osascript -e 'display notification "test"' once, then allow Script Editor in System Settings → Notifications.

The hook gets message, title and notification_type on stdin. /hooks shows whether it loaded; the hooks guide covers the format and why a hook does not run.

Notification when done, or when it needs permission: pick the matcher

An empty matcher fires on every notification type. To choose, set it to one of these:

When each Notification matcher fires, from the hooks reference, read 20 October 2026.
MatcherFires
permission_prompta permission prompt has waited about six seconds
idle_promptabout 60 seconds after Claude finished, if you have not typed
elicitation_dialogan MCP server's form has waited about six seconds
agent_completeda background session finishes or fails, while agent view is open
  • Both waits are on purpose: in a terminal session the alert comes only when you seem to be away, and each keystroke pushes permission_prompt back.
  • Told at once: a PermissionRequest hook runs the moment Claude asks for permission, with no six-second gate.
  • A Stop hook runs every time Claude finishes responding, even when you are watching, and not when you interrupt it. For "notify me when done", idle_prompt is the quieter choice; it does not fire while a background subagent is still running.

Phone push notifications with Remote Control

When a session is connected through Remote Control, Claude can push to your phone:

  • 1. Install the Claude app on iOS or Android and sign in with the account you use for Claude Code.
  • 2. Allow notifications when the phone asks.
  • 3. In the terminal, run /config and turn on Push when Claude decides (a long task finished, or a decision needed), Push when actions required (permission prompts and questions), or both.

Claude decides when to push, and beyond those two switches there is no per-event setting. It skips the push while you are typing in or focused on the connected terminal. If /config says No mobile registered, open the app once.

Remote Control needs a Pro, Max, Team or Enterprise plan — "API keys are not supported" — and does not run on Bedrock, Google Cloud's Agent Platform, Microsoft Foundry or behind a gateway in ANTHROPIC_BASE_URL. It pushes only for the sessions you connected. Working from the phone is covered in Claude Code on your phone.

Claude Code Telegram, the official way: Channels

Channels push messages from a chat app into a running session, and Claude answers back in the same chat. Telegram, Discord and iMessage are included. They are a research preview: the --channels flag is not in claude --help, and its syntax may change. They need Bun, a claude.ai login or a Console API key, and are not on Bedrock, Google Cloud's Agent Platform or Microsoft Foundry. On Team and Enterprise an Owner has to enable them.

  1. 1

    Create a bot: message @BotFather, send /newbot, copy the token

  2. 2

    Install the plugin, at Claude Code's prompt

  3. 3

    Save the token to ~/.claude/channels/telegram/.env

  4. 4

    Restart Claude Code with the channel on

  5. 5

    Message your bot, then pair with the code it replies

  6. 6

    Let only your account in

The official plugin also relays permission prompts: a message with See more, Allow and Deny, while the terminal dialog stays open and the first answer wins. Anyone on the allowlist can approve tool use in your session.

What it does not do: events reach only the session started with --channels, and only while it is open. A session you started without the flag, in another terminal, sends nothing.

A Telegram bot from a hook

For one-way alerts you do not need Channels. Create a bot with @BotFather, send it any message — a bot cannot start a chat — and read your chat id from https://api.telegram.org/bot<token>/getUpdates. Export TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID in your shell profile: a hook inherits Claude Code's environment, so the token stays out of settings.json and out of the repository.

Save as ~/.claude/hooks/telegram.sh and run chmod +x on it. It needs jq:

#!/bin/bash
# Notification hook: forward Claude Code's notification to your Telegram bot.
# TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID come from your environment.
input=$(cat)
project=$(basename "$(jq -r '.cwd' <<<"$input")")
text=$(jq -r '.message' <<<"$input")
curl -s -o /dev/null "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
  -d chat_id="$TELEGRAM_CHAT_ID" \
  --data-urlencode text="Claude Code · $project: $text"
exit 0

Register it in ~/.claude/settings.json. "async": true sends it in the background, so a slow network never holds up the session:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt|idle_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "$HOME/.claude/hooks/telegram.sh",
            "async": true
          }
        ]
      }
    ]
  }
}

Given a hand-written permission event for a folder called my-app, the script builds Claude Code · my-app: Claude needs your permission to use Bash. Telegram reads every word of what you send, so keep the text to what you would show it. The hook runs in every session that loads your user settings.

What Caprock adds: notifications with Approve and Deny

Caprock is a free desktop app for macOS, Windows and Linux that records every coding agent on the machine, the sessions it did not start included, and puts the ones waiting on you first. When a Claude Code session stops on a permission prompt, the app shows a system notification naming the project, the session and what it wants to do: Bash: go test ./..., the file an edit would change, or the question it asked. It covers every Claude Code session on the machine, and stays quiet for the session you are looking at.

On macOS, for a permission prompt in a Claude Code session Caprock started, the notification carries buttons (a question Claude asks you gets none):

  • Approve answers yes without bringing Caprock forward. It is offered only when the notification shows the whole request on one line; a longer command offers Open in Caprock instead, so you read it first.
  • Deny answers no.
  • A click opens the session, with Claude Code's own prompt in its terminal and Caprock's approval card under it.

A notification never offers "always allow", since that would write a rule to your settings. If the prompt was answered meanwhile — in the terminal, on the card, from a phone — the button says Already answered. Linux shows the same buttons where the desktop draws them. On Windows a notification has no buttons; a click opens the session, with Yes and No on the card when Caprock started it.

Two more signals stay on screen while you work elsewhere:

  • The badge. The Dock icon (a dot on the Windows taskbar) counts the sessions that need you — a permission prompt, a question, a plan to approve or a turn that stopped on an error — and clears when none do. A turn that ended asking nothing is Done: it stays listed, quieter, and is not counted.
  • The menu bar. On macOS the count sits beside the icon (2 waiting), joined by a plan window once it is 80% full. A click opens a panel with what needs you first, what is running with its cost, and the Claude and Codex plan windows.

A turn that ends on a question reads Needs your answer; a Done turn raises no notification. Settings → Desktop notifications has one switch, When a session needs you, on by default.

Caprock's Telegram alerts for every session, free

Away from the computer, Caprock sends phone alerts through your own Telegram bot. In Caprock, open Settings → Telegram, paste the token from @BotFather, send your bot the six-digit code Settings shows, tick the alerts you want, then Send a test alert.

  • Waiting for approval: a message at once, from Claude Code's PermissionRequest hook — once per question, so a burst of prompts in one session is one message.
  • Finished: a message after a minute with nothing new, so replying straight away sends nothing. A turn that ended on a question is titled Needs your answer; to skip turns that asked nothing, turn off Also when it asked nothing (Done).
  • Every Claude Code session on the machine, started in any terminal, not only the ones Caprock started. Each kind has its own tick.
  • No spam: at most one alert of a kind per session every three minutes, and 20 an hour; the twentieth says the rest are held.
  • Free. No licence is checked.

A message names the agent, project and session, then what happened, the folder and branch, and for an approval the command or file it asks about (up to 100 characters); a link to the session comes when phone access is on. A finished run, from Caprock's docs (example figures):

🟠 Claude Code · caprock · Fix the cache test
✅ Finished
~/dev/caprock · main
4m · $0.62 · 12 tool calls
2 files changed: cache.go, cache_test.go
💬 The cache test was reading a stale fixture; fixed and green.

A switch turns off the reply's first line; tool output is never sent. The message goes from your machine to Telegram's API, through no server of ours, and nothing is sent until you set up a bot. On the machine, Caprock's Home screen marks any session at a permission dialog waiting for approval, with the call it asks about.

What it does not cover: Codex and OpenCode sessions send no alerts, and no desktop notifications either. The two signals alerts are built on, a permission dialog and a finished turn, come only from Claude Code's hooks, so Caprock's hooks have to be installed; the app asks once. A failed send shows in Settings and is not retried. To answer the prompt, open the link, or answer it with a button from a paired phone for sessions Caprock started; with Premium, Approve and Deny under the Telegram message answer it too.

Which one to use

  • At the desk, one terminal: the built-in notification, or terminal_bell outside iTerm2, Ghostty and Kitty.
  • A sound or a custom command: a Notification hook.
  • Away, on a claude.ai plan, for a session you connected: Remote Control push.
  • Talk to Claude from Telegram: Channels, if a research preview is fine and you start that session with --channels.
  • Several sessions at the desk, answered from the notification: Caprock's app, with Approve and Deny on macOS and Linux and a badge counting what waits.
  • Telegram alerts for every Claude Code session, any plan, with no script to keep: Caprock.

Caprock is free and open source, and nothing leaves your machine until you switch an alert on. Install Caprock.

Questions people ask

How do I get notified when Claude Code is done?
In iTerm2, Ghostty and Kitty Claude Code sends a desktop notification by default. Elsewhere, set preferredNotifChannel to terminal_bell, or add a Notification hook with the idle_prompt matcher, which fires about 60 seconds after Claude finishes if you have not typed.
Why don't I get Claude Code notifications in Windows Terminal or VS Code?
With the default setting Claude Code sends desktop notifications only in iTerm2, Ghostty and Kitty. Set preferredNotifChannel to terminal_bell, or add a Notification hook that runs a PowerShell or notify-send command.
Can Claude Code send push notifications to my phone?
Yes, through Remote Control: install the Claude app, sign in with the same account, and turn on Push when Claude decides or Push when actions required in /config. Remote Control needs a Pro, Max, Team or Enterprise plan; API keys are not supported.
How do I connect Claude Code to Telegram?
Install the official Telegram channel plugin, configure your BotFather token, and start Claude Code with claude --channels plugin:telegram@claude-plugins-official. Channels are a research preview and need Bun. For one-way alerts, a Notification hook that calls the Telegram Bot API is enough.
Can I approve a Claude Code permission prompt from a notification?
With Caprock's desktop app on macOS and Linux, yes, for Claude Code sessions Caprock started: the notification carries Deny, and Approve when it shows the whole request on one line. On Windows a click opens the session, where a session Caprock started shows Yes and No buttons.
Can I get a Telegram alert for every Claude Code session without a hook?
With Caprock, yes, free: Settings → Telegram sends a message through your own bot when any Claude Code session on the machine waits for approval or has finished, at most 20 an hour, with no tool output in it.

Sources

Try it

The record of every coding agent you run, the sessions it did not start included. Free, open source; nothing leaves your machine.

Download for Mac

Notarized by Apple. One file for Apple silicon and Intel, macOS 13 or later.

Or run it yourself:

curl -fsSL https://caprock.dev/mac.sh | sh

Paste in Terminal: it installs Caprock and opens it.Or with Homebrew: brew install --cask dspv/tap/caprock-app