claude-code-notifier
how it works guides faq
◐English
English العربية Deutsch Español Français עברית Italiano 日本語 한국어 Nederlands Polski Português (Brasil) Русский Türkçe Tiếng Việt 简体中文 繁體中文
Get started
All guides

Send Claude Code notifications to Telegram, Slack or Discord

Updated 31 October 2026 · 7 min read
on this page 01Before you start: the message and the secret 02Telegram: a bot that messages you 03Slack: an incoming webhook 04Discord: a channel webhook 05The hook script (Mac and Linux) 06Add the hooks 07Windows (PowerShell) 08Things to know about chat apps as a notifier 09Where Claude Code Notifier fits 10FAQ

To send Claude Code notifications to Telegram, Slack or Discord, create a bot or an incoming webhook in that app, then add a Claude Code hook that posts a short message to it with curl. A Notification hook covers "Claude needs your permission" and "Claude is waiting", and a Stop hook covers "Claude has finished". Telegram needs a bot token and your chat ID, Slack and Discord need only a webhook URL. The same script works on Mac and Linux, and a short PowerShell version covers Windows.

01Before you start: the message and the secret

Every hook receives JSON on standard input. The useful fields are hook_event_name, cwd (the project folder), message on Notification events, and last_assistant_message on Stop events. The examples below turn those into one line such as Claude needs you in my-app: Claude needs your permission to use Bash.

Bot tokens and webhook URLs are passwords: anyone who has one can post as your bot. Slack's documentation says plainly not to share webhook URLs or commit them to version control. Keep them in a separate file that only you can read:

mkdir -p ~/.claude
touch ~/.claude/chat-notify.env
chmod 600 ~/.claude/chat-notify.env

02Telegram: a bot that messages you

  1. In Telegram, open a chat with @BotFather, send /newbot, and follow the prompts. It replies with a token such as 123456789:AA....
  2. Open a chat with your new bot and send it any message, so it is allowed to message you back.
  3. Find your chat ID. Visit this URL with your token, and look for "chat":{"id": in the reply:
curl "https://api.telegram.org/bot<TOKEN>/getUpdates"
  1. Put both values in ~/.claude/chat-notify.env:
SERVICE=telegram
TELEGRAM_TOKEN=123456789:AA...
TELEGRAM_CHAT_ID=987654321

Telegram's sendMessage method takes chat_id and text (1 to 4,096 characters). It also accepts disable_notification=true, which delivers the message with no sound. The script uses that for "finished" messages and keeps the sound for permission requests.

03Slack: an incoming webhook

  1. Create a Slack app at api.slack.com/apps (or open an existing one).
  2. Under Incoming Webhooks, switch on Activate Incoming Webhooks.
  3. Click Add New Webhook to Workspace, choose a channel and select Authorize.
  4. Copy the URL that starts with https://hooks.slack.com/services/.
SERVICE=slack
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T000/B000/XXXX

Each webhook posts to one channel, chosen when you create it, and you cannot change the name or icon per message. A small private channel of your own works best, so a busy channel does not bury the alert.

04Discord: a channel webhook

  1. In your server, open Server Settings, then Integrations, then Webhooks.
  2. Create a webhook, choose the channel, and copy its URL.
SERVICE=discord
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234/abcd

Discord's execute-webhook endpoint takes a JSON body with content (up to 2,000 characters) and an optional username to override the webhook's name.

05The hook script (Mac and Linux)

Save this as ~/.claude/chat-notify.sh and run chmod +x ~/.claude/chat-notify.sh. It needs curl and jq (brew install jq, or apt install jq).

#!/bin/sh
. "$HOME/.claude/chat-notify.env"

input=$(cat)
event=$(printf '%s' "$input" | jq -r '.hook_event_name')
project=$(basename "$(printf '%s' "$input" | jq -r '.cwd')")

if [ "$event" = "Stop" ]; then
  detail=$(printf '%s' "$input" | jq -r '(.last_assistant_message // "") | .[0:300]')
  text="Claude finished in $project. $detail"
  quiet=true
else
  detail=$(printf '%s' "$input" | jq -r '.message // "Needs your attention"')
  text="Claude needs you in $project: $detail"
  quiet=false
fi

case "$SERVICE" in
  telegram)
    curl -s "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" \
      --data-urlencode "chat_id=$TELEGRAM_CHAT_ID" \
      --data-urlencode "text=$text" \
      --data-urlencode "disable_notification=$quiet" > /dev/null ;;
  slack)
    jq -n --arg t "$text" '{text: $t}' | curl -s -X POST \
      -H 'Content-Type: application/json' --data @- "$SLACK_WEBHOOK_URL" > /dev/null ;;
  discord)
    jq -n --arg t "$text" '{content: $t, username: "Claude Code"}' | curl -s -X POST \
      -H 'Content-Type: application/json' --data @- "$DISCORD_WEBHOOK_URL" > /dev/null ;;
esac
exit 0

Building the JSON with jq -n --arg matters: Claude's replies contain quotes, backslashes and newlines, and pasting them into a JSON string by hand breaks the request.

