Three Rough Edges of Running Claude Code + Telegram MCP on Windows: A 200-Line Toolkit
I talk to Claude Code through Telegram every day.
Not as a side channel — Atlas and DropPin, two of our products, were essentially shipped this way: I throw a line into Telegram from my phone, Claude commits, pushes, and deploys from the desktop. I might be at a coffee shop, on a plane, or on a German train (the 7-day distributed shipping experiment is exactly that story).
From shipping updates while traveling, to dropping ideas after I get home, to remembering at 1am which PR I need to follow up on, Telegram is my most-used Claude Code interface. More than the terminal.
A few months in, I noticed three small papercuts on Windows. None of them are bugs — they're all gaps between OS behavior and plugin assumptions. Individually each is trivial. Together they produce the "it was connected, then it wasn't, then it was again" annoyance.
This morning I happened to reboot, and Claude and I fixed all three. Then I packaged it into a small open-source repo:
→ github.com/ppcvote/claude-tg-windows
Here's the story behind each one.
Papercut #1: A flurry of CMD windows on every login
My Startup folder holds a few auto-start .bat files:
-
claude-telegram-startup.bat— TG plugin health check -
ig_dashboard_autostart.bat— MindThread's Flask backend -
openclaw-keepalive.bat— wakes WSL2 for the OpenClaw agent fleet
Every Windows login, all three pop a CMD window briefly. Self-closing, no real harm, but the boot animation is now a strobe of black-and-white flashes. Annoying.
Root cause: Windows executing a .bat directly always opens a console window. Even if the .bat internally uses start "" /MIN ... to minimize spawned children, the .bat itself still gets a console for that brief moment.
The fix is small but requires one indirection:
-
Move all
.batfiles out of the Startup folder to a regular working dir (I use%USERPROFILE%\boot-scripts\). -
Keep only
.vbslaunchers in the Startup folder, calling the.batfiles viaWshShell.Run "cmd /c ...", 0, False. - That
0inwindowstyle=0means "completely hidden."
Set WshShell = CreateObject("WScript.Shell")
batPath = WshShell.ExpandEnvironmentStrings("%USERPROFILE%\boot-scripts\claude-telegram-startup.bat")
WshShell.Run "cmd /c """ & batPath & """", 0, False
8 lines of VBScript. Done. Next reboot: black desktop, no flicker.
Papercut #2: Telegram polling dies after a while
This one took longer to figure out.
Symptom: open Claude Code in the morning, TG works fine; come back at noon, Claude is still alive, the Telegram bot is still alive, but messages just don't arrive. Outbound still sends. Inbound dead.
Eventually traced it: the TG MCP plugin uses long-poll mode on getUpdates. Telegram allows only one active poller per bot token at any time. If two bun.exe processes are both polling, each call's result goes to one of them at random and the other comes back empty.
Why would there be two? Most often, an orphan from the previous Windows session. Windows soft restart, Claude Code crash, VS Code force-close — child processes don't always die with the parent. Next time you open Claude Code, the new bun spawns and the old one is still alive. Two pollers racing.
Fix: run a health check on boot to kill orphans:
orphans=$(ps aux 2>/dev/null | grep -i "[t]elegram.*server" | grep -i "bun" | awk '{print $2}')
if [ -n "$orphans" ]; then
echo "$orphans" | xargs kill -9
fi
This health-check.sh is called by the silent .vbs launcher 15 seconds after login (so the network is ready). About 20 lines of bash total. Clean.
Papercut #3: Opening two Claude sessions zombies you
Papercut #2 was orphans from a previous Windows session. Papercut #3 is zombies you create right now.
Scenario: I already have a Claude session running in VS Code, TG connected fine. For some reason (a demo, checking a log, casual testing) I run claude in another terminal. The second Claude also spawns its own TG plugin — now two bun instances are fighting for polling, and the first session starts dropping messages.
This kind of zombie can't be caught by a boot-time check — it spawns during an active session. You need continuous monitoring.
Fix: a PowerShell script that finds every bun.exe whose command line matches the Telegram plugin path. If more than one exists, keep the newest and kill the rest:
$wrappers = @(Get-CimInstance Win32_Process -Filter "Name='bun.exe'" | Where-Object {
$_.CommandLine -match 'claude-plugins-official[\\/]telegram'
})
if ($wrappers.Count -le 1) { exit 0 }
$sorted = $wrappers | Sort-Object CreationDate -Descending
$keep = $sorted[0]
$kill = $sorted[1..($sorted.Count - 1)]
foreach ($w in $kill) {
Get-CimInstance Win32_Process -Filter "ParentProcessId=$($w.ProcessId)" | ForEach-Object {
Stop-Process -Id $_.ProcessId -Force
}
Stop-Process -Id $w.ProcessId -Force
}
Wire it into Task Scheduler, every 2 minutes:
schtasks /Create /TN TGZombieKiller /TR "powershell -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File ..." /SC MINUTE /MO 2 /F
Safety precondition: you only ever run one Claude Code session at a time. True for me. If it's true for you, this script is pure upside.
Why open-source 200 lines of glue
I'll be honest, I hesitated. The Telegram MCP plugin itself is Anthropic's work — that's where the real engineering lives. My 200 lines are just glue: PowerShell + Bash + VBScript, no real depth anywhere.
But after Claude and I finished it this morning, I told it "I feel like I didn't really do much," and the reply was roughly: "The volume is small, but this is the result of months of you actually using it. For the next Windows user who hits any of these papercuts, those 200 lines save them hours of debugging."
Fair point. So: open-sourced. MIT. One-shot install.ps1, idempotent, has -Uninstall.
→ github.com/ppcvote/claude-tg-windows
If you're also running Claude Code + Telegram MCP on Windows and have hit any of the three — take it. Issues and PRs welcome.
Ultra Lab's open-source footprint grows one post at a time. From UltraProbe to the Microsoft Agent Governance Toolkit PR to today's small toolkit. Not every contribution is a flagship — but every "thing we've battle-tested" is worth writing down.
Originally published on Ultra Lab — we build AI products that run autonomously.
Try UltraProbe free — our AI security scanner checks your website for vulnerabilities in 30 seconds: ultralab.tw/probe
Top comments (0)