pi-telegram-command-bridge
Companion extension for @llblab/pi-telegram: executes pi extension commands (e.g. /project) and skill commands (/skill:name) natively from Telegram-originated prompts
Package details
Install pi-telegram-command-bridge from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-telegram-command-bridge- Package
pi-telegram-command-bridge- Version
0.3.0- Published
- Sep 29, 2026
- Downloads
- 699/mo · 202/wk
- Author
- stefklotz
- License
- MIT
- Types
- extension
- Size
- 23.6 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-telegram-command-bridge
A pi coding agent companion extension for @llblab/pi-telegram: executes pi extension commands (e.g. /project) and skill commands (/skill:name) natively from Telegram-originated prompts — with their full ExtensionCommandContext, no pi-telegram source changes required.
Why
pi-telegram deliberately does not forward arbitrary TUI slash commands (a documented safety boundary). Telegram prompts reach the agent via sendUserMessage() with template expansion disabled, so /project foo arrives as literal chat text instead of executing the command handler.
This extension closes that gap for the safe subset: extension-registered commands and skill commands. Built-in TUI commands (/model, /new, …) are still not forwarded.
How it works
pi.on("input") fires for every prompt before skill/template expansion when the extension-command check was skipped. For prompts with source "extension" (how sendUserMessage labels Telegram queue dispatch) that name a known extension command or skill command, this extension re-dispatches the same text through pi.sendUserMessage(text, { expandPromptTemplates: true }). prompt() then runs the extension-command check first — before the input event — so the real handler executes with its full context (ctx.ui, ctx.switchSession, ctx.sessionManager, …) and no second input event fires. Non-commands fall through once; a re-dispatch marker prevents loops.
Settling the Telegram dispatch queue
pi-telegram marks a dispatched prompt as pending and only settles it (clears its pending flag and consumes the queue item) when an agent turn starts. Extension commands run without a model turn, so a bridged command that triggers no LLM interaction of its own (e.g. /project with no arguments, which only calls ctx.ui.notify) would leave the pending flag set forever: every later Telegram message queues up but is never dispatched, the typing indicator never stops, and the bridge stays wedged until the session restarts.
After re-dispatching a command, the bridge watches for the next agent_start (or a session start, which resets pi-telegram's bridge state). Commands that start a turn themselves settle the queue that way — session switches announce via a sendUserMessage follow-up, skill commands expand into real prompts. If no agent turn arrives within three seconds, the bridge sends one short settle prompt: that turn gives pi-telegram the agent_start it needs, and its one-line confirmation reply is delivered to Telegram as the answer to the original command message.
Scope:
- Only
source: "extension"prompts are intercepted (Telegram queue dispatch, generated-control-surface buttons, generative-app prompts). TUI ("interactive") and RPC ("rpc") prompts are untouched — they already dispatch commands natively. - Only extension-registered commands (
pi.getCommands()withsource: "extension") and skill commands (/skill:name) are forwarded. Built-in TUI commands and prompt templates are not (pi-telegram expands prompt templates itself). - A leading
[telegram]tag (the bridge prefix) is stripped before matching; everything after the command name is preserved as arguments.
/bridge-commands
The extension registers its own /bridge-commands command — naturally forwardable through the bridge itself — which lists everything the bridge can execute from Telegram, derived live from pi.getCommands(): extension-registered commands (/name, with descriptions) and skill commands (/skill:name). Each entry is rendered as a tappable telegram_button cell queuing the command. Built-in TUI commands (/model, /new, …) and prompt templates are deliberately not listed and not forwarded — the output says so.
From the chat, send /bridge-commands and the reply is the list. The command is also available on native surfaces (TUI/RPC) via the local UI notification.
Install
pi install npm:pi-telegram-command-bridge
Or from git:
pi install git:github.com/stefclawd/pi-telegram-command-bridge
Requires @llblab/pi-telegram — this extension only does anything for prompts that arrive through it (or another sendUserMessage-based surface).
Caveats
- Commands whose handlers open
ctx.ui.confirm-style dialogs without a timeout can hang on headless/RPC surfaces, since nothing answers dialog requests there. Prefer commands with non-interactive opt-ins (e.g.pi-project-switcher's/project <name>!create opt-in). - Commands whose handlers only use
ctx.ui.notify(no agent turn) are followed by a short settle prompt three seconds later; the model's one-line confirmation is delivered to Telegram as the reply to the command message. - Command output is routed through
ctx.ui.notify(TUI/RPC channel), not the Telegram chat itself; the settle-turn confirmation is the Telegram-visible feedback.
Development
Single-file TypeScript extension (index.ts), loaded directly by pi via jiti — no build step.
npm install
npm test # vitest
npm run typecheck
License
MIT