AI & Development

How to Set Up Telegram Channels in Claude Code (and Fix Every Error Along the Way)

A Complete Setup Guide, Including the Problems the Docs Don't Warn You About

Complete guide to setting up Telegram as a Claude Code channel, including the silent MCP server failure, token issues, 409 conflicts, and message truncation. Every problem documented with fixes.

15 min read|March 28, 2026
Claude CodeTelegramChannels

Introduction

I just spent an evening getting Telegram working as a channel in Claude Code. If you want the backstory on why Telegram is the developer platform of choice over WhatsApp, we wrote a separate piece on that. The feature itself is great. Text your bot a message, it lands in your Claude Code session, Claude acts on it, replies back to Telegram. Bug reports become instant fixes. Deployment commands go from your pocket to production.

But the setup had friction. The kind of friction where the plugin loads, says "1 MCP server," and then silently fails. No error in the terminal. No logs to check. Just nothing.

I figured it out. Here's the full walkthrough — including every problem I hit and how to fix each one. If you're new to Claude Code, start with our complete guide to Claude Code first, then come back here.

What you're building

By the end of this guide, you'll have a Telegram bot connected to your Claude Code session. You message the bot. Claude reads your message, has full access to your project files and tools, does the work, and replies back in Telegram.

Channels connect external messaging platforms to a running Claude Code session through MCP (Model Context Protocol). Once connected, the bot acts as a bridge between Telegram and your terminal. It works standalone or alongside Remote Control:

# Channels only
claude --channels plugin:telegram@claude-plugins-official

# Channels + Remote Control
claude --remote-control --channels plugin:telegram@claude-plugins-official

# Channels + Server mode
claude remote-control --spawn worktree --channels plugin:telegram@claude-plugins-official

If you want to understand how Channels and Remote Control compare (and when to use each), our Remote Control vs Channels comparison covers that in detail.

Prerequisites

Before starting, confirm the following:

  1. A recent Claude Code version with Channels support. Check with claude --version. If you use the native install, run claude update. If you are still on the older npm-based install, migrate to Anthropic's native installer first.
  2. A Claude Pro, Max, Team, or Enterprise plan. API keys do not support Channels.
  3. Bun installed. The Telegram plugin runs on Bun, not Node. Install with curl -fsSL https://bun.sh/install | bash, then restart your terminal.
  4. A Telegram account on your phone.

Verify Bun is available:

bun --version

If this returns nothing or "command not found", Bun is not in your PATH. Restart your terminal or add Bun's install directory to your shell profile.

Step 1: Create the Telegram bot

Open Telegram on your phone and search for @BotFather. Start a conversation and send:

/newbot

BotFather walks you through naming your bot. Pick whatever you want. The name doesn't affect functionality. The username must end in "bot" (e.g., my_claude_bot). When it's done, you get a token that looks like this:

123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Copy that token. You'll need it in Step 3.

Step 2: Install the Telegram plugin

Inside a Claude Code session, run these two commands:

/plugin marketplace add anthropics/claude-plugins-official
/plugin install telegram@claude-plugins-official

The first adds the official plugin marketplace. The second installs the Telegram channel from it. You'll see output confirming the install.

If either command fails, check your Claude Code version. Both require v2.1.81 or later. Our development environment setup guide walks through getting Claude Code installed from scratch if you need it.

Step 3: Configure the bot token

Still inside Claude Code:

/telegram:configure <your-bot-token>

Paste in the full token from BotFather. This writes it to ~/.claude/channels/telegram/.env and sets file permissions to 600 (owner-only read/write, since the token is a credential).

After saving, reload the plugin:

/reload-plugins

You should see 1 plugin MCP server in the output.

Step 4: Pair your Telegram account

Open Telegram on your phone and DM your bot. Send any message. "Hello" works fine.

The bot replies with a six-character pairing code. Back in Claude Code, approve it:

/telegram:access pair <code>

Then lock access down so nobody else can pair:

/telegram:access policy allowlist

Now only your Telegram account can reach the bot. Anyone else who DMs it gets silently ignored.

Step 5: Start Claude Code with Channels enabled

Exit your current session and restart with the channel flag:

claude --channels plugin:telegram@claude-plugins-official

Or if you're using Remote Control (which I'd recommend — our article on deploying from your phone covers why):

claude --remote-control --channels plugin:telegram@claude-plugins-official

DM your bot again. This time, your message goes straight into the Claude Code session. Claude reads it, works on it, and replies back in Telegram.

That's the happy path. If everything above worked on the first try, skip ahead to the access system reference. If it didn't — and there's a good chance it didn't — keep reading.

Problem 1: MCP server fails silently

You run /reload-plugins, it reports 1 plugin MCP server, but the MCP tools never appear. No error message in the terminal. The server silently fails to start.

