The right service for where you are right now.
From a 48-hour website launch to ongoing growth and automation. Start with what you need, add more when you are ready.
From a 48-hour website launch to ongoing growth and automation. Start with what you need, add more when you are ready.
Every industry gets a custom setup — not a template with your logo swapped in. Website, automation, and lead capture tailored to your vertical.
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.
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.
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.
Before starting, confirm the following:
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.curl -fsSL https://bun.sh/install | bash, then restart your terminal.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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 Telegram channel has three access modes:
| Mode | Behaviour | When to use |
|---|---|---|
pairing | Anyone who DMs the bot gets a pairing code. You approve codes individually. | Initial setup only. |
allowlist | Only approved sender IDs can reach the bot. No new pairing codes issued. | Production use. Always end on this. |
disabled | Bot 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.
Every file the Telegram channel depends on:
| File | Purpose |
|---|---|
~/.claude/channels/telegram/.env | Bot token storage. Must have chmod 600. |
~/.claude/plugins/cache/claude-plugins-official/telegram/0.0.1/.mcp.json | MCP server launch configuration. Edit this to fix the silent startup failure (Problem 1). |
~/.claude/plugins/cache/claude-plugins-official/telegram/0.0.1/server.ts | The 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.
Five things to be aware of before relying on Channels in production:
.mcp.json, missing token, crashed MCP server) produce no visible error in Claude Code. Debugging requires manual process checks and direct server testing..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.
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
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.
A practical walkthrough of using Claude Code's Remote Control, Channels, and server mode to build and deploy client websites entirely from a phone. Includes step-by-step setup instructions.
Remote Control and Channels both let you control Claude Code from your phone, but they solve different problems. After using both daily, here's how they compare and which one to start with.
Telegram's bot API lets you ship AI integrations in an afternoon. WhatsApp's requires a week of business verification. As AI assistants move from novelty to utility, that gap decides which platform developers build on first.
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