ChannelHub

ChannelHub simplifies managing multiple Claude Code sessions from a single interface.

ChannelHub

⚠️ Beta Software — ChannelHub is in active development. Expect bugs, breaking changes, and rough edges. Bug reports and contributions are welcome. Do not rely on it for critical workflows yet.

A multi-session channel plugin for Claude Code that lets you manage all your Claude sessions from one place — Telegram, web dashboard, or CLI.

The problem: Claude Code channels are 1:1 — one bot per session. If you run multiple projects, you need multiple bots or keep switching.

The solution: ChannelHub runs a single daemon that accepts connections from all your Claude sessions. Send messages, approve permissions, upload files, and spawn agent teams — all from one Telegram bot or web dashboard.

Features

  • Multi-session management — all Claude sessions visible in one dashboard
  • Telegram bot — send messages, approve permissions, upload photos/documents from your phone
  • Web dashboard — real-time chat, permission prompts, session status, file upload
  • Permission relay — approve/deny tool use from Telegram or web (native MCP channel protocol)
  • Agent teams — spawn teams of Claude instances with shared task coordination
  • Session routing — switch between projects, broadcast to all, or target specific sessions
  • CLI — manage sessions from the terminal
  • Prompt tags — toggle instructions (use superpowers, TDD, be concise) appended to messages

How It Works

You (Telegram / Web / CLI)
       ↓
Hub Daemon (manages everything)
  ├── Socket Server (Unix socket)
  │     ↕ shim ↔ Claude session A
  │     ↕ shim ↔ Claude session B
  │     ↕ shim ↔ Claude session C
  ├── Telegram Bot
  ├── Web Dashboard
  └── Permission Engine

Each Claude session runs with --channels server:hub. The hub's shim (MCP server) bridges Claude's stdio to the daemon via Unix socket. The daemon routes messages between your frontends and all connected sessions.

Prerequisites

Before installing, make sure you have:

  • Bun >= 1.0 — the installer will offer to install it for you if missing
  • tmux — required for daemon and session management
    • Debian/Ubuntu: apt install tmux
    • RHEL/Fedora: dnf install tmux
    • macOS: brew install tmux
  • Claude Code with claude.ai login
  • git — to clone the repository
  • jq (recommended) — for automatic config updates
  • A Telegram bot token (optional) — create one with @BotFather if you want the Telegram frontend

Quick Install

One-liner that handles everything:

curl -fsSL https://raw.githubusercontent.com/mahdi-awadi/channelhub/main/install.sh | bash

This will:

  1. Check prerequisites (install Bun if missing)
  2. Clone ChannelHub to ~/.channelhub
  3. Install dependencies
  4. Create config template at ~/.claude/channels/hub/config.json
  5. Register the MCP server in ~/.claude.json
  6. Install the channelhub command to ~/.local/bin

Configure

Edit ~/.claude/channels/hub/config.json and add your Telegram token and user ID:

{
  "webPort": 3000,
  "telegramToken": "<bot-token-from-botfather>",
  "telegramAllowFrom": ["<your-telegram-user-id>"],
  "defaultTrust": "ask",
  "defaultUploadDir": "."
}

Get your Telegram user ID by messaging @userinfobot.

Start

channelhub start              # Start the daemon in tmux
channelhub status             # Check if it's running
channelhub attach             # View daemon logs (Ctrl+B then D to detach)

Connect Claude Code

In any project folder:

claude --dangerously-load-development-channels server:hub

Your session appears in the dashboard at http://localhost:3000 immediately.

CLI Commands

channelhub start       # Start daemon
channelhub stop        # Stop daemon
channelhub restart     # Restart daemon
channelhub status      # Status
channelhub attach      # Attach to daemon tmux
channelhub update      # Pull latest and restart
channelhub list        # List sessions
channelhub send <name> "message"
channelhub spawn <name> <path>
channelhub trust <name> auto

Manual Install

If you prefer to install manually instead of the one-liner:

git clone https://github.com/mahdi-awadi/channelhub.git ~/.channelhub
cd ~/.channelhub
bun install

# Create config
mkdir -p ~/.claude/channels/hub
cp config.example.json ~/.claude/channels/hub/config.json
$EDITOR ~/.claude/channels/hub/config.json

# Register MCP server — add to ~/.claude.json mcpServers:
# "hub": { "command": "bun", "args": ["run", "~/.channelhub/src/shim.ts"] }

# Start daemon
tmux new-session -d -s hub-daemon "bun run ~/.channelhub/src/daemon.ts"

Telegram Bot Commands

CommandDescription
/listShow sessions, pick active (inline buttons)
/statusDashboard with session details
/spawn <name> <path> [team-size]Launch Claude in tmux
/kill <name>Stop a session
/team <name> [add]Show team status or add teammate
/trust <name> [auto|ask]Toggle auto-approve permissions
/prefix <name> <text>Set command prefix for a session
/rename <old> <new>Rename a session
/all <message>Broadcast to all sessions
/verify <name>Run the session's verification commands (tests, typecheck, lint)

Message routing:

  • Plain text goes to your active session
  • /<session-name> message targets a specific session
  • Send a photo or document to upload it to the active session's project folder

Verification

Running /verify <session> executes the session's profile-defined verification commands against the session's project directory. If the applied profile has no commands, the runner auto-detects them from the project's package.json scripts (test, typecheck, lint).