The Telegram plugin's .mcp.json file uses bun run --cwd ${CLAUDE_PLUGIN_ROOT} start to launch the server. On certain Bun versions (including 1.3.x), the --cwd flag doesn't resolve package.json scripts from the target directory. Bun looks for the start script in your current working directory instead of the plugin directory, finds nothing, and exits with "Script not found." Claude Code swallows that error. You see nothing.

If you've read our guide on hooks, MCP, and custom commands, you'll know MCP server configuration can be finicky. This is a prime example.

Here's how to fix it.

Find the plugin cache directory:

ls ~/.claude/plugins/cache/claude-plugins-official/telegram/

You'll see a version folder (like 0.0.1). Open the .mcp.json file inside it:

~/.claude/plugins/cache/claude-plugins-official/telegram/0.0.1/.mcp.json

Change it from:

{
  "mcpServers": {
    "telegram": {
      "command": "bun",
      "args": ["run", "--cwd", "${CLAUDE_PLUGIN_ROOT}", "--shell=bun", "--silent", "start"]
    }
  }
}

To:

{
  "mcpServers": {
    "telegram": {
      "command": "bash",
      "args": ["-c", "cd \"${CLAUDE_PLUGIN_ROOT}\" && bun install --no-summary && bun server.ts"]
    }
  }
}

This bypasses the --cwd bug by changing directory with cd first, then running the server directly instead of going through package.json scripts.

Run /reload-plugins after saving. Verify it works by testing the server manually:

cd ~/.claude/plugins/cache/claude-plugins-official/telegram/0.0.1
bun run server.ts

If it prints telegram channel: polling as @yourbotname, the server works. If it prints TELEGRAM_BOT_TOKEN required, see Problem 2.

Problem 2: TELEGRAM_BOT_TOKEN required

The server starts but immediately exits because it can't find the bot token.

The token should live at ~/.claude/channels/telegram/.env. If /telegram:configure didn't create it (or the directory doesn't exist), the server has nothing to authenticate with.

Create the file manually:

mkdir -p ~/.claude/channels/telegram
echo "TELEGRAM_BOT_TOKEN=your-token-here" > ~/.claude/channels/telegram/.env
chmod 600 ~/.claude/channels/telegram/.env

Replace your-token-here with the actual token from BotFather. The chmod 600 keeps the token readable only by your user account.

Problem 3: 409 Conflict — another instance is polling

The server logs 409 Conflict and retries repeatedly, or silently fails to connect.

Telegram only allows one bot instance to poll for updates at a time. If a previous Claude Code session crashed, got killed, or you ran the server manually for testing, a zombie bun process may still be holding the polling slot.

Find and kill the orphan process:

ps aux | grep "bun.*server.ts" | grep -v grep

If you see a process, grab its PID (second column) and kill it:

kill <pid>

Then /reload-plugins. The new instance picks up the polling slot within a few seconds.

The server has built-in retry logic for 409 errors, backing off up to 15 seconds between attempts. If you restart Claude Code normally (not a crash), the old process gets a shutdown signal and releases the slot. The zombie problem only happens when processes die unexpectedly.

Problem 4: Bot responds to nothing

You DM the bot on Telegram and get no response. No pairing code, no error, nothing.

The MCP server isn't actually running, even though /reload-plugins reported it. This is Problem 1 in disguise.

Check if the bot process is actually running:

ps aux | grep "bun.*server.ts" | grep -v grep

If nothing shows up, the server isn't running. Go back to Problem 1 and fix the .mcp.json file. After fixing, run /reload-plugins and DM the bot again.

Problem 5: Pairing code expired

You receive the pairing code from Telegram but when you run /telegram:access pair <code>, Claude Code says the code is expired or not found.

Pairing codes expire after one hour. DM the bot again. It generates a new code. Approve that one instead.

Problem 6: Message truncation

Claude's reply in Telegram starts normally but stops mid-sentence. No error or warning. The response just ends.

Channels run through MCP. MCP tool results have size limits. When Claude's response exceeds that limit, the tail end gets silently dropped. You don't know what you missed.

Short responses (quick commands, confirmations, brief status updates) are unaffected. Longer responses (code reviews, detailed status summaries, multi-file explanations) may be truncated without warning.

There is no fix on the Channels side because it's an MCP protocol limitation. For any request that needs a detailed response, use Remote Control instead. Remote Control streams full responses through Anthropic's API with no intermediary protocol truncation.

Run both together:

claude --remote-control --channels plugin:telegram@claude-plugins-official

Telegram handles the quick stuff. Switch to Remote Control in the Claude app for anything that needs a complete response. This combined approach is what I use to ship client websites from my phone.

The access system explained

