MindSwarm
Engineering Blog

How We Built a 24/7 Claude Code Telegram Bot on a Free Oracle VM

Anthropic's official Telegram plugin silently fails on headless Linux servers. Here's how we diagnosed the bug, built a workaround, and now run Claude Code as a Telegram bot that never sleeps.

The Problem: Telegram Plugin + Linux = Silence

Claude Code v2.1.81 ships with an official Telegram channel plugin. On Windows and macOS, it works beautifully:

User (Telegram) → @Bot → Grammy polling → MCP notification → Claude Code → reply tool → Telegram

We wanted to run this on a free Oracle Cloud VM so Claude is available 24/7 — not just when a laptop is open. The setup was straightforward:

claude --channels plugin:telegram@claude-plugins-official \
       --model sonnet --permission-mode bypassPermissions

Everything looked correct. The MCP server connected. Grammy started polling. The bot received messages. But Claude never responded.

The Bug (Still Unfixed as of March 2026)

mcp.notification({method: 'notifications/claude/channel'}) is sent by the plugin but never reaches Claude Code on headless Linux. Grammy receives the message, gate() passes it, the notification fires into the void. Zero errors in logs. Complete silence.

What We Tried (Nothing Worked)

  1. Updated Claude Code to latest (2.1.81)
  2. Manually installed the plugin from source into ~/.claude/plugins/cache/
  3. Verified enabledPlugins in settings.json
  4. Confirmed access.json with correct allowlist
  5. Ran in tmux, screen, direct SSH — same result
  6. Restarted Claude Code multiple times

Root Cause (Our Best Theory)

The MCP stdio transport layer on Linux doesn't properly handle async notifications when Claude Code is idle at the prompt. This likely works on desktop because the GUI has a different event loop. On headless Linux, the notification gets written to stdout but Claude Code doesn't read it until the next user input.

This is a known architectural limitation, not a simple config issue. We reported it — no fix yet.

The Solution: ccgram + Hooks Architecture

Instead of waiting for Anthropic to fix the plugin, we built an alternative using ccgram and Claude Code's hook system:

User (Telegram) → @Bot → ccgram (Node.js) → tmux send-keys → Claude Code
Claude Code → hooks (Stop/Permission) → ccgram → Bot API → Telegram
Why This Works

Instead of relying on MCP notifications (broken on Linux), ccgram injects messages directly into Claude Code's terminal via tmux send-keys. Hooks fire on real Claude Code events (task completion, permission requests) and trigger notification scripts. No MCP notification layer needed.

Step 1: Install ccgram

# On Oracle VM (free tier: 1 core, 1GB RAM, 45GB disk)
npm install -g @jsayubi/ccgram
ccgram init  # Interactive setup: bot token + chat ID

Step 2: Configure Hooks

Add to ~/.claude/settings.json:

{
  "hooks": {
    "PermissionRequest": [{
      "hooks": [{
        "type": "command",
        "command": "node ~/.ccgram/dist/permission-hook.js",
        "timeout": 120
      }]
    }],
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "node ~/.ccgram/dist/enhanced-hook-notify.js completed",
        "timeout": 5
      }]
    }]
  }
}

Step 3: Launch in tmux

# Terminal 1: ccgram bot
tmux new-session -d -s ccgram \
  'cd ~/.ccgram && node dist/workspace-telegram-bot.js'

# Terminal 2: Claude Code
tmux new-session -d -s claude \
  'claude --model sonnet --dangerously-skip-permissions'

That's it. Claude Code is now a 24/7 Telegram bot running on a free VM.

Plugin vs. ccgram: Side-by-Side

FeatureOfficial Pluginccgram + Hooks
Windows/MacWorksWorks
Headless LinuxBrokenWorks
Photo supportYesNo
Permission approvalVia MCPVia Telegram buttons
Task notificationsLimitedFull (hooks)
Requires tmuxNoYes
Setup complexityLowMedium
24/7 on free VMNoYes

What This Enables: Always-On AI Agent

With this setup, we run Claude Code as a permanent agent on an Oracle Cloud free-tier VM. From Telegram, we can:

Total cost: $0/month. Oracle free tier gives you 2 VMs with 1GB RAM each — more than enough for Claude Code + ccgram.

Lessons Learned

  1. Don't wait for vendors to fix bugs. We spent 6 hours debugging the plugin before building the workaround in 30 minutes.
  2. Hooks are more powerful than plugins. Claude Code's hook system (21 event types) gives you full lifecycle control without depending on MCP notification transport.
  3. tmux is underrated. It's the simplest bridge between a bot process and an interactive CLI. No WebSocket servers, no IPC, just send-keys.
  4. Free VMs are production-ready. Oracle's Always Free tier runs 24/7. We've had 50+ days uptime.

Want AI Agents That Run 24/7?

MindSwarm orchestrates Claude, Gemini, and Codex across multiple VMs with self-healing infrastructure, persistent memory, and Telegram control.

Learn More About MindSwarm