Telegram channel: support multiple bots (per-project configuration)

Status Open
Maintainer reply None cached
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/.env within 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

View original on GitHub ↗

7 Comments

kamalptw · 5 months ago

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):

const STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join(homedir(), '.claude', 'channels', 'telegram')

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:

BEFORE:  Load token → MCP connect → Start bot
AFTER:   MCP connect (get roots) → Resolve config (project → global) → Load token → Start bot

Config resolution would check:

  1. <workspace-root>/.claude/channels/telegram/.env (project-scoped)
  2. ~/.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:

{
  "env": {
    "TELEGRAM_STATE_DIR": "${CLAUDE_PROJECT_DIR}/.claude/channels/telegram"
  }
}

The existing TELEGRAM_STATE_DIR env var override (line 26) means the plugin change is minimal — just update .mcp.json to include the fallback logic.

Pro: Minimal plugin change; benefits all channel plugins.
Con: Requires a Claude Code core change.

Backward Compatibility

  • If no project-level config exists, falls back to global (zero-config upgrade)
  • Existing global setups continue working unchanged
  • /telegram:configure skill would gain --scope project|global flag
  • Project-level access.json is independent (different bot = different allowlist)

Questions for maintainers

  1. Is Approach A or B preferred? (Or a third option?)
  2. Should project-level config be in <project>/.claude/channels/telegram/ or somewhere else?
  3. Any concerns about the boot sequence restructuring in Approach A?

Happy to submit a PR once aligned on direction.

HappySookie · 4 months ago

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! 🙏

julianleopold · 4 months ago

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 .env and access.json. The key is setting TELEGRAM_STATE_DIR in the shell environment before Claude Code starts — the MCP plugin picks it up from there:

export TELEGRAM_STATE_DIR="$HOME/.claude/channels/telegram-${bot_name}"
claude --chat

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.

HappySookie · 4 months ago

Thanks @julianleopold — your TELEGRAM_STATE_DIR tip really helped me get
this 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_DIR for
full 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/ needs bun install run manually
— without node_modules, the MCP server silently dies ~5 seconds after
connecting. 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 @.***>님이 작성:

julianleopold left a comment (anthropics/claude-code#37173) <https://github.com/anthropics/claude-code/issues/37173#issuecomment-4187100419> 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 .env and access.json. The key is setting TELEGRAM_STATE_DIR in the shell environment before Claude Code starts — the MCP plugin picks it up from there: export TELEGRAM_STATE_DIR="$HOME/.claude/channels/telegram-${bot_name}" claude --chat 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. — Reply to this email directly, view it on GitHub <https://github.com/anthropics/claude-code/issues/37173#issuecomment-4187100419>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/BR5ADQ2E7BMBCMP3XLCYRHD4UEDDBAVCNFSM6AAAAACW2FHE36VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DCOBXGEYDANBRHE> . You are receiving this because you commented.Message ID: @.***>
cversek · 4 months ago

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_DIR environment variable (server.ts line 26), though it's not documented.

Working setup:

  1. Create a separate bot per project via @BotFather
  2. In each project's .claude/settings.local.json, set the env var:
{
  "env": {
    "TELEGRAM_STATE_DIR": "/path/to/project/.claude/channels/telegram"
  },
  "channelsEnabled": true,
  "enabledPlugins": {
    "telegram@claude-code-plugins": true
  }
}
  1. Put .env (with TELEGRAM_BOT_TOKEN=...) and access.json in that directory
  2. Launch each project with claude --channels

Both sessions run simultaneously, each polling its own bot. No 409 conflicts.

The gap is that /telegram:access hardcodes ~/.claude/channels/telegram/access.json and ignores TELEGRAM_STATE_DIR (#42641). So pairing has to be done by editing access.json manually. 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

alexgodlewski · 4 months ago

would be great to have this

astanford · 4 months ago

+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.