Skip to content
AlterMundiPublic
forked from Headcrab/telecodex

About

Telegram bridge for running your local Codex CLI remotely with topic-aware sessions, attachments, and streamed replies.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

🤖 Telecodex

Telegram as a remote, topic-aware frontend for your local Codex CLI.
Long polling. Persistent sessions. Attachment handling. Topic-aware workspace sync. SQLite ACLs.

Rust Telegram Bot API SQLite Codex CLI License: MIT


Maintained tribal fork

AlterMundi maintains this fork for a dedicated human Telegram channel into the existing native Codex harness. See deployment and continuity and private-topic configuration. Portable setup is distributed through AlterMundi/Skills. The qualified toolchain is Rust1.95.0; text builds use --locked --no-default-features.

An optional compact activity indicator shows tools, agent waits and native activity even for turns already running, without restarting the bridge or enabling unfinished answer previews.

✨ What it is

Telecodex is a Rust bridge that connects a local codex CLI instance to Telegram.

It turns Telegram chats and forum topics into lightweight remote workspaces where you can:

  • talk to Codex from your phone or desktop Telegram client,
  • keep separate sessions per chat/topic,
  • switch between existing Codex threads,
  • send files and media into a turn,
  • receive streamed progress and generated artifacts back in Telegram.

No webhook infrastructure. No browser dependency. No cloud relay between Telegram and your local Codex process.

🔥 Why it is useful

  • Remote terminal vibe, but usable: Telegram becomes the UI, Codex stays local.
  • Topic-aware sessions: each forum topic can map to its own workspace/session.
  • Safer multi-user access: SQLite-backed allowlist with admin and user roles.
  • Practical file flow: attachments go into a turn inbox, output files come back automatically.
  • Session memory without chaos: import local Codex Desktop/CLI history by cwd.
  • Codex-first runtime: Telecodex mirrors Codex sessions and settings instead of running its own local scheduler.

🧠 Core capabilities

Conversation and session model

  • Polls Telegram Bot API via getUpdates.
  • Maintains one logical session per Telegram chat/topic pair.
  • Queues turns per session and streams progress with private chat drafts or in-place Telegram message edits.
  • Shows the remaining weekly Codex allowance and reset time above live progress; /limits shows both the 5-hour and weekly windows.
  • Steers an active Codex turn with new plain-text messages, matching Codex's mid-turn follow-up behavior; messages with attachments remain queued as separate turns.
  • Queues outbound Telegram deliveries per chat, applies a safer group/topic send cadence, and backs off when Telegram returns retry_after.
  • Supports /new, /environments, /sessions, /use, /history, /status, /clear, /stop, /retry, /fast, and per-session runtime settings.
  • Can bind a Telegram topic to an existing Codex thread by thread id or latest.
  • In the primary forum dashboard, environments are listed for import and topics are created on button click by default.

Attachments and artifacts

  • Accepts text, images, documents, audio, and video attachments.
  • Stages incoming files under:
<session cwd>/.telecodex/inbox/...
  • Expects generated deliverables under:
<session cwd>/.telecodex/turns/.../out
  • Sends resulting files back to the originating topic automatically (at most ten top-level regular files per turn).
  • Supplies the current output contract through native turn/start.additionalContext with kind: application, instead of relying on overrides to a loaded thread. This requires a Codex App Server supporting that experimental surface (qualified with Codex 0.160.0). Session preferences and built-in collaboration modes remain separate. No modified Codex distribution is required.
  • Checks explicit references to old output directories or missing current files; it never scans or uploads historical directories. Claims without a file reference cannot prove that a file was created or delivered.
  • Records each upload attempt and matching Telegram acceptance in the private audit log. Acceptance is distinct from human receipt. On failure or an uncertain response, it reports the failure, retains nonempty turn output for explicit recovery, and does not automatically retry or replay the native input. Successful turn workspaces are cleaned up as before.

Audio transcription

  • Optional audio transcription via ffmpeg + transcribe-rs.
  • Auto-detects a local Handy Parakeet model directory when present.
  • If transcription succeeds, the transcript is appended to the user prompt.

Access control and safety

  • SQLite-backed ACL with allowed, admin, and user role handling.
  • Unauthorized access attempts are ignored and written to audit_log.
  • Supports Codex runtime defaults for sandbox, approval policy, search mode, and writable directories.
  • Supports headless Codex device login from Telegram via /login and /logout.
  • If Codex is not logged in, Telecodex does not start turns or forward Codex-native slash commands; it asks the user to authenticate first.

