Source: Anthropic official docs — Channels + Anthropic official docs — Channels reference Type: Product Feature (research preview) Product: Claude Code Requires: Claude Code v2.1.80+ (channels), v2.1.81+ (permission relay), Anthropic authentication (claude.ai or Console API key)

A channel is an MCP server that pushes external events into a running Claude Code session over stdio, so Claude can react to things happening outside the terminal. Channels can be one-way (forward webhooks, alerts, monitoring events) or two-way (chat bridges that also expose a reply tool). A two-way channel with sender authentication can additionally relay permission prompts to a phone or other device. Team and Enterprise organizations must explicitly enable channels.

Auth update (W19, 2026-05-10): --channels now works with Console API key authentication. Previously, channels required claude.ai login. The note “Console and API key authentication is not supported” has been removed from the official docs.

How channels compare with other Claude Code reach-outs

FeatureWhat it doesGood for
Claude Code on the webRuns in fresh cloud sandbox cloned from GitHubSelf-contained async work checked on later
Claude in SlackSpawns web session from @Claude mentionTasks starting from team conversation context
Standard MCP serverClaude pulls; nothing pushedOn-demand read/query of a system
Remote ControlDrive a local session from claude.ai or mobileSteering an in-progress session while away from desk
ChannelsExternal systems push events into your already-running local sessionWebhooks, chat bridges, monitoring forwards

Compared with loop polling, channels are reactive (event-driven) instead of timer-driven.

Built-in channel plugins

All four require Bun and are published as plugins under claude-plugins-official.

Telegram

  1. Create a bot via BotFather (/newbot).
  2. /plugin install telegram@claude-plugins-official
  3. /reload-plugins
  4. /telegram:configure <token> — saves to ~/.claude/channels/telegram/.env. (Or set TELEGRAM_BOT_TOKEN in shell env.)
  5. Restart with claude --channels plugin:telegram@claude-plugins-official.
  6. DM the bot. It replies with a pairing code.
  7. /telegram:access pair <code> then /telegram:access policy allowlist.

Discord

  1. Discord Developer Portal → New Application → Bot → Reset Token.
  2. Enable Message Content Intent under Privileged Gateway Intents.
  3. OAuth2 URL Generator: bot scope + permissions (View Channels, Send Messages, Send Messages in Threads, Read Message History, Attach Files, Add Reactions). Open the URL to invite.
  4. /plugin install discord@claude-plugins-official, then /discord:configure <token> (or DISCORD_BOT_TOKEN).
  5. Restart with --channels plugin:discord@claude-plugins-official.
  6. DM the bot, get pairing code, run /discord:access pair <code> and /discord:access policy allowlist.

iMessage (macOS only)

Reads the Messages database directly; sends via AppleScript. No bot token, no external service.

  1. Grant Full Disk Access to your terminal (System Settings → Privacy & Security → Full Disk Access). Required to read ~/Library/Messages/chat.db.
  2. /plugin install imessage@claude-plugins-official.
  3. Restart with --channels plugin:imessage@claude-plugins-official.
  4. Text yourself from any device on your Apple ID — self-chat bypasses access control.
  5. First reply triggers a macOS Automation prompt asking if your terminal can control Messages. Click OK.
  6. Allow other senders by handle: /imessage:access allow +15551234567 or user@example.com.

fakechat (localhost demo)

A localhost browser UI for trying the channel pattern without a real platform.

  1. /plugin install fakechat@claude-plugins-official.
  2. Restart with claude --channels plugin:fakechat@claude-plugins-official.
  3. Open http://localhost:8787 and type — messages arrive in your session as <channel source="fakechat"> events; Claude’s replies show up in the chat UI.

Building your own channel

A channel is an MCP server that runs over stdio (Claude Code spawns it as a subprocess). Three things are required:

  1. Declare claude/channel: {} in experimental capabilities — registers the notification listener.
  2. Emit notifications/claude/channel events with content (string) and meta (string→string map).
  3. Connect over StdioServerTransport.
const mcp = new Server(
  { name: 'webhook', version: '0.0.1' },
  {
    capabilities: { experimental: { 'claude/channel': {} } },
    instructions: 'Events arrive as <channel source="webhook" ...>. One-way, no reply expected.',
  },
)
await mcp.connect(new StdioServerTransport())

Events arrive in Claude’s context as XML-like tags:

<channel source="your-channel" severity="high" run_id="1234">
build failed on main: https://ci.example.com/run/1234
</channel>

Each meta key becomes a tag attribute. Keys must be [a-zA-Z0-9_] — hyphens or other characters are silently dropped.

Two-way channels (reply tool)

Add tools: {} to capabilities, register ListToolsRequestSchema + CallToolRequestSchema handlers for a tool like reply(chat_id, text). The instructions string tells Claude when to call it and which meta attribute (e.g., chat_id) to pass back.

Permission relay

