Skip to content

strato-space/ccbot

 
 

Repository files navigation

CCBot

中文文档 Русская документация

Control Codex tmux sessions remotely via Telegram — monitor, interact, and manage AI coding work without leaving the live terminal surface.

Jietu20260207-final.mp4

Why CCBot?

Codex runs in your terminal. When you step away from your computer — commuting, on the couch, or just away from your desk — the session keeps working, but you lose visibility and control.

CCBot solves this by letting you seamlessly continue the same terminal-backed conversation from Telegram. The key insight is that it operates on tmux, not a hosted agent API. Your Codex process stays exactly where it is, in a tmux window on your machine. CCBot simply reads its output and sends keystrokes to it. This means:

  • Switch from desktop to phone mid-conversation — Codex is working on a refactor? Walk away, keep monitoring and responding from Telegram.
  • Switch back to desktop anytime — Since the tmux session was never interrupted, just tmux attach and you're back in the terminal with full scrollback and context.
  • Run multiple conversations in parallel — Each Telegram topic maps to a separate tmux window, so you can juggle multiple projects from one chat group.

Other Telegram bots often wrap a separate API session that cannot be resumed in your terminal. CCBot takes a different approach: it's just a thin control layer over tmux, so the terminal remains the live control surface and you never lose the ability to switch back.

In fact, CCBot itself was built this way — iterating on itself through terminal sessions monitored and driven from Telegram via CCBot.

Runtime Model

The Codex adaptation work uses an explicit runtime ontology to avoid collapsing live tmux control, persisted conversation identity, and on-disk rollout evidence into a single "session" concept.

Maintainer reference:

Strato Ops

For the Strato fork, use the operator runbook in doc/strato-ops-codex.md. It documents:

  • the live tmux -> Codex -> rollout log operating path
  • the legacy CLAUDE_COMMAND env var name that now launches codex
  • one-time state migration and reversible rollback via *.v1.bak
  • the operator tooling path /home/tools/codex-tools/codex-session-scout
  • the release-scope boundary: voice, task, and ACP are preserved but not expanded in this Codex release

Features

  • Topic-based control — Each Telegram topic binds to one tmux window at a time, while the live process in that window may start or resume a persisted conversation
  • Real-time notifications — Get Telegram messages for assistant responses, thinking content, tool use/result, and local command output
  • Prompt-safe control lane — Detect input ready, busy, and blocked prompt terminal states before sending input
  • Voice messages — Voice messages are transcribed via OpenAI and forwarded as text
  • Send messages — Forward text to Codex via tmux keystrokes
  • Codex command forwarding — Forward raw Codex slash commands, with a small supported menu surface for /clear, /compact, /diff, /init, /review, and /status
  • Create new sessions — Start Codex sessions from Telegram via directory browser
  • Resume sessions — Pick up where you left off by resuming an existing Codex thread in a directory
  • Kill sessions — Close a topic to auto-kill the associated tmux window
  • Message history — Browse conversation history with pagination (newest first)
  • Explicit process registration — Auto-associates tmux windows with Codex processes at launch time
  • Persistent state — Thread bindings and read offsets survive restarts

Prerequisites

  • tmux — must be installed and available in PATH
  • Codex CLI — the codex binary must be installed

Installation

Option 1: Install from GitHub (Recommended)

# Using uv (recommended)
uv tool install git+https://github.com/strato-space/ccbot.git

# Or using pipx
pipx install git+https://github.com/strato-space/ccbot.git

Option 2: Install from source

git clone https://github.com/strato-space/ccbot.git
cd ccbot
uv sync

Configuration

1. Create a Telegram bot and enable Threaded Mode:

  1. Chat with @BotFather to create a new bot and get your bot token
  2. Open @BotFather's profile page, tap Open App to launch the mini app
  3. Select your bot, then go to Settings > Bot Settings
  4. Enable Threaded Mode

2. Configure environment variables:

Create ~/.ccbot/.env:

TELEGRAM_BOT_TOKEN=your_bot_token_here
ALLOWED_USERS=your_telegram_user_id

Required:

Variable Description
TELEGRAM_BOT_TOKEN Bot token from @BotFather
ALLOWED_USERS Comma-separated Telegram user IDs

Optional:

Variable Default Description
CCBOT_DIR ~/.ccbot Config/state directory (.env loaded from here)
TMUX_SESSION_NAME ccbot Tmux session name
CLAUDE_COMMAND claude Legacy env var name for the command run in new windows; set this explicitly to codex or your Codex wrapper in this fork
MONITOR_POLL_INTERVAL 2.0 Polling interval in seconds
CCBOT_SHOW_HIDDEN_DIRS false Show hidden (dot) directories in directory browser
OPENAI_API_KEY (none) OpenAI API key for voice message transcription
OPENAI_BASE_URL https://api.openai.com/v1 OpenAI API base URL (for proxies or compatible APIs)

Message formatting is always HTML via chatgpt-md-converter (chatgpt_md_converter package). There is no runtime formatter switch to MarkdownV2.

For Codex, prefer setting approval and sandbox policy explicitly in the launch command rather than relying on interactive approval prompts in a detached terminal.

Launch Behavior

CCBot registers live processes at launch time and then resolves them onto persisted Codex threads. The tmux window is the live write target; the thread and rollout log remain separate persisted identities.

Usage

# If installed via uv tool / pipx
ccbot

# If installed from source
uv run ccbot

Commands

Bot commands:

Command Description
/start Show welcome message
/history Message history for this topic
/screenshot Capture terminal screenshot
/esc Send Escape to interrupt Codex
/unbind Detach this topic from its live window
/usage Legacy Claude-only helper; Codex users should prefer /status

Supported Codex commands shown in the Telegram menu:

Command Description
/clear Start a fresh chat in the bound window
/compact Compact the current thread context
/diff Show git diff
/init Create AGENTS.md for Codex
/review Review current changes
/status Show Codex session status

Other raw /command inputs are still forwarded best-effort to the Codex TUI, but they are not part of the supported Telegram command surface unless documented above. This is intentional: commands that depend on prompt selection or other unsupported remote controls are not advertised in the menu even if Codex can handle them locally. Claude-only commands such as /cost, /help, /memory, and /usage are not part of the supported Codex lane.

Topic Workflow

1 Topic = 1 live tmux binding at a time. The bot runs in Telegram Forum (topics) mode.

Each topic controls one tmux window at a time. The process inside that window may start a fresh conversation or resume an existing persisted thread.

Creating a new session:

  1. Create a new topic in the Telegram group
  2. Send any message in the topic
  3. A directory browser appears — select the project directory
  4. If the directory has existing Codex threads, a thread picker appears — choose one to resume or start fresh
  5. A tmux window is created, codex starts (with resume wiring if resuming), and your pending message is forwarded

Sending messages:

Once a topic is bound to a window, just send text or voice messages in that topic — text gets forwarded to Codex via tmux keystrokes, and voice messages are automatically transcribed and forwarded as text.

Killing a session:

Close (or delete) the topic in Telegram. The associated tmux window is automatically killed and the binding is removed.

Message History

Navigate with inline buttons:

📋 [project-name] Messages (42 total)

───── 14:32 ─────

👤 fix the login bug

───── 14:33 ─────

I'll look into the login bug...

[◀ Older]    [2/9]    [Newer ▶]

Notifications

The monitor polls session JSONL files every 2 seconds and sends notifications for:

  • Assistant responses — Codex text replies
  • Thinking content — Shown as expandable blockquotes
  • Tool use/result — Summarized with stats (e.g. "Read 42 lines", "Found 5 matches")
  • Local command output — stdout from commands like git status, prefixed with ❯ command_name

Notifications are delivered to the topic bound to the session's window.

Formatting note:

  • Telegram messages are rendered with parse mode HTML using chatgpt-md-converter
  • Long messages are split with HTML tag awareness to preserve code blocks and formatting

Running Codex in tmux

Option 1: Create via Telegram (Recommended)

  1. Create a new topic in the Telegram group
  2. Send any message
  3. Select the project directory from the browser

Option 2: Create Manually

tmux attach -t ccbot
tmux new-window -n myproject -c ~/Code/myproject
# Then start Codex in the new window
codex

The window must be in the ccbot tmux session (configurable via TMUX_SESSION_NAME). CCBot registers the live process when it launches the window and then resolves the persisted thread from local Codex state.

Data Storage

Path Description
$CCBOT_DIR/state.json Thread bindings, window states, display names, and per-user read offsets
$CCBOT_DIR/session_map.json Versioned live process registrations and thread hints per tmux window
$CCBOT_DIR/monitor_state.json Monitor byte offsets per session (prevents duplicate notifications)
~/.codex/session_index.jsonl Persisted Codex thread index (read-only)
~/.codex/sessions/ Codex rollout logs and thread state (read-only)

File Structure

src/ccbot/
├── __init__.py            # Package entry point
├── main.py                # CLI dispatcher (hook subcommand + bot bootstrap)
├── hook.py                # Hook subcommand for session tracking (+ --install)
├── config.py              # Configuration from environment variables
├── bot.py                 # Telegram bot setup, command handlers, topic routing
├── session.py             # Session management, state persistence, message history
├── session_monitor.py     # JSONL file monitoring (polling + change detection)
├── monitor_state.py       # Monitor state persistence (byte offsets)
├── transcript_parser.py   # Legacy transcript parsing + normalized rollout event shaping
├── terminal_parser.py     # Terminal pane parsing (interactive UI + status line)
├── html_converter.py      # Markdown → Telegram HTML conversion + HTML-aware splitting
├── screenshot.py          # Terminal text → PNG image with ANSI color support
├── transcribe.py          # Voice-to-text transcription via OpenAI API
├── utils.py               # Shared utilities (atomic JSON writes, JSONL helpers)
├── tmux_manager.py        # Tmux window management (list, create, send keys, kill)
├── fonts/                 # Bundled fonts for screenshot rendering
└── handlers/
    ├── __init__.py        # Handler module exports
    ├── callback_data.py   # Callback data constants (CB_* prefixes)
    ├── directory_browser.py # Directory browser inline keyboard UI
    ├── history.py         # Message history pagination
    ├── interactive_ui.py  # Interactive UI handling (AskUser, ExitPlan, Permissions)
    ├── message_queue.py   # Per-user message queue + worker (merge, rate limit)
    ├── message_sender.py  # safe_reply / safe_edit / safe_send helpers
    ├── response_builder.py # Response message building (format tool_use, thinking, etc.)
    └── status_polling.py  # Terminal status line polling

Contributors

Thanks to all the people who contribute! We encourage using Codex to collaborate on contributions.

About

Telegram ↔ tmux bridge for Claude Code: 1 topic = 1 window = 1 session

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 99.6%
  • Shell 0.4%