Test it before wiring it up:

echo '{"hook_event_name":"Notification","cwd":"/tmp/demo","message":"Test"}' | ~/.claude/chat-notify.sh

06Add the hooks

In ~/.claude/settings.json, inside the existing hooks object if there is one:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt|idle_prompt",
        "hooks": [{ "type": "command", "command": "~/.claude/chat-notify.sh" }]
      }
    ],
    "Stop": [
      {
        "hooks": [{ "type": "command", "command": "~/.claude/chat-notify.sh", "async": true }]
      }
    ]
  }
}

Start a new Claude Code session so the hooks load. idle_prompt and Stop overlap: Stop fires the moment Claude finishes, and idle_prompt about a minute later if you have not typed. Keep both, or drop one; the ntfy guide explains the trade-off.

07Windows (PowerShell)

Save as %USERPROFILE%\.claude\chat-notify.ps1. This version posts to Discord; change the body to @{ text = $text } and the URL for Slack.

$url = 'https://discord.com/api/webhooks/1234/abcd'
$in = [Console]::In.ReadToEnd() | ConvertFrom-Json
$project = Split-Path $in.cwd -Leaf

if ($in.hook_event_name -eq 'Stop') { $text = "Claude finished in $project." }
else { $text = "Claude needs you in ${project}: $($in.message)" }

$json = @{ content = $text; username = 'Claude Code' } | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri $url -ContentType 'application/json; charset=utf-8' `
  -Body ([Text.Encoding]::UTF8.GetBytes($json)) | Out-Null

Hook entry:

{
  "type": "command",
  "shell": "powershell",
  "command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"$HOME\\.claude\\chat-notify.ps1\""
}

Inside WSL, use the Mac and Linux script.

08Things to know about chat apps as a notifier

  • What you send leaves your computer. The "finished" message includes the start of Claude's reply. In a shared Slack or Discord channel, everyone in it can read that. Drop $detail if your code is private.
  • Chat apps batch and mute. A busy workspace or a muted server can hide the alert. A dedicated push app such as ntfy, see the ntfy guide, is less likely to get lost.
  • Hooks do not know if you are at the desk. Stop posts every time. idle_prompt and permission_prompt are the closest built-in "away" filter.

09Where Claude Code Notifier fits

A webhook is a good way to keep a log of what Claude did, and for a team it can be the right tool. For one person who wants to act on the alert, it stops short: you read that Claude needs permission, then walk back to the terminal to give it. A Telegram bot could in principle take replies, but you would be writing the hook that waits for them and returns a decision.

Claude Code Notifier does that part. With a phone paired, you allow once, allow for the session or deny a permission request, answer Claude's multiple-choice questions, and send a follow-up instruction when Claude finishes, from the phone. If you typed in the last 30 seconds the terminal asks as usual and nothing waits on the phone. It is independent, not made by Anthropic, and ccn runs on Mac, Windows and Linux. See how it compares, the ccn page and pricing.

10FAQ

Can Claude Code post to Slack without a script?

Claude Code has http hooks that POST the hook's JSON to a URL, but Slack and Discord webhooks expect their own body format (text or content), so a direct http hook to them fails. A small script or a relay in between is needed.

How do I find my Telegram chat ID?

Send your bot a message, then open https://api.telegram.org/bot<TOKEN>/getUpdates. The number after "chat":{"id": is the chat ID. For a group, add the bot to the group and send a message there first.

Can I answer Claude Code from Slack or Discord?

Not with an incoming webhook, which only posts. Answering needs a hook that waits for your reply and returns a decision, which is what remote-approval tools are built to do.

Will the hook slow Claude Code down?

The Stop entry uses "async": true, so it sends in the background. Notification hooks already run alongside Claude without blocking it.

Claude Code Notifier Get a push on your phone when Claude Code finishes or needs you, then approve, deny or answer from there. The ccn command line tool is free on Mac, Windows and Linux.
Download for iOS Download for Android Install ccn

Related guides

  • Claude Code push notifications with ntfy (do it yourself)Send Claude Code alerts to your phone with ntfy: a hook script for Mac, Windows and Linux, the settings.json entries, and how to keep the topic private.
  • Every way to get Claude Code notifications, comparedBuilt-in alerts, your own hooks, ntfy and chat webhooks, Anthropic's Remote Control and notifier apps, compared on what each can and cannot do.
  • The Claude Code Notification hook: when it fires and how to use itWhen Claude Code's Notification hook fires, what permission_prompt and idle_prompt mean, the input it gets, and why it waits before firing.
claude-code-notifier

Claude Code Notifier is an independent third-party application. It is not affiliated with, endorsed by, or sponsored by Anthropic, PBC. "Claude" and "Claude Code" are trademarks of Anthropic, PBC.

apps iOS App Android App ccn for macOS, Windows & Linux All guides
legal Privacy Policy Terms of Service Other languages © 2026 touchtap. All rights reserved. TouchTap Ltd is registered in England and Wales, company number 13942589.