The Telegram channel has three access modes:

ModeBehaviourWhen to use
pairingAnyone who DMs the bot gets a pairing code. You approve codes individually.Initial setup only.
allowlistOnly approved sender IDs can reach the bot. No new pairing codes issued.Production use. Always end on this.
disabledBot ignores all DMs.When you want to fully deactivate the channel.

You should always end up on allowlist. The pairing mode is temporary. It exists so you can capture Telegram user IDs you don't already know. Once everyone is added, lock it.

All access commands:

/telegram:access                    # Show current status
/telegram:access pair <code>        # Approve a pairing code
/telegram:access allow <id>         # Add a sender ID directly
/telegram:access remove <id>        # Remove a sender
/telegram:access policy pairing     # Re-enable pairing (temporary)
/telegram:access policy allowlist   # Lock to allowlist only
/telegram:access policy disabled    # Disable all access

If you need to add someone later: flip to pairing, have them DM the bot, approve their code, flip back to allowlist.

Key file locations

Every file the Telegram channel depends on:

FilePurpose
~/.claude/channels/telegram/.envBot token storage. Must have chmod 600.
~/.claude/plugins/cache/claude-plugins-official/telegram/0.0.1/.mcp.jsonMCP server launch configuration. Edit this to fix the silent startup failure (Problem 1).
~/.claude/plugins/cache/claude-plugins-official/telegram/0.0.1/server.tsThe actual Telegram bot server script.

If you're troubleshooting and not sure where to start, check these three files in order. The .env confirms your token is saved. The .mcp.json confirms the server launch command is correct. The server.ts is the file you can run directly to test outside of Claude Code.

Known limitations

Five things to be aware of before relying on Channels in production:

  1. Channels use MCP, which has size limits on tool results. Long responses get silently cut off. No fix available, so use Remote Control for detailed responses.
  2. Telegram allows only one bot instance polling at a time. If a previous session crashes, you must manually kill the zombie process before a new session can connect.
  3. The plugin requires Bun, not Node. This is an additional install step that catches people off guard, especially on teams where Node is the standard runtime.
  4. Multiple failure modes (bad .mcp.json, missing token, crashed MCP server) produce no visible error in Claude Code. Debugging requires manual process checks and direct server testing.
  5. If you edit .mcp.json to fix Problem 1, updating the plugin may reset the file to the broken default. Re-apply the fix after any plugin update.

For a deeper look at how Claude Code handles security and enterprise deployment patterns, including MCP server isolation, that article covers the security model behind these tools.

Quick reference

Every command from this guide in one place:

# Prerequisites
bun --version                       # Verify Bun is installed
claude --version                    # Verify Claude Code version

# Install plugin
/plugin marketplace add anthropics/claude-plugins-official
/plugin install telegram@claude-plugins-official

# Configure bot token
/telegram:configure <bot-token>
/reload-plugins

# Pair and lock access
/telegram:access pair <code>
/telegram:access policy allowlist

# Start with Channels
claude --channels plugin:telegram@claude-plugins-official

# Start with Channels + Remote Control
claude --remote-control --channels plugin:telegram@claude-plugins-official

# Start with Channels + Server mode
claude remote-control --spawn worktree --channels plugin:telegram@claude-plugins-official

# Debug: test server manually
cd ~/.claude/plugins/cache/claude-plugins-official/telegram/0.0.1
bun run server.ts

# Debug: check for zombie processes
ps aux | grep "bun.*server.ts" | grep -v grep

# Debug: verify token file exists
cat ~/.claude/channels/telegram/.env

What it looks like in practice

Once everything is connected, the workflow is simple. You text your bot:

"What's the status of the homepage?"

Claude reads your project, checks the files, and replies in Telegram with the answer. You can send follow-ups:

"Fix the spacing on the hero section and push to main."

Claude makes the changes, commits, pushes, and confirms in the Telegram thread. If you're running Remote Control alongside Channels, you can also see the full session in the Claude app on your phone. That's useful when you want to review a diff before approving a push.

This is the same workflow I use when building full-stack applications with Claude Code. Telegram for quick fire-and-forget commands during the day. Remote Control for the review-and-deploy sessions where I need to see everything.

Bug reports from clients? Forward them to your bot. Feature requests? Same. Quick deployments while you're at lunch? Text the bot. The phone becomes your terminal.

If you're running multiple client projects, server mode with Git worktrees keeps each session isolated so one project's changes never bleed into another.


I build websites and web applications for service businesses and law firms at Luminous Digital Visions. If you want to see what this workflow can do for your next project, book a free 30-minute call.

Related Articles

Need Help Implementing This?

Our team at Luminous Digital Visions specializes in SEO, web development, and digital marketing. Let us help you achieve your business goals.

Get Free Consultation