Tech 5 min read

Claude Code Channels lets external services push events into a session

IkesanContents

Claude Code v2.1.80 introduced “Channels” as a research preview. It is a way for external services to push live messages into a running Claude Code session through MCP. The supported platforms are Telegram and Discord through first-party plugins, plus a localhost demo called fakechat.

I had already built something similar in Kana Chat using a tmux bridge. The phone connects over Tailscale to FastAPI, which injects messages into a Claude Code session with tmux send-keys, then reads the reply back from a pane capture. Channels gives this external-to-session message injection a proper MCP-based official implementation.

Kana Chat has also evolved since the February article. The tmux bridge is still there for live relaying, but routine jobs have moved to a task-instruction-file model. For tasks that do not need a conversational back-and-forth, batch-style execution is more reliable than real-time messaging.

Channels solves the “live bidirectional communication” problem. For tasks that are better handled with instruction files, you do not need it. That is why Kana Chat uses both approaches.

How it works

Channels is an MCP server that receives messages from external services while the Claude Code session is running and injects them into the session as events.

flowchart LR
    A[Telegram DM] --> B[Telegram bot]
    B --> C[Channel plugin<br/>MCP server]
    C -->|push event| D[Claude Code session]
    D --> E{Claude processes}
    E -->|reply tool| C
    C --> B
    B --> A

The important part is that communication is bidirectional. After Claude processes an event, it can send a reply back through the channel’s reply tool. In the terminal, you only see the tool call and the “sent” confirmation, not the full message body.

Events only arrive while the session is open. If you want it to run in the background, Claude Code has to keep running in a persistent terminal or background process such as tmux or screen.

Compared with Kana Chat’s tmux bridge:

ItemChannelstmux bridge (Kana Chat)
ProtocolMCP, officially supportedtmux send-keys + pane capture
Message injectioninjected as MCP eventsinjected as keyboard input
Reply handlingstructured via reply toolparse terminal output
Authenticationpairing + allowlistTailscale VPN + app-level auth
CLI dependencydepends on the MCP speconly depends on terminal output, so it is more resilient to internal CLI changes

Channels is integrated at the protocol layer, so there is no response parsing. The tmux bridge is more general and can connect Claude Code’s CLI cousins such as Codex or Gemini CLI as well.

Telegram setup

Bun is required to launch Channels.

bun --version  # install from bun.sh if needed

For Telegram, the setup is:

  1. Create a bot with BotFather and obtain the token
  2. Install the plugin inside Claude Code
/plugin install telegram@claude-plugins-official
  1. Configure the token
/telegram:configure <token>

The configuration is saved to .claude/channels/telegram/.env.

  1. Restart with the Channels flag
claude --channels plugin:telegram@claude-plugins-official
  1. Send a DM from Telegram and pair using the returned code
/telegram:access pair <code>
/telegram:access policy allowlist

The allowlist keeps the channel limited to registered accounts.

Discord follows the same pattern: create a bot in the Developer Portal, install the plugin, set the token, and pair it.

Security model

Because the feature lets external systems inject commands into a Claude Code session, the security model is strict.

Plugin allowlist

In the current research preview, the plugins accepted by --channels are restricted to Anthropic-managed allowlisted plugins. Using a custom development channel requires --dangerously-load-development-channels.

Sender allowlist

Each channel plugin only accepts IDs that were paired during setup. Unregistered messages are silently dropped. The /telegram:access policy allowlist step is documented as part of the required setup.

Session-level opt-in

A server entry in .mcp.json is not enough. The channel only becomes active when explicitly enabled with --channels.

Permission prompts still apply

Claude keeps its normal permission flow. If it reaches an operation that needs approval, the session pauses and waits for local confirmation. For unattended use, --dangerously-skip-permissions exists, but only for trusted environments.

Kana Chat uses the same principle: let read-only operations through, but stop writes and execution. --dangerously-skip-permissions is the same idea as auto-approving everything, so it should stay off unless you really need it.

Enterprise settings

PlanDefault behavior
Pro / Max, no organizationChannels available, user opts in with --channels
Team / Enterprisedisabled until an admin enables it

For Team and Enterprise, the admin has to enable it from claude.ai -> Admin settings -> Claude Code -> Channels, or set channelsEnabled: true in managed settings. Even when disabled, the MCP server can still connect and tools can work, but channel messages do not arrive.

Building your own channel

The Telegram and Discord plugins are published in the anthropics/claude-plugins-official repository and implemented as Bun scripts. If you want to build a custom channel, that repo is the place to start.

Because this is still a research preview, the --channels syntax and protocol details may change. Feedback goes through Claude Code’s GitHub issues.