codex-telegram-relay
v0.2.0
Published
Lightweight Codex x Telegram bot relay
Readme
Codex Telegram Relay
Run Codex from private Telegram chats.
Start
Run it directly without installing the package globally:
npx codex-telegram-relayForeground mode keeps the relay attached to the current terminal. If you close the terminal, log out, reboot the computer, or the process crashes, the relay stops.
Config
Default config path: ~/.codex-telegram-relay/config.json
Example:
{
"allowedUsernames": ["your-telegram-username"],
"bots": [
{
"name": "primary",
"token": "YOUR_TELEGRAM_BOT_TOKEN",
"workdir": "/Users/you/project",
"auto": "medium",
"schedules": [
{
"name": "daily-report",
"auto": "medium",
"cron": "0 9 * * 1-5",
"prompt": "Summarize the most important repo changes today.",
"chatId": 123456789,
"enabled": true
}
],
"model": "default",
"reasoningEffort": "default"
}
]
}Notes:
- Top-level
allowedUsernamesis optional and merged into every bot. - Bot-level
allowedUsernamesis optional and is merged with the top-level list. allowedUsernamesmatching is case-insensitive and accepts values with or without@.namemust be unique and may contain only letters, numbers,_, and-.workdiris optional. If omitted, the relay uses your home directory. It must already exist.autodefaults tomedium.schedulesis optional. Each schedule is tied to one Telegram private chat bychatId.- Each schedule must define its own
autolevel. - Schedule
cronuses the standard five-field numeric format:minute hour day-of-month month day-of-week. modelandreasoningEffortdefault todefault, which means the relay does not pass an override tocodex exec.auto: lowmaps tocodex exec --sandbox read-only.auto: mediummaps tocodex exec --sandbox workspace-write.auto: highmaps tocodex exec --dangerously-bypass-approvals-and-sandbox.- If you do not know your Telegram username, send the bot any message once. The unauthorized reply shows the normalized username to add.
- Multiple bots can be configured in one file and run in one process.
Persistent Deployment
The relay does not daemonize itself and does not restart itself after crashes or reboots. For always-on usage, run it under a process manager.
PM2 Example
Use PM2 when you want the relay to keep running in the background and restart automatically after crashes:
npm install -g pm2 codex-telegram-relay
pm2 start codex-telegram-relay --name codex-telegram-relay
pm2 saveUseful PM2 commands:
pm2 statuspm2 logs codex-telegram-relaypm2 restart codex-telegram-relaypm2 stop codex-telegram-relay
Telegram Commands
/statusshows running state, current workdir, auto/model/reasoning values, the latest context length, and the queued messages for the current chat./schedule listshows schedules for the current chat./schedule add <name> <auto>creates a schedule for the current chat. Put the cron expression on the next line, then the prompt below it./schedule pause <name>pauses a schedule for the current chat./schedule resume <name>resumes a paused schedule for the current chat./schedule delete <name>deletes a schedule for the current chat./schedule run <name>starts a schedule immediately./workdirshows the current bot workdir./workdir <path>changes the bot workdir. Only absolute paths and~/...are accepted./autoshows the current auto level./auto <low|medium|high>sets the auto level for future runs in the current chat and persists the bot default./modelshows the current model value./model <value>sets the model for future runs in the current chat and persists the bot default. Use/model defaultto return to CLI defaults./reasoningshows the current reasoning value./reasoning <value>sets reasoning effort for future runs in the current chat and persists the bot default. Use/reasoning defaultto return to CLI defaults./resetreloads the current bot defaults fromconfig.json, clears chat-specific auto/model/reasoning overrides, and starts a fresh session for this chat./clear_cachedeletes cached Telegram attachments for the current bot instance./abortinterrupts Codex and clears the queued messages while keeping the currentthreadId./newinterrupts Codex, clears queued messages, and drops the current chat's storedthreadId.
Behavior
- Only private chats are supported.
- Each
(bot, chat)pair has its own queue,threadId, and usage state. - Supported Telegram attachments are
photo,document,video,audio,voice, andanimation. photoattachments are passed tocodex execnatively with--image. Other supported attachments are downloaded to~/.codex-telegram-relay/cache/<bot-name>/c<base36-chat-id>/...and passed to Codex by local file path in the prompt.- Captionless photo-only turns send an empty prompt plus one or more
--imageflags. - Telegram media albums are grouped by
media_group_idand submitted as one logical Codex turn. - Attachments larger than 20 MB are rejected.
- Fresh prompts use
codex exec --json --skip-git-repo-check; continued prompts usecodex exec resume. - Fresh interactive threads and scheduled ephemeral runs inject relay-specific
developer_instructionsthat tell Codex to prefer Telegram HTML-compatible output. - Scheduled prompts use a fresh
codex exec --ephemeral --output-last-message ...run with the schedule's ownautolevel and send only the lastagent_messageback to Telegram, prefixed with[schedule: <name>]. - Scheduled runs are independent from the chat's interactive session and their messages may interleave with normal replies in the same chat.
- The relay persists
threadIdfromthread.startedand the latestcontext_lengthfor the chat. context_lengthis derived from the finaltoken_count.last_token_usageevent in the thread's rollout file under~/.codex/sessions/....- Completed
agent_messageitems become the visible final reply. - Non-message items such as
reasoning,web_search, andcommand_executionreuse one in-flight Telegram message that is edited as progress changes. - Telegram sends replies with
HTMLparse mode first, then falls back toMarkdownV2, then plain text if parsing still fails. - Slash commands that change bot settings persist those defaults to
config.json. They apply immediately to the invoking chat; other already-loaded chats keep their current in-memory settings until restart. /clear_cacheis bot-wide. It clears only~/.codex-telegram-relay/cache/<bot-name>/and refuses to run while turns or media albums are pending./workdir <path>is bot-wide. It updates the stored bot workdir, aborts the invoking chat's current run, clears that chat's queue, and resets that chat to a fresh Codex session./abortaffects only the interactive run and queue for the current chat. It does not cancel scheduled runs.
