Skip to content

poseidonchan/codex-telegram-bot

Repository files navigation

codex-telegram-bot (tgcodex-bot)

Run the codex CLI from Telegram with per-chat sessions, machine selection (local/SSH), and an approvals UI for command execution.

This is designed for private, single-operator use: you allowlist your Telegram user ID(s), then you can run Codex from your phone or desktop Telegram client.

Features

  • Private by default: Telegram user allowlist.
  • Stateful: persists a per-chat Codex session ID (resume across restarts).
  • Multi-machine: run on local or SSH targets.
  • Safer execution UX: inline approvals for exec requests (accept once / accept similar / reject).
  • Telegram-friendly output: buffered streaming with typing indicator.

Requirements

  • Python >= 3.10
  • A Telegram bot token (create via @BotFather)
  • The codex CLI installed and available on each machine you run on
  • Optional: asyncssh for SSH machines (installed by default on non-Windows)

Install

From the repo (recommended):

python -m pip install -e .

Or directly from GitHub:

python -m pip install "git+https://github.com/poseidonchan/codex-telegram-bot.git"

Quickstart

  1. Create a config using the setup wizard:
tgcodex-bot setup --config config.yaml
  1. Export your bot token into the env var you chose in the wizard (default: TELEGRAM_BOT_TOKEN):
export TELEGRAM_BOT_TOKEN="123456:ABC...keep_this_secret"
  1. Validate config:
tgcodex-bot validate-config --config config.yaml
  1. Start the bot:
# Detached background process (recommended for servers)
tgcodex-bot start --config config.yaml

# Foreground (useful for debugging)
tgcodex-bot run --config config.yaml
  1. In Telegram, open a private chat with your bot and send:
/start
/menu

Configuration

For a full reference, see config.example.yaml.

Minimal example:

telegram:
  token_env: TELEGRAM_BOT_TOKEN
  allowed_user_ids: [123456789]

state:
  db_path: ~/.tgcodex/tgcodex.sqlite3

codex:
  bin: codex
  args: []
  model: null
  sandbox: workspace-write
  approval_policy: on-request
  skip_git_repo_check: true

machines:
  default: local
  defs:
    local:
      type: local
      default_workdir: /home/ubuntu
      allowed_roots: [/home/ubuntu, /tmp]

Notes:

  • telegram.allowed_user_ids is your security boundary: if the user ID is not listed, the bot refuses requests.
  • allowed_roots restricts /cd and path resolution to an allowlist.
  • codex.approval_policy sets the default approval behavior for new chats (recommended: on-request). You can change it per chat with /approval.
  • For SSH machines you can override the remote codex path with machines.defs.<name>.codex_bin.

Running And Operations

Background Mode (Detached)

tgcodex-bot start --config config.yaml
tgcodex-bot status --config config.yaml
tgcodex-bot stop --config config.yaml

By default the runtime artifacts are created next to your config:

  • PID file: ./.tgcodex-bot/config.yaml.pid
  • Log file: ./.tgcodex-bot/config.yaml.log

Log tail:

tail -f .tgcodex-bot/config.yaml.log

Foreground Mode

tgcodex-bot run --config config.yaml

Telegram Commands

Start here:

  • /start: health check
  • /menu: list commands
  • /status: current machine/workdir/session + token telemetry

Session management:

  • /new: clear the active session (next message starts fresh)
  • /rename <title>: set the current session title
  • /resume: pick a recent session to resume
  • /exit: cancel an active run and clear session state

Environment:

  • /machine <name>: switch machine (clears session)
  • /cd <path>: change working directory (restricted by allowed_roots)

Run behavior:

  • /approval [on-request|yolo]: update approval mode (legacy aliases like untrusted, always, never still work)
  • /sandbox [read-only|workspace-write|danger-full-access]: set sandbox mode for this chat (applies next message; clears session)
  • /plan: toggle “plan mode”
  • /compact: compact the active session and continue in a new one
  • /model [slug] [effort]: pick a model (and thinking level if supported)
  • /skills: list available Codex skills (on the active machine)
  • /mcp: list MCP servers configured for Codex

Tip:

  • If you want to send a literal slash-prefixed prompt to Codex, you can type //... in Telegram and it will be rewritten to /....

Approvals And Safety Model

Execution approvals are shown as inline buttons:

  • Accept once
  • Accept similar (stores a trusted prefix for this session)
  • Reject

Approval modes:

  • on-request: approvals are required for commands outside Codex's trusted set; the bot shows inline Approve/Reject buttons and waits.
  • yolo: auto-accept approvals (no prompts). Sandbox stays enabled.

Sandbox vs YOLO

These are separate controls:

  • Sandbox controls what Codex is allowed to do when it runs tools/commands.

    • read-only: Codex can inspect, but should not modify files.
    • workspace-write: Codex can write within the allowed workspace scope.
    • danger-full-access: broad permissions; use only when you understand the risk.
  • YOLO controls approvals only.

    • In tgcodex, yolo means the bot auto-accepts approval requests.
    • YOLO does not disable the sandbox. To change sandbox behavior, use /sandbox.

Machines (Local And SSH)

You can define multiple machines and switch per chat with /machine.

Local machine:

  • Runs on the host where tgcodex-bot is running.

SSH machine:

  • Runs codex remotely via asyncssh.
  • Requires a reachable SSH host and correct auth settings.
  • If remote PATH isn’t initialized for non-interactive shells, set machines.defs.<name>.codex_bin to an absolute codex path.

Troubleshooting

Bot Starts But Doesn’t Reply

  1. Confirm it’s running:
tgcodex-bot status --config config.yaml
  1. Check logs:
tail -n 200 .tgcodex-bot/config.yaml.log
  1. Confirm you’re allowlisted:
  • Your Telegram user ID must be in telegram.allowed_user_ids.
  1. Ensure only one poller:
  • Running two instances with the same token will cause getUpdates conflicts.
  1. If your chat is set to an unreachable SSH machine:
  • Switch back to local:
    • /machine local

codex Not Found

  • Ensure codex is installed and in PATH on the active machine.
  • For SSH machines, set machines.defs.<name>.codex_bin to the absolute path.

Development

Install dev dependencies:

python -m pip install -e ".[dev]"

Run tests:

python -m pytest -q

Lint (if you use ruff):

ruff check .

Security Notes

  • Keep your bot token secret (use env vars; never commit it).
  • Do not commit config.yaml (this repo ignores it by default).
  • Logs and runtime files live in ./.tgcodex-bot/ (also ignored by default).
  • You are running a tool that can execute commands; use approval policies appropriately.

License

MIT. See LICENSE.

About

Coding with your favorite Codex via Telegram!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages