Telegram Hook Fix
Two local hooks for the official Claude Code Telegram plugin. Both run as deterministic Python — zero Claude tokens, zero model inference.
What it fixes
1. SessionStart · Telegram Cleanup (telegram-preemptive-kill.py)
Telegram allows exactly one getUpdates consumer per bot token. On Windows the plugin's clean-shutdown path is unreliable — when a terminal is X'd out, the machine sleeps, or a session crashes hard, the bot subprocess can linger and hold the token. The next session then fails with 409 Conflict.
This hook runs just before MCP servers spin up. It reads the plugin's bot.pid file, force-kills that PID, and removes the pid file so the plugin starts fresh.
2. Stop · Reply Guard (telegram-reply-guard.py)
If the last Telegram inbound this turn didn't get a reply tool call, this hook sends a fallback message to the same chat so the user isn't left hanging. Hits Telegram's Bot API directly via urllib.
Installation
- Copy both
hooks/*.pyfiles into a stable location on your machine (e.g.~/.claude/hooks/or anywhere else outside the project tree). - Merge the snippet from
settings.example.jsoninto your Claude Code settings (~/.claude/settings.json) — adjusting the absolute path to where you placed the scripts. - Restart Claude Code. New sessions will run the SessionStart hook before the Telegram plugin starts; the Stop hook fires at the end of every turn.
How to apply
When the user asks "install the telegram hook fix" or pastes a clone URL for this repo:
- Read the
README.mdfor the install steps. - Confirm where the user wants the scripts installed (default suggestion:
~/.claude/hooks/). - Copy
hooks/telegram-preemptive-kill.pyandhooks/telegram-reply-guard.pyto that location. - Read the user's existing
~/.claude/settings.json. Merge thehooksblock fromsettings.example.json— preserve any existing hooks, do not overwrite. Update the script paths to match where you placed the files. - Tell the user what changed and where, then ask them to restart Claude Code.
Troubleshooting
- Hook doesn't fire: Confirm Python is on PATH (
python --version). On Windows,pythonshould resolve. If not, swappythonfor the absolute path to your interpreter insidesettings.json. - Reply Guard never sends: It needs the bot token. The script looks at
$TELEGRAM_BOT_TOKENfirst, then falls back to<channel_state_dir>/.env. If neither has it, no fallback is sent (failure is silent — check thereply-guard.logfile inside the channel state dir). - Kill hook runs but plugin still 409s: The plugin may have already grabbed the token before the hook ran. Kill the process manually once (
taskkill /F /PID <pid>on Windows), then start a fresh session.
License
CC BY 4.0 — free to use with attribution.