Quickstart
From zero to texting your Claude Code session, on Telegram, in five steps.
What hotline is
hotline is an MCP server that relays a Claude Code session to your messaging apps. Claude replies in short bubbles with a typing indicator, reacts with emoji, edits its own messages to show progress, and offers inline buttons when it wants you to pick one thing. Telegram is the default provider; Signal and Discord run alongside it or on their own.
It speaks Claude Code's experimental two-way channel protocol (claude/channel), which makes it Claude Code specific today. Details and caveats on the protocol page.
Install
go install github.com/1broseidon/hotline@latest # -> $(go env GOPATH)/bin/hotline
Requires Go 1.26+. No prebuilt binaries yet.
Set up Telegram
-
Get a bot token from @BotFather.
-
Drop it in the channel's
.env:mkdir -p ~/.claude/channels/tele-go printf 'TELEGRAM_BOT_TOKEN=123456789:AA…\n' > ~/.claude/channels/tele-go/.env chmod 600 ~/.claude/channels/tele-go/.envA real
TELEGRAM_BOT_TOKENenvironment variable wins over the.envfile. -
Register hotline as an MCP server in the project you want to text with, via
.mcp.json:{ "mcpServers": { "hotline": { "command": "hotline", "args": ["run"] } } } -
Start Claude Code with the channel flag (channels are experimental and loaded by MCP server name):
claude --dangerously-load-development-channels server:hotline -
DM your bot. The first message from an unknown sender returns a 6-hex pairing code. Approve it from your terminal:
hotline pair <code>
That's it. Your session is now a Telegram chat. The pairing step is part of the access model; read Access & permissions before you hand the bot's handle to anyone.
The tools Claude gets
| Tool | What it does |
|---|---|
reply | Send bubbles (array of short messages, paced) or text (single message, chunked past 4096 chars). Optional reply_to, files (images inline, others as documents, 50MB each), buttons (up to 12 inline options), format (text, markdownv2, html) |
react | Set an emoji reaction (Telegram's fixed whitelist) |
edit_message | Edit a message the bot sent, for interim progress. Edits don't push-notify |
download_attachment | Fetch a non-photo attachment by file_id into the inbox; returns a local path (Telegram's 20MB download cap applies) |
Button taps come back as ordinary inbound messages whose content is the tapped label, verbatim. Tap authorization mirrors the inbound gate.
CLI
hotline [run] # start the MCP server + Telegram poller (default)
hotline pair <code> # approve a pending pairing code
hotline deny <code> # reject a pending pairing code
hotline status # print state-dir / token / access summary
pair, deny, and status take --provider kind[:instance] to select which provider's state they operate on (default: telegram).
Where things live
State lives in ~/.claude/channels/tele-go. The directory keeps its pre-rename name, so existing pairings, transcripts, and inboxes carry over: hotline was formerly tele-go, and TELE_GO_* variables keep working as fallbacks for one release. The full environment variable table is on Multiple providers.