History and topic sync

  • Reads local Codex history and imports existing sessions by cwd.
  • Can browse final assistant messages from the selected Codex session with an interactive pager.
  • Can sync forum topics from Codex Desktop and/or CLI history.
  • Can target a dedicated Telegram forum chat for all new topics.
  • Supports stale topic cleanup on a timer.

🏗️ How it works

Telegram chat/topic
        ↓
     Telecodex
        ↓
 local codex CLI
        ↓
  workspace files
        ↓
 Telegram edits + artifacts

High-level flow:

  1. Telegram sends updates through long polling.
  2. Telecodex resolves the active session for the current chat/topic.
  3. Incoming text and attachments are converted into a Codex turn request. While a normal turn is active, new plain-text messages are sent to Codex through turn/steer; if steering is unavailable or terminally rejected, they fall back to the session queue.
  4. Codex runs locally in the configured workspace.
  5. Progress is streamed back with private chat drafts or Telegram message edits.
  6. Files produced in the turn output directory are uploaded back to Telegram.

🛠️ Command model

Bridge-handled commands

Command Purpose
/new [title] Start a fresh Codex session in the current topic/chat
/topic [title] Create a new Telegram topic and copy the current environment into it
/use <thread_id_prefix|latest> Switch this Telegram session to an existing Codex thread
/review [--uncommitted] [--base BRANCH] [--commit SHA] [--title TITLE] [prompt] Run codex review-style flows
/login Start headless Codex device login, send a clickable auth link, and show the one-time code inline
/logout Remove stored Codex credentials
/cd <absolute_path> Change the session working directory
/pwd Show the current working directory
/environments Show importable Codex environments in the primary forum dashboard
/sessions Show topic sessions in dashboard root, or Codex sessions for the current cwd inside a work topic
/history Browse final assistant messages from the selected Codex session with an interactive pager
/plan [prompt] Select native Plan mode for the topic's next turn; optionally queue a prompt
/default [prompt] Select native Default mode for the next turn; optionally queue a prompt
/questions Reopen your pending native questions in this topic
/icon Choose this topic's icon from Telegram's paginated emoji catalog
/status Show the current Telegram session, selected Codex session, and runtime settings
/rename <new name> Rename the current Codex session and Telegram topic together
/stop Stop the active turn
/retry <turn_id> Retry a failed or cancelled turn without attachments
/model [model|default|-] Set or show the current model
/think [minimal|low|medium|high|default|-] Set or show reasoning effort
/fast [on|off|status] Set or show fast mode for this session
/prompt [text|clear|default|-] Set or clear the persistent session prompt
/approval <never|on-request|untrusted> Set approval policy
/sandbox <read-only|workspace-write|danger-full-access> Set sandbox mode
/search <on|off|cached> Set search behavior
/add-dir <absolute_path> Add a writable directory
/limits Show Codex rate limits
/copy Re-send the last assistant reply
/clear Force a fresh session on the next turn
/allow <tg_user_id> Admin: allow a Telegram user
/deny <tg_user_id> Admin: deny a Telegram user
/role <tg_user_id> <admin|user> Admin: assign role
/restart_bot Admin: restart the bot process

/icon works inside private bot topics and forum topics, including on iOS. It fetches Telegram's allowed icon catalog and shows 24 emojis per page, with previous/next, default-icon and cancel buttons. Only the person who opened the picker can use it; buttons expire after 15 minutes, after selection/cancellation, or on restart. This command makes no Codex/model calls and does not change the topic name or native session. Telegram does not permit changing the General topic icon or the original default bubble color.

Forwarded to Codex as-is

/help, /doctor, /prompts, /memory, /mentions, /init, /bug, /config, /compact, /agents, /diff

These commands require an active Codex login. If the local Codex CLI is not authenticated yet, Telecodex will remind the user to run /login instead of forwarding them.

Explicitly unsupported in Telegram

/theme, /vim, /statusline, /browser, /ide, /notifications, /terminal-setup

⚙️ Requirements

Required

  • Rust 1.85+
  • a working local codex CLI available on PATH or configured explicitly
  • Telegram bot token
  • go-task

Optional but recommended

  • ffmpeg for audio/video conversion
  • a local Handy Parakeet model for speech transcription

🚀 Quick start

1. Clone and enter the repo

git clone https://github.com/Headcrab/telecodex.git
cd telecodex

2. Create the config

task init-config

This creates telecodex.toml from telecodex.toml.example if it does not exist.

3. Set your Telegram bot token

Set TELEGRAM_BOT_TOKEN in your environment before launch. Example:

export TELEGRAM_BOT_TOKEN="123456:replace-me"

4. Edit telecodex.toml

Minimal example:

