tgbot 0.0.5
tgbot: ^0.0.5 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 Telegram bots to the Codex CLI. It long-polls Telegram, forwards authorized messages into Codex, preserves a per-chat thread, and sends text, files, and images back to Telegram.
Install #
dart pub global activate tgbot
Requirements #
- Dart SDK installed
- Codex CLI installed and available on
PATHunless you overridecodex_cmd - A Telegram bot token from
@BotFather - Your Telegram user ID
Quick Start #
Initialize a 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
CLI #
tgbot <command> [options]
| Command | Description |
|---|---|
start |
Start the Telegram-Codex bridge |
init |
Generate a starter tgbot.yaml |
validate |
Validate a config file without starting |
upgrade |
Upgrade tgbot with dart pub global activate tgbot |
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
Getting Telegram Credentials #
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 this user ID 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 definitions.defaults(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:
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
project_path: /absolute/path/to/repo-a
- 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 project path used as Codex working directory |
codex_cmd |
No | Codex executable, default codex |
codex_args |
No | String or list of extra args inserted before built-in exec |
codex_allow_dirs |
No | String or list of extra directories appended as --add-dir; ~ is expanded |
poll_timeout_sec |
No | Telegram long-poll timeout, default 60 |
codex_timeout_sec |
No | Per-request Codex timeout, default 1000 |
additional_system_prompt |
No | Extra system instructions injected before each user request |
telegram_commands |
No | Extra Telegram slash commands registered for this bot |
Notes:
defaultsvalues are used when a bot omits that key.project_pathcan be inherited fromdefaults, but every bot must have an effective value.codex_argsaccepts either a YAML list or a whitespace-delimited string.codex_allow_dirsaccepts either a YAML list or a comma-delimited string.- Built-in
/startand/newcommands are always present. If you redefine them intelegram_commands, your definition wins.
Custom Telegram Commands #
You can register additional 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. - Command names must match
^[a-z0-9_]{1,32}$. - If
descriptioncontains{args}, the message text after the command replaces that placeholder. - Otherwise the command arguments are appended after the description.
Examples:
/review->Review the current branch and list bugs first./fix login race->Fix this issue: login race
Runtime Behavior #
- One polling loop runs per configured bot.
- Only messages from
allowed_user_idare processed. /startreturns usage help plus all registered commands./newresets the saved Codex thread for that Telegram chat.- Any other text message is sent to Codex.
- The current Codex thread ID is stored per chat, so follow-up messages continue the same conversation until
/new.
When invoking Codex, tgbot currently runs:
codex ...args exec --skip-git-repo-check --json <prompt>
If a thread already exists for the chat, it instead 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 the final parsed message if Codex only emits a completed result
File and Image Delivery #
tgbot can send local artifacts back to Telegram in the same response 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 retry_afteris respected when Telegram provides it- empty outgoing messages are skipped
- Codex process failures and timeouts are returned to the Telegram chat as errors
- 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 process 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 models
Development #
Validate package metadata and code locally with standard Dart tooling:
dart analyze
dart test
dart test requires tests to exist in the package. At the moment this repository does not include a test/ directory.
License #
MIT. See LICENSE.