Claude Code Telegram Notification Hook
push.tgClaude Code can run a shell command whenever it finishes or needs your input. Point that command at a Telegram endpoint and you can leave a long task running, make coffee, and get a ping on your phone the moment Claude is done or stuck on a permission prompt. Checked against the official Claude Code hooks reference (October 2026).
Step 1: get your endpoint (30 seconds)
Open @trafficRobot in Telegram and press Start. You get an address like k3x9q@push.tg. Your endpoint is the part before the @: https://push.tg/k3x9q. Every example below uses k3x9q, so swap in your own key.
There's no bot to create, no chat_id to look up and no token to keep safe. Add @trafficRobot to a group and the group gets its own address, so the whole team sees the alerts.
You need jq and curl (brew install jq / apt install jq).
Step 2: add two hooks
Open ~/.claude/settings.json (applies to every project) or .claude/settings.json in a repo (that project only), and merge in:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "jq -r '\"✅ Claude Code finished: \" + (.cwd | split(\"/\") | last) + \"\\n\\n\" + ((.last_assistant_message // \"\")[:300])' | curl -s -m 10 --data-binary @- https://push.tg/k3x9q >/dev/null",
"async": true
}
]
}
],
"Notification": [
{
"matcher": "permission_prompt|idle_prompt",
"hooks": [
{
"type": "command",
"command": "jq -r '\"⏳ Claude Code: \" + (.message // \"needs your attention\") + \" (\" + (.cwd | split(\"/\") | last) + \")\"' | curl -s -m 10 --data-binary @- https://push.tg/k3x9q >/dev/null",
"async": true
}
]
}
]
}
}That's it. Next time Claude finishes a turn you get "✅ Claude Code finished: myproject" plus the start of its reply. When it's blocked on a permission you get "⏳ Claude Code: Claude needs your permission to use Bash (myproject)".
How it works
- Stop fires when Claude finishes responding. Its stdin JSON includes
cwdandlast_assistant_message(the text of Claude's final reply). Stop doesn't take a matcher; it fires every time. - Notification fires when Claude Code shows a notification. The matcher
permission_prompt|idle_promptlimits it to "needs permission" and "waiting for your input". The JSON hasmessage,titleandnotification_type. "async": trueruns the command in the background, so a slow network never delays Claude.>/dev/nullmatters. Without it, push.tg's reply{"ok":...}would land on stdout, and Claude Code tries to read hook stdout as JSON.
Variations
Only ping for long tasks: Claude Code also passes session_id, so you can write a small script that records a start time on UserPromptSubmit and only sends on Stop if more than 5 minutes have passed.
Send to a team chat: add @trafficRobot to the group and use the group's address instead.
Using Codex or Cursor too? The AI agents page in the list below has tested configs for both.
Check that the message really arrived. push.tg answers HTTP 200 even when the key is wrong. The body says {"error":"no such user"} instead of {"ok":...}. So a green "test sent" in your tool doesn't prove delivery. Look at Telegram.
More copy-paste guides
- Claude Code, Codex and Cursor: Get a Telegram Message When Your AI Agent Finishes
- Uptime Kuma Telegram Alerts Without a Bot Token
- Healthchecks.io Alerts to Telegram
- Proxmox Notifications to Telegram with a Webhook Target
- Home Assistant Telegram Notification Without a Bot
- n8n Error Workflow: Telegram Alert When a Workflow Fails
- Grafana Alerts to Telegram with a Custom Webhook Payload
- Cron Job Failure Alert to Telegram (cron and systemd)
- GitHub Actions and GitLab CI Telegram Notification in One Line
- Synology NAS Email Alerts to Telegram
- Nagios Alerts to Telegram with curl
- Python: Get a Telegram Notification When Training Finishes
- How to Receive Email in Telegram Without Giving Out Your Real Address
- Send Server Alerts to Telegram with One curl Command
Get your endpoint: t.me/trafficRobot?start=tg-claude-code. It takes 30 seconds, it has no ads, and it has been running since 2016.