About this project

tg-cli (command name tg) is a Telegram bridge for AI coding agents. It has two halves: an outbound CLI that agents call to push updates, and an inbound daemon, tg-ctl, that carries your replies from a phone back into a running agent session. Outbound. Agents send text, HTML reports, photos and files. HTML tags are auto-detected, and a branded emoji prefix is added for the detected agent. Markdown files are converted to PDF via pandoc and headless Chrome before upload, falling back to sending the original if conversion fails. File paths mentioned in the message text are detected and attached automatically by recursive search across the worktree, with the path left in the caption. Several guards run before a send. A message long enough to fragment into more than six Telegram sends is refused up front with the character count and fragment count. Secret-looking files are never attached: .env files, SSH private keys, pem/key/p12/pfx/ppk, credential rc-files, shell histories, tfvars, credentials.json and kubeconfig; auto-detected mentions are skipped, while an explicit file argument is a hard error. A garbled-token guard blocks a lone CJK codepoint stuck inside a Latin or Cyrillic word and tokens whose script switches twice or more, while allowing genuinely bilingual text. A screenshot guard refuses a message that mentions a screenshot with no photo attached. A dictionary gate matches banned wording from a user-maintained JSON file against the title, body and captions of every send, with no bypass flag by design; a malformed file fails closed. Autolinks resolve Linear ticket ids through the linear CLI and GitHub PR/issue numbers through gh, caching verdicts for an hour and degrading to plain text. Individual features can be turned off with a no-feature flag. Inbound. tg-ctl starts automatically on the first outbound send from a tmux pane with a detected agent. Plain text replies from Telegram are injected into that agent's pane. Replying to a message with a quote attaches a quote anchor naming the answered message, and the tg replies command can pull the full original back. The /agent command routes a message to a specific agent, fuzzy-matching (and Cyrillic-aware on) window names, offering selection buttons grouped by session when ambiguous, and giving a bare invocation a list of agents. An agent started outside tmux has no pane; it is listed as unreachable with the reason and instead gets a second channel through a Stop-hook inbox, which is read at each turn end. The README states the limitation plainly: an already idle agent receives the queued message only when it next finishes a turn. The tg-ctl inbox command shows what is queued. Question-to-buttons forwards agent questions and permission prompts to Telegram as inline buttons, so you can answer by tapping and have the answer injected straight back into the pane. It covers Claude Code question and permission shapes, Codex PermissionRequest and opencode question.asked and permission.asked events, and is wired up idempotently by an install-hooks command that backs up and preserves existing settings. Messages sent while a question is pending are deferred rather than interrupting the prompt, and a timed-out question card can still be answered with plain text. Commands include stop (interrupts the current turn), kill, status, limit (latest usage telemetry per agent), tasks (a filterable task board), agent, daily (shipped-work report) and spend (token and cost usage). Photos and documents sent from Telegram are downloaded to a local cache directory and the path is injected for the agent to read. Usage telemetry piped from Claude Code statusLine, Codex token counts and Pi session stats can trigger a deduplicated warning when a limit reaches 90 percent. Forum-topic routing is opt-in and experimental, with documented caveats around topic creation spawning an agent and reopening a live topic not re-attaching its agent. Control can be disabled in the config file. Installation. A one-line install script installs dependencies via Bun, links tg into PATH and registers the agent skill; a manual clone plus symlink also works. Configuration lives in a dotenv file under the config directory with a bot token and chat id. An install-skill subcommand writes a skill file and appends short instructions to detected harness files. Because the checked-out script is the running binary there is no build step, and a deploy script fast-forwards the checkout, refusing to pull over local changes; daemon code changes require a restart, which the script detects and reports. One bot token per machine is required, since Telegram allows a single getUpdates consumer per token.