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.
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.
- 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
adminanduserroles. - 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.
- 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;
/limitsshows 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.
- 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.additionalContextwithkind: 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.
- 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.
- SQLite-backed ACL with
allowed,admin, anduserrole 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
/loginand/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.
- 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.
Telegram chat/topic
↓
Telecodex
↓
local codex CLI
↓
workspace files
↓
Telegram edits + artifacts
High-level flow:
- Telegram sends updates through long polling.
- Telecodex resolves the active session for the current chat/topic.
- 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. - Codex runs locally in the configured workspace.
- Progress is streamed back with private chat drafts or Telegram message edits.
- Files produced in the turn output directory are uploaded back to Telegram.
| 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.
/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.
/theme, /vim, /statusline, /browser, /ide, /notifications, /terminal-setup
- Rust
1.85+ - a working local
codexCLI available onPATHor configured explicitly - Telegram bot token
- go-task
ffmpegfor audio/video conversion- a local Handy Parakeet model for speech transcription
git clone https://github.com/Headcrab/telecodex.git
cd telecodextask init-configThis creates telecodex.toml from telecodex.toml.example if it does not exist.
Set TELEGRAM_BOT_TOKEN in your environment before launch. Example:
export TELEGRAM_BOT_TOKEN="123456:replace-me"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"]task runAfter 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.
telegram.bot_tokenortelegram.bot_token_envmust be configured.telegram.use_message_drafts = trueenablessendMessageDraftpreviews for private chats; final replies are still sent as normal messages.telegram.show_unfinished_messages = falsehides unfinished text, tool progress and placeholders. Completed commentary and final responses are published permanently. This overrides draft previews; the default istrue.- Group and topic previews use throttled
editMessageTextupdates, and outbound Telegram deliveries are paced per chat to avoid Bot API rate limits. telegram.primary_forum_chat_idis used by/topicto create topics in one dedicated forum.telegram.auto_create_topics = falsekeeps environment import manual; set it totrueto auto-create missing forum topics from history.telegram.forum_sync_topics_per_pollthrottles topic sync work.telegram.stale_topic_days+telegram.stale_topic_action = "close"|"delete"enable cleanup.
codex.binarycan be a binary name or absolute path.codex.default_cwdmust be an existing absolute directory.codex.seed_workspacesadds explicit workspace directories to/environmentsand forum sync, even before they have local Codex history.codex.default_add_dirsentries must also be absolute existing directories.codex.import_desktop_historyandcodex.import_cli_historycontrol session import sources.codex.default_search_modedefaults tolive; explicitdisabledandcachedchoices remain supported. Existing topics retain their saved mode until changed with/search live.
TELEGRAM_BOT_TOKEN: Telegram Bot API token.TELECODEX_RESTART_DELAY_MS: optional startup delay before boot.
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
Build and run:
task build
task build-release
task run
task run-releaseValidation:
task test
task verifyAvailable quality tasks:
task fmt
task fmt-check
task check
task clippyOverride config path when needed:
task run CONFIG=telecodex.toml- Unauthorized updates are ignored and logged into
audit_log. - Existing Codex history can be auto-attached by
cwdunless/clearwas used. /sessionsis contextual: in dashboard root it shows Telegram topic sessions, while inside a work topic it shows Codex sessions for the currentcwd./historybrowses final assistant messages from the selected Codex session, starts from the newest message, and wraps around at both ends.- In the primary forum dashboard,
/environmentsshows importable environments and creates topics only when you press the button unlesstelegram.auto_create_topics = true. /newnow resets the Codex conversation inside the current topic and keeps the current environment/runtime settings./topicis the explicit path for creating a new Telegram topic from the current environment./thinkand/promptpersist 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
/environmentsor/sessions;/status,/history,/new, and normal prompts are meant for an actual work topic. /loginstarts 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/loginattempt. - After
/logout, the bot stays responsive and keeps suggesting/logininstead of going silent. /statusis 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.
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.
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.
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.