tgbot 0.0.6
tgbot: ^0.0.6 copied to clipboard
A CLI tool that bridges Telegram messages to Codex, allowing you to interact with AI agents through a Telegram bot.
tgbot #
tgbot is a Dart CLI that connects a Telegram bot to the Codex CLI. It long-polls Telegram, forwards authorized messages into Codex, keeps a per-chat thread ID in memory, and sends streamed text plus local file/image artifacts back to Telegram.
Install #
dart pub global activate tgbot
If Dart's global bin directory is not already on your PATH, add it first so tgbot is runnable from the shell.
Requirements #
- Dart SDK
- Codex CLI installed and available on
PATH, unless overridden withcodex_cmd - A Telegram bot token from
@BotFather - Your Telegram numeric user ID
Quick Start #
Create a starter config:
tgbot init
Edit tgbot.yaml:
bots:
- name: my-bot
telegram_bot_token: "YOUR_TELEGRAM_BOT_TOKEN"
allowed_user_id: 123456789
project_path: /absolute/path/to/project
Validate it:
tgbot validate
Start the bridge:
tgbot start
Then open your bot in Telegram and send it a message.
CLI #
tgbot <command> [options]
| Command | Description |
|---|---|
start |
Start all bots declared in the config file |
init |
Generate a starter tgbot.yaml |
validate |
Parse and validate a config file without starting bots |
upgrade |
Reinstall the latest published tgbot with Dart |
Global flags:
| Flag | Description |
|---|---|
-h, --help |
Print usage help |
-v, --version |
Print the version |
Examples:
tgbot start
tgbot start -c custom.yaml
tgbot init
tgbot init -o other.yaml
tgbot validate
tgbot validate -c custom.yaml
tgbot upgrade
Telegram Setup #
Bot token #
- Open Telegram and find
@BotFather. - Run
/newbot. - Follow the prompts.
- Copy the token into
telegram_bot_token.
User ID #
- Open Telegram and find
@userinfobot. - Send it any message.
- Copy the numeric ID into
allowed_user_id.
Only that user can interact with the configured bot.
Configuration #
tgbot loads one YAML file, defaulting to tgbot.yaml.
Top-level keys:
bots(required): non-empty list of bot definitionsdefaults(optional): shared values inherited by each bot
Minimal config #
bots:
- name: my-bot
telegram_bot_token: "YOUR_TELEGRAM_BOT_TOKEN"
allowed_user_id: 123456789
project_path: /absolute/path/to/project
Config with shared defaults #
defaults:
project_path: /absolute/path/to/default/project
codex_cmd: codex
codex_args:
- --model
- gpt-5
codex_allow_dirs:
- ~/Workspace/shared
poll_timeout_sec: 60
codex_timeout_sec: 1000
bots:
- name: repo-a
telegram_bot_token: "TOKEN_A"
allowed_user_id: 123456789
- name: repo-b
telegram_bot_token: "TOKEN_B"
allowed_user_id: 123456789
project_path: /absolute/path/to/repo-b
additional_system_prompt: |
Keep answers brief and focus on production issues.
Bot fields #
| Key | Required | Notes |
|---|---|---|
name |
Yes | Used in logs and status messages |
telegram_bot_token |
Yes | Telegram Bot API token |
allowed_user_id |
Yes | Only this Telegram user can use the bot |
project_path |
Yes | Absolute working directory used for Codex; may be inherited from defaults |
codex_cmd |
No | Codex executable, default codex |
codex_args |
No | Extra args inserted before built-in exec; accepts a YAML list or whitespace-delimited string |
codex_allow_dirs |
No | Extra directories appended as --add-dir; accepts a YAML list or comma-delimited string, and ~ is expanded |
poll_timeout_sec |
No | Telegram long-poll timeout in seconds, default 60 |
codex_timeout_sec |
No | Per-request Codex timeout in seconds, default 1000 |
additional_system_prompt |
No | Extra system instructions prepended before each user request |
telegram_commands |
No | Extra Telegram slash commands registered for this bot |
Notes:
defaultsapplies only when a bot omits that key.- Every bot must end up with an effective
project_path. telegram_commandsmust be a non-empty list when provided.- Command names must match
^[a-z0-9_]{1,32}$. - Built-in
/startand/newcommands are always present unless you override them intelegram_commands.
Custom Telegram Commands #
You can register Telegram slash commands that map to prompt templates:
bots:
- name: my-bot
telegram_bot_token: "YOUR_TELEGRAM_BOT_TOKEN"
allowed_user_id: 123456789
project_path: /absolute/path/to/project
telegram_commands:
- command: review
description: Review the current branch and list bugs first.
- command: fix
description: Fix this issue: {args}
Behavior:
- Telegram shows these commands via
setMyCommands. - If
descriptioncontains{args}, text after the command replaces that placeholder. - Otherwise command arguments are appended to the description with a blank line.
Examples:
/reviewbecomesReview the current branch and list bugs first./fix login racebecomesFix this issue: login race
Runtime Behavior #
- One polling loop runs per configured bot.
- Only messages from
allowed_user_idare processed. /startreturns a short help message plus the registered command list./newclears the in-memory Codex thread for that Telegram chat.- Any other text message is forwarded to Codex.
- The current Codex thread ID is stored per chat and reused until
/newor process restart.
When invoking Codex, tgbot runs:
codex ...args exec --skip-git-repo-check --json <prompt>
If a thread already exists for the chat, it resumes with:
codex ...args exec resume --skip-git-repo-check --json <thread_id> <prompt>
Streaming and Replies #
tgbot reads Codex JSON output incrementally and forwards assistant messages to Telegram as they arrive. It also:
- keeps Telegram's typing indicator active while Codex is running
- avoids re-sending duplicate streamed messages
- chunks long Telegram messages at newline or word boundaries
- falls back to reconstructed assistant messages if only final JSON output is available
File and Image Delivery #
tgbot can send local artifacts back through Telegram during the same reply flow.
Preferred mechanism:
TG_ARTIFACT: {"kind":"image","path":"artifacts/plot.png","caption":"Latest chart"}
Supported artifact detection:
TG_ARTIFACT: {...}marker lines- standalone JSON artifact objects in Codex output
- local Markdown image/link syntax when no explicit artifact marker is present
Rules:
- image files are uploaded with
sendPhoto - non-image files are uploaded with
sendDocument - relative paths are resolved from
project_path - artifact paths must stay inside
project_path - missing files and path traversal are rejected
Error Handling #
- Telegram API calls retry up to 3 times on HTTP
429 - Telegram
retry_aftervalues are respected - empty outgoing messages are skipped
- Codex failures and timeouts are reported back to the Telegram chat
- bot tokens are never logged
Project Layout #
bin/tgbot.dart: CLI entry point and subcommandslib/tgbot.dart: public package exportslib/src/app.dart: bridge runtime and message routinglib/src/config.dart: YAML parsing and validationlib/src/codex/codex_runner.dart: Codex execution and output parsinglib/src/telegram/telegram_client.dart: Telegram Bot API clientlib/src/session/session_store.dart: in-memory per-chat thread statelib/src/models/telegram_models.dart: Telegram API modelsexample/main.dart: package exampletest/: unit tests
Development #
Run the standard Dart checks locally:
dart analyze
dart test
License #
MIT. See LICENSE.