Commands run sequentially and stop on the first failure. You get back on success, or a failure message containing the failed command, exit code, and the last 20 lines of merged stdout/stderr on failure. Per-command timeout is 120 seconds.

Built-in profiles with defaults:

  • carefulbun test, bunx tsc --noEmit
  • tddbun test, bunx tsc --noEmit
  • docs / yolo — no commands (probe decides from package.json)

Web Dashboard

Access at http://localhost:<webPort> (or via reverse proxy).

  • Telegram login — only allowlisted users can access
  • Session sidebar — status dots, team grouping, [+] to add teammates
  • Chat view — send messages, see replies, permission prompts with Allow/Always Allow/Deny
  • File upload — clip button or drag-and-drop
  • Prompt tags — toggleable pills (Superpowers, TDD, Concise, etc.)
  • Spawn dialog — directory browser, team checkbox

Permission Relay

When Claude wants to run a tool (Bash, Write, etc.), the permission prompt appears in both the terminal AND your Telegram/web dashboard. You can approve from either place — first response wins.

Claude wants to use Bash → permission_request → Hub → Telegram/Web
You click Allow → Hub → Claude proceeds
  • Trusted sessions (auto-approve): auto-allowed, you never see the prompt
  • Untrusted sessions (ask): forwarded with Allow / Always Allow / Deny buttons

Agent Teams

Spawn multiple Claude instances that work together:

  • Web UI: check "Run as team" when spawning, set team size
  • Telegram: /spawn myproject /home/user/project 3 (1 lead + 2 teammates)
  • Add teammates later: [+] button in web, or /team myproject add in Telegram

The hub monitors ~/.claude/tasks/ for agent team task files and displays progress.

Configuration

FieldTypeDefaultDescription
webPortnumber3000Web dashboard and API port
telegramTokenstring""Bot token from @BotFather
telegramAllowFromstring[][]Telegram user IDs allowed. Empty = deny all. The Telegram frontend refuses to start and web auth rejects every login when this list is empty.
defaultTrust"ask" | "auto-approve""ask"Default permission mode for new sessions
defaultUploadDirstring"."Upload directory relative to project root

Config file: ~/.claude/channels/hub/config.json

CLI

HUB_URL=http://localhost:3000 bun run src/cli.ts <command>
CommandExample
listShow all sessions
statusDetailed session info
spawn <name> <path>Launch Claude in tmux
kill <name>Stop a session
send <name> <message>Send message to session
trust <name> autoSet auto-approve
prefix <name> <text>Set command prefix
rename <old> <new>Rename session
upload <name> <file>Upload file to project

Security Model

ChannelHub runs as you on your own machine and treats anyone who can authenticate as having your shell. Accordingly:

  • The web server binds to 127.0.0.1 only. It is not reachable from the LAN. Remote access must go through a reverse proxy or tunnel (see below).
  • Authentication is cookie-based. Logging in via the Telegram Login Widget verifies an HMAC and sets an HttpOnly, SameSite=Strict session cookie signed with your bot token. Every /api/* request and WebSocket upgrade requires that cookie; unauthenticated requests return 401.
  • telegramAllowFrom is deny-by-default. Leaving the list empty disables both the Telegram frontend (refuses to start) and web login. There is no "allow everyone" mode.
  • The Unix socket is 0600 and restricted to your UID, so other local users cannot impersonate a shim.
  • Uploads are sanitized and scoped — filenames are stripped of path separators and unsafe characters; the resolved destination must stay inside the session's project directory.
  • Auto-fetched file contents (when Claude says "saved to /path/..." and the hub forwards the file body to your Telegram/web) are scoped to each session's project root. Prompt-injection cannot make the daemon read ~/.ssh/ or /etc/.

Exposing the Web Dashboard

The web dashboard runs on 127.0.0.1 only. To access it remotely, put an authenticated proxy in front — the dashboard's own cookie auth is not a substitute for TLS + an external access control. Options:

  • Nginx / Traefik / Caddy with TLS and basic auth or SSO — point your domain to http://127.0.0.1:<webPort>, enable WebSocket passthrough, require authentication at the proxy.
  • Tailscale / Cloudflare Tunnel — identity-aware tunnels. Good default for personal use.
  • SSH tunnelssh -L 3000:localhost:3000 your-server. Simplest; only you have the key.

Do not expose the port directly (0.0.0.0 or a public address) — the daemon deliberately refuses that binding for safety, and proxying is cheap.

Configure your bot's domain in @BotFather (/setdomain) so the Telegram Login Widget works on your proxy domain.

Prerequisites

  • Bun >= 1.0
  • tmux (for daemon and session management)
  • Claude Code with claude.ai login
  • A Telegram bot token (optional, for Telegram frontend)

Development

bun test              # 65 tests
bun run src/daemon.ts # start daemon
bun run src/cli.ts    # CLI tool

Plugin Status

ChannelHub is not yet on the approved marketplace. During the research preview, custom channels must use --dangerously-load-development-channels server:hub to run. This flag bypasses the allowlist check for your specific server entry. Permission relay and all other channel features work normally.

The project is structured as a Claude Code channel plugin and ready to submit to the official marketplace. Once approved, users will be able to install it with /plugin install channelhub@marketplace and use --channels plugin:channelhub@marketplace without the development flag.

License

Apache-2.0