A two-way authenticated channel can opt in to receive tool-approval prompts in parallel with the local terminal dialog. Add 'claude/channel/permission': {} to experimental capabilities.

When Claude calls a tool needing approval:

  1. Claude Code generates a 5-letter request ID (drawn from [a-km-z] — no l to avoid confusion with 1/I on phones).
  2. Notifies your server via notifications/claude/channel/permission_request with request_id, tool_name, description, input_preview (JSON args truncated to 200 chars).
  3. Your server forwards the prompt + ID to your chat app.
  4. The remote user replies (e.g., yes abcde / no abcde).
  5. Your inbound handler parses, emits notifications/claude/channel/permission with request_id + behavior: 'allow'|'deny'.

Local terminal dialog and remote prompt stay live in parallel. First answer wins; the other is dropped. Project-trust and MCP-consent dialogs do not relay — terminal-only.

Only declare permission relay if your channel authenticates the sender (see below). Anyone who can reply through the channel can approve or deny tool use in your session.

Sender gating (security)

Ungated channels are a prompt-injection vector. Anyone who can reach your endpoint can put text in front of Claude.

  • Gate on sender identity, not chat/room ID — in group chats these differ, and gating on the room would let anyone in an allowlisted group inject messages.
  • Telegram/Discord bootstrap the allowlist via pairing: user DMs the bot → bot returns code → user approves it in their session → sender ID added.
  • iMessage detects the user’s own addresses from the Messages DB at startup and lets them through automatically; other senders are added by handle.

When Claude replies, you see the inbound message in your terminal but not the reply text — the terminal shows the tool call and sent confirmation; the actual reply lands on the other platform.

Enterprise controls

On Team and Enterprise plans, channels are off by default. Two managed settings (users cannot override):

SettingPurposeDefault
channelsEnabledMaster switch. Must be true for any channel to deliver. Blocks all channels including dev flag when off.Channels blocked
allowedChannelPluginsReplaces the Anthropic allowlist with your own. Each entry: { "marketplace": "...", "plugin": "..." }. Empty array blocks all.Anthropic default list applies

Pro and Max users without an organization skip these checks — channels are available; opt in per session with --channels.

Enable from claude.ai → Admin settings → Claude Code → Channels, or set channelsEnabled: true directly.

Research preview

  • --channels accepts only plugins on the Anthropic-maintained allowlist (or your org’s allowedChannelPlugins if set).
  • To test custom channels you’re building: claude --dangerously-load-development-channels server:<name> or plugin:<name>@<marketplace>. Bypass is per-entry; combining with --channels doesn’t extend bypass to those entries.
  • Bypass skips the allowlist only — the channelsEnabled policy still applies.
  • API surface and protocol contract may change based on feedback during the preview.

Permission prompts while you’re away

If Claude hits a permission prompt and you’re away from the terminal:

  • A channel with permission relay can forward the prompt to you.
  • For unattended use, --dangerously-skip-permissions bypasses prompts entirely. Use only in trusted environments.

Key Takeaways

  • Channels = MCP servers that push events into a running Claude Code session, not pull.
  • Telegram, Discord, iMessage, and fakechat ship as official plugins; build your own with the MCP SDK + claude/channel capability.
  • Sender gating on identity (not room) is mandatory — channels are a direct prompt-injection vector.
  • Permission relay is opt-in (claude/channel/permission) and requires authentication; first answer (terminal vs remote) wins.
  • Team/Enterprise off by default; admins enable via channelsEnabled and optionally constrain via allowedChannelPlugins.
  • Pairs cleanly with loop (timer-driven) and hooks (lifecycle-driven) — channels are the event-driven leg.
  • Research preview — flag-gated, expect API changes.

Try It

  1. Fakechat in 30 seconds: /plugin install fakechat@claude-plugins-official, restart with claude --channels plugin:fakechat@claude-plugins-official, open http://localhost:8787, type “what’s in my working directory?”
  2. Telegram bridge for a real workflow: create a bot with BotFather, install + configure as above. Useful pattern: ask “is the deploy still red?” from your phone while Claude has your repo open.
  3. iMessage if you’re on macOS: install plugin, grant Full Disk Access, text yourself. Self-chat is the lowest-friction smoke test of the entire channel system.
  4. Custom webhook receiver for CI: follow the channels-reference walkthrough — a single Bun file gives you curl -X POST localhost:8788 -d "..." reaching Claude in seconds.
  5. Add permission relay to a two-way channel only after you’ve gated senders — anyone who can reply can approve tools.

Open Questions

  • What is the per-channel rate limit before Claude Code throttles or drops events?
  • How does permission relay handle multiple simultaneous tool prompts — one ID per prompt, FIFO ordering, or interleaved?
  • Will channels move out of research preview, and what is the migration path if the protocol contract changes?
  • Can a single session connect to multiple channels of the same type (e.g., two Telegram bots)?