The gap between polling and waiting
Claude Code already has a few ways to react to the outside world without you sitting at the terminal: scheduled tasks poll on an interval, /goal keeps a session working turn after turn toward a condition, and the Monitor tool watches a specific log, script or feed in the background. Channels fill a different gap: getting an event from outside pushed into a session you already have open, the moment it happens, without Claude having to ask for it or poll for it at all.
A channel is an MCP server that pushes events into your running Claude Code session, so Claude can react to things that happen while you're not at the terminal. Anthropic documents it as a research preview feature as of August 2026, which means the --channels flag and its underlying protocol may still change based on feedback, and it doesn't yet appear in claude --help even though the flags work.
What makes a channel different from an ordinary MCP server
A standard MCP server is something Claude queries during a task; nothing arrives unless Claude asks for it. A channel inverts that: the external system pushes an event in on its own schedule, and Claude reads it as it arrives. Channels can also be two-way, so Claude reads the inbound event and replies back through the same channel, functioning as a chat bridge, or a webhook receiver that just needs to land in the session and get acted on.
Anthropic's own comparison lays out where channels sit against everything else that connects a session to the outside world:
| Feature | What it does | Good for |
|---|---|---|
| Claude Code on the web | Runs tasks in a fresh cloud sandbox, cloned from GitHub | Delegating self-contained async work you check on later |
| Claude in Slack | Spawns a web session from an @Claude mention | Starting tasks directly from team conversation context |
| Standard MCP server | Claude queries it during a task; nothing pushed | On-demand access to read or query a system |
| Remote Control | You drive your local session from claude.ai or mobile | Steering an in-progress session while away from your desk |
| Channels | Pushes events from non-Claude sources into your open session | Reacting to CI, monitoring, or chat while you're away |
Installing a channel
Every supported channel ships as a plugin you install and configure with your own credentials, and the three included in the research preview are Telegram, Discord and iMessage, each requiring Bun to run. The flow is the same shape for all three: install the plugin, configure a token or grant access, restart Claude Code with the channel opted in, then pair your account.
For Telegram, that looks like:
/plugin install telegram@claude-plugins-official
/telegram:configure <token-from-botfather>
Then restart with the channel active:
claude --channels plugin:telegram@claude-plugins-official
Message the bot once to get a pairing code, then approve it inside the session with /telegram:access pair <code>, and lock the channel down to just your account with /telegram:access policy allowlist. Discord follows the same install, configure, restart, pair sequence. iMessage differs in one respect: it reads the local Messages database directly and needs no bot token, only Full Disk Access granted to your terminal, and texting yourself bypasses the access gate automatically since it's your own device.
If you just want to try the mechanism before wiring up a real platform, fakechat is a demo channel with a chat UI on localhost:8787 and nothing to authenticate:
/plugin install fakechat@claude-plugins-official
claude --channels plugin:fakechat@claude-plugins-official
Typing in the browser at http://localhost:8787 delivers the message into your Claude Code session as a <channel source="plugin:fakechat:fakechat"> event, and Claude's reply appears back in the browser rather than in your terminal, which is the pattern every channel follows once it's live: you see the inbound message and a confirmation that a reply was sent, not the reply text itself.
The use case that matters most: webhooks
For pushing CI failures specifically into a running session, the relevant pattern is the webhook receiver, not the chat bridges above. A webhook channel accepts a payload from CI, an error tracker, or a deploy pipeline and delivers it straight into the session where Claude already has your repository open and remembers what you were debugging a few minutes ago. That beats a scheduled /loop checking CI on an interval for one reason: the event arrives the instant it happens, with zero polling overhead in between, and Claude reacts inside the context it already has rather than starting a fresh investigation from scratch.
Building a webhook receiver channel isn't a built-in plugin the way Telegram or Discord is; it's covered under building your own channel in Anthropic's channels reference, for teams that want CI or monitoring events landing in a session rather than routed through chat first.
Security: who can push into your session
Every approved channel plugin keeps a sender allowlist, and anyone not on it is silently dropped. Telegram and Discord bootstrap that list through the pairing flow described above: message the bot, get a code, approve it in the session, and that sender is added. iMessage works differently since texting yourself bypasses the gate by design, and you add other contacts explicitly with /imessage:access allow <handle>.
Two more layers sit on top of the allowlist. First, being listed in .mcp.json isn't enough on its own; a server also has to be named explicitly in --channels for a given session before it can push anything. Second, if the channel plugin declares permission relay support, anyone who can reply through that channel can also approve or deny tool-use prompts in your session remotely, which is powerful but means the allowlist for a relay-capable channel deserves real scrutiny before you add someone to it.
Enterprise and account-level controls
Availability depends on how you authenticate. Pro and Max users without an organisation get channels with no admin setting involved: opt a plugin in per session with --channels and that's it. On claude.ai Team and Enterprise, channels are blocked by default until an Owner enables them from Admin settings → Claude Code → Channels, or sets channelsEnabled: true in managed settings. Anthropic Console organisations authenticating with an API key have channels permitted by default, unless the organisation deploys managed settings, in which case the same channelsEnabled flag applies.
Admins can also narrow which plugins are allowed to register as a channel at all, replacing Anthropic's default list with their own:
{
"channelsEnabled": true,
"allowedChannelPlugins": [
{ "marketplace": "claude-plugins-official", "plugin": "telegram" },
{ "marketplace": "acme-corp-plugins", "plugin": "internal-alerts" }
]
}
This is worth checking with your admin before assuming a channel simply doesn't work; a plugin that isn't on the effective allowlist still lets Claude Code start normally, but the channel never registers, and the startup notice explains why.
The real limitation: the session has to be open
Channels only deliver into a session that's actually running. Close the terminal and the events stop arriving; there's no queue building up for you to catch up on later. For anything you want to catch reliably, the practical answer is running Claude in a background process or a persistent terminal rather than a session you open and close per task, similar in spirit to how self-hosting a Claude Code runner keeps a session available continuously.
If Claude hits a permission prompt while you're away, the session simply pauses until someone responds. Channel plugins that declare the permission relay capability can forward that prompt to you through the same channel, so you can approve or deny it remotely rather than the session stalling until you're back at your desk.
Why this is still labelled a research preview
Two restrictions come with the research preview label, beyond the flag not appearing in claude --help yet. First, channels require Anthropic authentication through claude.ai or a Console API key; they aren't available on Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry at all, regardless of plan. Second, only plugins on an approved allowlist can register as a channel during the preview, either Anthropic's own maintained list or your organisation's allowedChannelPlugins. To test a channel you're building yourself before it's ready for that list, --dangerously-load-development-channels bypasses the allowlist for local testing, but it's explicitly a development-only flag rather than something to run against production credentials.
Because the protocol itself may still change, treat anything you build against channels today as likely to need small updates as the feature matures out of preview, the same caution worth applying to any research-preview feature you wire into a workflow people depend on.
What running fakechat actually shows you
It's worth walking through the fakechat demo once even if you have no plan to use a real channel, because it makes the push-vs-poll distinction concrete rather than abstract. After installing and starting the plugin, opening http://localhost:8787 and typing a message shows up in your terminal as an inbound line prefixed with the channel's name, something like ← fakechat · web: what's in my working directory?. Claude receives that as a structured event tagged with the plugin's scoped server name, does the work exactly as it would for a typed prompt, then calls the channel's own reply tool to send the answer back. The first reply typically triggers a permission prompt, since calling a new tool for the first time in a session does; approve it and the answer appears in the browser tab, not in your terminal. That's the shape every real channel follows once wired up: the terminal shows the inbound event and a confirmation a reply was sent, while the actual conversation happens on whichever platform the channel connects to.
Troubleshooting
A channel plugin installs but never receives anything. Confirm it's actually named in --channels for the session you're running. Being present in .mcp.json or successfully installed as a plugin isn't sufficient on its own; the flag has to name it explicitly each time you start Claude Code with channels active.
The startup notice says a plugin isn't on the approved list. An admin has set allowedChannelPlugins and your plugin isn't in it, or you're testing a custom channel that isn't Anthropic-approved yet. Ask your admin to add it, or use --dangerously-load-development-channels for local testing only.
Telegram or Discord never sends a pairing code. Confirm Claude Code is actually running with --channels naming that plugin before messaging the bot; the bot can only reply while the channel is active in a running session, so a message sent beforehand won't trigger anything.
iMessage exits immediately with authorization denied. The Messages database at ~/Library/Messages/chat.db needs Full Disk Access granted to whichever app launched Bun. Grant it manually under System Settings → Privacy & Security → Full Disk Access if the initial prompt didn't appear or you dismissed it.
Channels silently don't work for anyone in the organisation. Check whether channelsEnabled has actually been set. On claude.ai Team and Enterprise it's blocked by default until an Owner turns it on; an unset value here means every user hits the same silent block regardless of what they pass to --channels.
Where to go next
For scheduling a prompt to check something on an interval instead of reacting to a pushed event, see Claude Code Routines vs /loop. For watching a specific log, script or feed continuously from inside a session rather than receiving pushed events, see what Claude Code's Monitor tool does. For messaging between two of your own Claude Code sessions rather than an external platform, see how Claude Code sessions message each other. Browse the current catalogue at getclaudeskills.com/platforms/claude-code.