db_path = "telecodex.sqlite3"
startup_admin_ids = [123456789]
poll_timeout_seconds = 30
edit_debounce_ms = 900
max_text_chunk = 3500
tmp_dir = "/absolute/path/to/telecodex/tmp"

[telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
api_base = "https://api.telegram.org"
use_message_drafts = true

[codex]
binary = "codex"
default_cwd = "/absolute/path/to/telecodex"
default_model = "gpt-5.4"
default_reasoning_effort = "medium"
default_sandbox = "workspace-write"
default_approval = "never"
default_search_mode = "live"
import_desktop_history = true
import_cli_history = true
seed_workspaces = ["/absolute/path/to/workspace-a"]
default_add_dirs = ["/absolute/path/to/workspace"]

5. Run it

task run

6. Log in to Codex from Telegram

After the bot starts, open the Telegram chat with your bot and run:

/login

Telecodex will start codex login --device-auth, send a clickable auth.openai.com link, show the one-time code inline in the message for quick copying, and post the result in chat when the login finishes.

🧩 Configuration notes

Telegram

  • telegram.bot_token or telegram.bot_token_env must be configured.
  • telegram.use_message_drafts = true enables sendMessageDraft previews for private chats; final replies are still sent as normal messages.
  • telegram.show_unfinished_messages = false hides unfinished text, tool progress and placeholders. Completed commentary and final responses are published permanently. This overrides draft previews; the default is true.
  • Group and topic previews use throttled editMessageText updates, and outbound Telegram deliveries are paced per chat to avoid Bot API rate limits.
  • telegram.primary_forum_chat_id is used by /topic to create topics in one dedicated forum.
  • telegram.auto_create_topics = false keeps environment import manual; set it to true to auto-create missing forum topics from history.
  • telegram.forum_sync_topics_per_poll throttles topic sync work.
  • telegram.stale_topic_days + telegram.stale_topic_action = "close"|"delete" enable cleanup.

Codex

  • codex.binary can be a binary name or absolute path.
  • codex.default_cwd must be an existing absolute directory.
  • codex.seed_workspaces adds explicit workspace directories to /environments and forum sync, even before they have local Codex history.
  • codex.default_add_dirs entries must also be absolute existing directories.
  • codex.import_desktop_history and codex.import_cli_history control session import sources.
  • codex.default_search_mode defaults to live; explicit disabled and cached choices remain supported. Existing topics retain their saved mode until changed with /search live.

Environment variables

  • TELEGRAM_BOT_TOKEN: Telegram Bot API token.
  • TELECODEX_RESTART_DELAY_MS: optional startup delay before boot.

📁 Project layout

src/
  app.rs            # main runtime loop and orchestration
  app/
    auth.rs         # Codex login/logout and device-code flow
    forum.rs        # forum/topic sync
    io.rs           # attachments and Telegram status delivery
    presentation.rs # formatting and keyboards
    support.rs      # shared helpers
    tests.rs        # app-level tests
    turns.rs        # turn execution pipeline
  commands.rs       # command parsing and help
  config.rs         # config loading and validation
  telegram.rs       # Telegram Bot API client
  store.rs          # SQLite persistence
  transcribe.rs     # optional audio transcription

🧪 Development

Build and run:

task build
task build-release
task run
task run-release

Validation:

task test
task verify

Available quality tasks:

task fmt
task fmt-check
task check
task clippy

Override config path when needed:

task run CONFIG=telecodex.toml

📌 Practical behavior notes

  • Unauthorized updates are ignored and logged into audit_log.
  • Existing Codex history can be auto-attached by cwd unless /clear was used.
  • /sessions is contextual: in dashboard root it shows Telegram topic sessions, while inside a work topic it shows Codex sessions for the current cwd.
  • /history browses final assistant messages from the selected Codex session, starts from the newest message, and wraps around at both ends.
  • In the primary forum dashboard, /environments shows importable environments and creates topics only when you press the button unless telegram.auto_create_topics = true.
  • /new now resets the Codex conversation inside the current topic and keeps the current environment/runtime settings.
  • /topic is the explicit path for creating a new Telegram topic from the current environment.
  • /think and /prompt persist for the current session and affect future turns.
  • During active work the bot sends Telegram chat actions such as typing/upload indicators.
  • In forum dashboard root, use /environments or /sessions; /status, /history, /new, and normal prompts are meant for an actual work topic.
  • /login starts Codex device authentication in headless mode and sends a clickable auth link plus the one-time code inline in the message.
  • If the device-code endpoint returns 429 Too Many Requests, the bot reports that in chat and applies a short local backoff before the next /login attempt.
  • After /logout, the bot stays responsive and keeps suggesting /login instead of going silent.
  • /status is handled by Telecodex itself and shows the current Telegram session, selected Codex session, and runtime settings.
  • If Codex is not logged in, Telecodex does not run turns and does not forward Codex-native slash commands; it asks the user to authenticate first.
  • If a live prompt clearly asks for fresh information like "today", "latest", or "news", Telecodex can automatically switch that turn to live search.

📄 License

This project is licensed under the MIT License.


Built for people who want Codex local, but reachable from Telegram.

Native planning, question controls and recovery are documented in native questions. The Telegram convergence pilot records source provenance and reuse decisions.

Fork a conversation

Use /fork Shared Resources in an idle, bound work topic to create a named Telegram topic backed by Codex's native thread/fork. The creator's conversation history is shared through the fork; future messages diverge. Compacted history retains its native representation. Workspace files remain shared. No model turn is started by an unquoted command. Running tools and pending questions are not copied.

The child retains session settings and gets an origin notice in Telegram and once in its first native input. Native and Telegram titles are coordinated. Fork stages are recorded in the private audit log (fork_requested, fork_native_created, fork_topic_created, fork_bound) with a common operation identifier. If a mutating RPC times out, inspect that record and reconcile the existing child/topic before retrying; uncertain effects are never retried automatically. A title-only failure can be repaired with /rename in the child. Requires a Codex App Server supporting thread/fork with excludeTurns and Telegram topic support. This command creates no worktree or Matrix attention.

When /fork Name is sent as a reply containing text or a caption, it creates a fresh context handoff rather than cloning native history. One bounded summarization turn selects relevant original text excerpts and synthesizes older available context through the quote. The handoff is loaded on the child's first successful native turn; source history and its saved instructions remain unchanged. Source entries are restricted to the quoted turn's native conversation, at most 120 earlier completed turns and a 96 KB earlier-text budget; individual texts are excerpted when long. Up to six selected entries, including the quote, accompany the summary. Model output must identify actual source entries; generated replacements are not treated as quotes.

Exact Telegram boundaries require the durable ingress journal and native turn binding, or the new outgoing message correlation. Without that mapping, the bridge searches only the currently bound native conversation for one literal occurrence of the quoted text, normalizing whitespace and projecting bot Markdown to visible text. A unique occurrence selects the entire completed native turn, including its assistant response; both notices and context declare this coarser boundary. Later turns are excluded. Ambiguous, missing or unfinished matches, incomplete pagination, and searches exceeding 5,000 turns or 128 MiB are rejected before summarization or topic creation. Empty reply references use the ordinary native fork. The bridge never guesses a boundary or silently substitutes a full fork. Summary failure creates no destination. Later creation/delivery failures retain audit stages for reconciliation without automatic replay. Summarization uses an ephemeral thread, empty workspace, read-only sandbox, disabled search, shell and configured MCP servers, and no source task continuation. This mode requires config/read, ephemeral thread/start and structured turn/start output support; no modified Codex distribution is required.

The optional activity companion also reads thread/goal/get for /status, showing native goal state and a literal, length-bounded objective, including paused and blocked goals. This is a metadata read without model inference. Goals do not create a Working card while idle; unavailable goal APIs omit the goal line.

Human-triggered Tribu topic

An explicitly configured [tribu] policy connects genuine paired-human public @ requests to the same persistent conversation as an existing private Tribu topic. This is opt-in and Source-only for the current rollout. It uses the maintained authenticated Matrix human ingress and a private local Unix socket; it does not consume the public bot again or watch peer inboxes.

The policy pins socket_path, owner_client_file, being_ref, body_label, embodiment_id, human_id, chat_id, topic_id and activated_after. deadline_seconds defaults to 300 (maximum 300); max_pending defaults to 20. The destination must be a fresh, authorized topic named Tribu, with shared App Server enabled. Public admissions and ordinary private messages use one queue and writer; new private messages do not steer an active turn. Every turn receives its start, limit and UTC deadline before work, including continuations. Native goals and multi-agent continuation are disabled for this dedicated thread.

/tribu pause persistently closes admission and requests interruption; /tribu resume accepts new input without replaying withdrawn work. /tribu status reports retained states; /tribu reconcile checks only the already-admitted native turn. Unconfirmed termination blocks subsequent dispatch. Session replacement and goal/review commands are disabled in this topic.

For rollback, pause this writer and disable ingress admission while keeping the qualified writer, conversation, databases and polling offsets. Older binaries without the dedicated controls must not accept input in this topic. Live human acceptance is separate from synthetic HTTP/TLS/socket/native contract tests.

About

Telegram bridge for running your local Codex CLI remotely with topic-aware sessions, attachments, and streamed replies.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages