📋 Overview
pi-telegram (@llblab/pi-telegram) turns a private Telegram DM into a session-local operator console for the Pi coding agent. It handles work admission, context preservation, streaming Telegram HTML replies, prompt queuing for busy sessions, voice transcription and synthesis, inline operator menus, and native Telegram artifact delivery. It's also a voice-provider platform — companion extensions can supply transcription and synthesis backends while pi-telegram owns transport, queueing, and reply policy.
This is an actively maintained fork of badlogic/pi-telegram that has diverged substantially from the original.
1 What Is pi-telegram?
At its core, pi-telegram bridges a Telegram bot to a running Pi instance. But it's far more than a simple message relay:
- Operator console —
/startopens a full Telegram control panel: status, prompt templates, model switching, thinking levels, settings, and queue management - Prompt queue — fire off tasks while Pi is busy; they enter a visible queue instead of being lost
- Streaming HTML — closed Markdown blocks render as rich Telegram HTML in real time during generation
- Voice pipeline — send voice notes for STT, receive voice replies via configurable TTS
- Multi-modal — send images, files, media groups directly to Pi with context
- Extension platform — other Pi extensions can register Telegram commands, UI sections, status lines, and voice providers without owning a polling loop
- Session-local — only one Pi instance polls Telegram at a time; ownership is managed via a singleton lock
2 Install & Connect
Install
pi install npm:@llblab/pi-telegram
Step 1: Create a Telegram Bot
- Open @BotFather
- Run
/newbot, pick a name and username - Copy the bot token
Step 2: Configure the Token
/telegram-setup
Paste the token when prompted. It's saved to ~/.pi/agent/telegram.json with 0600 permissions. The setup also checks for TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_KEY, TELEGRAM_TOKEN, or TELEGRAM_KEY environment variables as fallbacks.
Step 3: Connect
/telegram-connect
This starts polling Telegram updates. Ownership is recorded in ~/.pi/agent/locks.json. Live ownership moves require confirmation; /new and same-cwd restarts resume automatically.
Step 4: Pair Your Telegram Account
Open the DM with your bot and send /start. The first user to message becomes the exclusive owner — all messages from other users are ignored.
3 Operator Menu & Controls
The inline application menu (/start) is the primary operator surface — a Telegram-native subset of Pi's CLI controls:
- Status — session state, model, context usage
- Prompt templates — discovered from Pi and mapped to Telegram-safe aliases (e.g.,
fix-tests.md→/fix_tests) - Model selection — switch models mid-session; the adapter schedules a safe continuation
- Thinking controls — 6 levels: off · minimal · low · medium · high · xhigh
- Settings — voice, time injection, proactive push, and more
- Queue — inspect, delete, promote, or reorder waiting work
4 Queue Runtime
Messages sent while Pi is busy enter the prompt queue and are processed in order. The queue system handles:
- Ordered processing — text, voice, files, images, and media groups all queue
- Priority lanes — control actions and model-switch continuations get higher priority
- Local execution — queue processing and reply delivery stay local to the Pi instance that accepted the work, even if
/telegram-connectmoves elsewhere - Emoji reaction shortcuts — when Telegram delivers
message_reactionupdates:- 👍 ⚡️ ❤️ 🕊 🔥 — promote waiting work
- 👎 👻 💔 💩 🗑 — remove waiting work from queue
- Edit coalescing — if a Telegram message is edited while queued, the queued turn updates instead of duplicating
- Split text coalescing — very long messages that Telegram splits are recombined via debounce
5 Streaming & Telegram HTML Rendering
Closed Markdown blocks stream as rich Telegram HTML while Pi is generating. The rendering is phone-aware:
- Tables and lists stay narrow for mobile displays
- Table padding accounts for emoji graphemes and wide Unicode
- Long replies are split below Telegram limits without breaking HTML structures, links, code blocks, blockquotes, or fences
- Unsupported link forms degrade safely
- Block spacing stays faithful to the original Markdown
6 Files & Artifacts
Inbound
Send files or images directly to the bot. Downloads are saved to <agent-dir>/tmp/telegram (default 50 MiB limit). Temp files are cleaned up on later session starts.
Outbound
telegram_attach— Pi tool for sending generated files. During Telegram-originated turns, it sends with the next reply. During local/TUI work, it sends directly to the paired chat.telegram_message— push Markdown text messages to Telegram, with optional inline buttons viatelegram_buttonHTML comments
Outbound attachments default to a 50 MiB limit, configurable via environment variables.
7 Voice Integration
pi-telegram is a full voice-provider platform. The voice pipeline works in both directions:
Inbound (STT)
Telegram .ogg voice notes arrive → STT runs locally or via command → transcript is injected as [outputs] context → Pi receives usable text.
Outbound (TTS)
Agent writes <!-- telegram_voice --> markup or automatic voice mode intercepts text → TTS provider produces .ogg/.opus → Telegram sendVoice delivers it.
Provider Priority
- Configured
outboundHandlerswithtype: "voice"(telegram.json) - Programmatic inbound handlers from extensions
- Registered synthesis provider extensions (e.g.,
pi-xai-voice)
8 Voice Reply Policies
Configure automatic voice conversion from Settings → 👄 Voice reply or via voice.replyMode in telegram.json:
- hidden (default) — manual mode, prompt context stays silent
- manual — explicit
<!-- telegram_voice -->markup required; adds[voice]context - mirror — when user sends voice, reply is converted to voice; text-originated turns stay text
- always — every reply is converted to voice, text preview suppressed
If every voice generator fails, the bridge falls back to sending the text reply instead.
9 Inbound Handlers
telegram.json can define ordered inboundHandlers for Telegram → Pi preprocessing: text translation, voice transcription, OCR, PDF extraction, or any command-template pipeline.
{
"inboundHandlers": [
{
"type": "text",
"template": "/path/to/translate --lang {lang=en} --text \"{text}\""
},
{
"type": "voice",
"template": [
"/path/to/stt --file {file} --lang {lang=ru}",
"/path/to/translate-stdin --lang {lang=en}"
]
},
{
"mime": "audio/*",
"template": [
"/path/to/stt-fallback --file {file} --lang {lang=ru}",
"/path/to/translate-stdin --lang {lang=en}"
]
}
]
}
Matching handlers run before the turn enters the queue. Failed handlers record diagnostics and fall back safely. Extensions can also register programmatic inbound handlers.
10 Extension Interop — The Extension Platform
pi-telegram is designed as a platform that other Pi extensions can build on top of, without needing their own Telegram polling loop:
Slash Commands
Extensions can register Telegram-native slash commands via @llblab/pi-telegram/commands. Workflow-specific commands (e.g., fresh-session control) live in companion extensions.
UI Sections
Register Telegram-native menu sections and status lines via @llblab/pi-telegram/sections. Sections appear in the main menu and Settings submenu. Each section gets a typed context with edit, open, enqueuePrompt, answerCallback, and callbackData().
Callback Forwarding
Unknown inline-button callbacks are forwarded to Pi as [callback] <data>, so other extensions can namespace and handle Telegram buttons without owning the bot.
Voice Synthesis Providers
Extensions register TTS backends at runtime through public API subpaths. Multiple providers are tried in registration order; the first success handles the reply.
11 Proactive Push & Time Context
Proactive Push
Set proactivePush: true in telegram.json to send successful local (non-Telegram) final replies to the paired chat. Local prompt text is not mirrored — the bot doesn't own terminal user messages. Toggle from Settings.
Time Context
Opt into a compact [time] line in Telegram prompts so Pi has wall-clock reference for "today", "now", or scheduling:
- hidden — no time line (default)
- always — every prompt gets a timestamp
- interval — rate-limited per chat (e.g., 3600000ms = 1 hour)
12 Commands Reference
Telegram Commands (in the DM)
| Command | Description |
|---|---|
| /start | Pair + open operator menu |
| /compact | Session compaction with confirmation |
| /next | Dispatch next queued turn |
| /continue | Enqueue priority continue prompt |
| /abort | Abort active run, keep queue |
| /stop | Abort active run + clear queue |
Pi Commands (in the terminal)
| Command | Description |
|---|---|
| /telegram-setup | Configure/update bot token |
| /telegram-connect | Start Telegram polling, acquire lock |
| /telegram-disconnect | Stop polling, release lock |
| /telegram-status | Inspect adapter status and diagnostics |
13 Configuration & Environment
Files
~/.pi/agent/telegram.json— bot token, inbound/outbound handlers, voice settings, proactive push, time injection~/.pi/agent/locks.json— singleton polling ownership~/.pi/agent/tmp/telegram/— inbound Telegram file downloads
Key Environment Variables
TELEGRAM_BOT_TOKEN/TELEGRAM_BOT_KEY— bot token bootstrapHTTP_PROXY/HTTPS_PROXY— proxy support (withNODE_USE_ENV_PROXY=1)PI_CODING_AGENT_DIR— override agent data rootPI_TELEGRAM_INBOUND_FILE_MAX_BYTES— inbound file limit (default 50 MiB)PI_TELEGRAM_OUTBOUND_ATTACHMENT_MAX_BYTES— outbound attachment limit (default 50 MiB)
14 Companion Extensions
- pi-codex-usage — Codex subscription quota/status widget for the status line and inline menu
pi install npm:@llblab/pi-codex-usage - pi-telegram-tool-status — live-updating service messages listing tools used by the agent
pi install npm:pi-telegram-tool-status - pi-xai-voice — xAI-powered TTS for voice reply policies and
telegram_voicemarkuppi install npm:pi-xai-voice
🎯 Key Takeaways
🔑 Key Takeaways
- Full Telegram operator console — status, model switching, thinking levels, prompt templates, queue management, all from the DM
- Prompt queue with priority lanes — fire off tasks while Pi is busy; manage via menu or emoji reactions
- Streaming Telegram HTML — real-time rendering, phone-aware, smart splitting below Telegram limits
- Bidirectional voice pipeline — inbound STT + outbound TTS with 4 reply modes (hidden, manual, mirror, always)
- Voice-provider platform — companion extensions register TTS/STT backends; pi-telegram owns transport
- Extension platform — other extensions register slash commands, UI sections, status lines, and callbacks without polling
- Multi-modal input — text, images, files, media groups, voice notes, replies, and edits all handled
- Session-local singleton — only one Pi polls Telegram; clean ownership transfer with lock management
- Inbound handlers — configurable preprocessing pipeline for translation, OCR, PDF extraction, STT
- Proactive push — local Pi work results can be sent to Telegram automatically
- 9,200+ monthly downloads — the most popular Pi extension by far
🔗 Resources & Links
- @llblab/pi-telegram on Pi Package Registry — official package page
- GitHub Repository — source code, issues, documentation
- Pi Coding Agent — the host agent