Telegram channel: support multiple bots (per-project configuration)
Status Open
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
Activity 7 comments · opened Mar 21, 2026
Feature Request
Current behavior:
The Telegram channel reads a single bot token from ~/.claude/channels/telegram/.env, shared globally across all Claude Code instances. Only one bot can be active at a time.
Desired behavior:
Support multiple Telegram bots, ideally with per-project configuration. This would allow users who run different Claude Code instances in different directories to have a dedicated bot for each project context.
Use case:
Users working across multiple projects (e.g., personal life system, work repo A, work repo B) want separate Telegram bots so messages route to the correct Claude Code session without ambiguity.
Possible approaches:
- Per-project channel config (e.g.,
.claude/channels/telegram/.envwithin the project or a project-scoped override) - A config file that maps bot tokens to project directories
- Multiple named channel instances (e.g.,
telegram/personal,telegram/work)
🤖 Generated with Claude Code
7 Comments
Proposing to implement this
I've analyzed the Telegram channel plugin architecture (
server.ts) and have two viable approaches. Looking for maintainer guidance on which direction is preferred before submitting a PR.Current Architecture
All state paths derive from a single
STATE_DIR(line 26):The token is loaded at boot (lines 31-52) before MCP transport connects, so there's no project context available at token-load time.
Approach A: Use MCP workspace roots (plugin-only change)
Restructure the boot sequence to delay token loading until after MCP
initialize, which provides workspace roots:Config resolution would check:
<workspace-root>/.claude/channels/telegram/.env(project-scoped)~/.claude/channels/telegram/.env(global fallback)Same for
access.json,approved/,inbox/.Pro: Self-contained in the plugin, no Claude Code core changes needed.
Con: Requires restructuring the startup sequence; bot polling starts later.
Approach B: Add
${CLAUDE_PROJECT_DIR}template variable (Claude Code + plugin change)Add a new template variable in Claude Code's MCP server spawner, then use it in
.mcp.json:The existing
TELEGRAM_STATE_DIRenv var override (line 26) means the plugin change is minimal — just update.mcp.jsonto include the fallback logic.Pro: Minimal plugin change; benefits all channel plugins.
Con: Requires a Claude Code core change.
Backward Compatibility
/telegram:configureskill would gain--scope project|globalflagaccess.jsonis independent (different bot = different allowlist)Questions for maintainers
<project>/.claude/channels/telegram/or somewhere else?Happy to submit a PR once aligned on direction.
I tried running two separate Claude Code Telegram bots on one machine using tmux sessions with different TELEGRAM_STATE_DIR environment variables.
What worked:
The server correctly stored pairing data in the custom state directory
Bot token was read from the separate .env file
What didn't work:
The /telegram:configure and /telegram:access skills have hardcoded paths (~/.claude/channels/telegram/), so they always read/write to the default location
The MCP server plugin doesn't inherit the TELEGRAM_STATE_DIR environment variable from the tmux session
Suggestion: If the skills and MCP plugin respected TELEGRAM_STATE_DIR, multi-bot setups would work without any code changes to the server itself.
Would love to see official multi-bot support! 🙏
I'm running a multi-bot setup on a headless Mac with 3 worker bots + 1 admin bot. Here's how I work around these issues:
Each bot gets its own config directory (
~/.claude/channels/telegram-{name}/) with its own.envandaccess.json. The key is settingTELEGRAM_STATE_DIRin the shell environment before Claude Code starts — the MCP plugin picks it up from there:The hardcoded skills (
/telegram:configure,/telegram:access) I haven't fully worked around — they still default to~/.claude/channels/telegram/. I configure those files manually per bot. Day-to-day it works fine since the MCP server respects the env var.An admin bot acts as orchestrator — I message it on Telegram and it dispatches worker bots into specific project folders, each in their own tmux window with isolated state. It also handles stop/send, per-bot sandboxing, a relay for blocking prompts, and health monitoring via a watchdog.
I'm building this into a tool called hivectl — planning to add a UI for managing the agent swarm and a simple install path so others can set this up easily. Happy to share more details if interested.
Thanks @julianleopold — your
TELEGRAM_STATE_DIRtip really helped me getthis working.
I'm not a developer — just a curious non-dev who uses Claude Code heavily
via Telegram. So getting a second bot running was quite a journey for me.
With help from Claude Code itself, I ended up using
CLAUDE_CONFIG_DIRforfull filesystem separation instead of sharing
~/.claude/:Bot 1: ~/.claude/ (main bot)
Bot 2: ~/ddochi/.claude/ (backup bot, via CLAUDE_CONFIG_DIR)
Each bot has its own tmux session, Claude Code process, and completely
isolated config/plugins/channels.
One gotcha worth sharing: the telegram plugin in
marketplaces/external_plugins/telegram/needsbun installrun manually— without
node_modules, the MCP server silently dies ~5 seconds afterconnecting. That one took a while to figure out.
Interested in hivectl — sounds like a great tool for people like me who
want multi-bot setups without deep technical knowledge.
2026년 4월 4일 (토) 오후 10:14, julianleopold @.***>님이 작성:
We ran into this exact scenario this week — two Claude Code agents on the same Mac, each needing its own Telegram bot. The plugin already supports this via the
TELEGRAM_STATE_DIRenvironment variable (server.ts line 26), though it's not documented.Working setup:
.claude/settings.local.json, set the env var:.env(withTELEGRAM_BOT_TOKEN=...) andaccess.jsonin that directoryclaude --channelsBoth sessions run simultaneously, each polling its own bot. No 409 conflicts.
The gap is that
/telegram:accesshardcodes~/.claude/channels/telegram/access.jsonand ignoresTELEGRAM_STATE_DIR(#42641). So pairing has to be done by editingaccess.jsonmanually. Once that skill is fixed, this workflow is clean.Wrote up the full procedure with examples: https://github.com/cversek/cc-telegram-channel-tutorial#multiple-bots-per-project-channel-configuration
would be great to have this
+1 We have a similar use case; multiple repos / projects on a single system. @cversek has already documented this; I'd be happy to implement the fix if I thought it would be adopted.