NAME
cli-discord-bridge — CLI Discord bridge with Codex-first runtime and legacy Claude compatibility.
SYNOPSIS
pip install -rINFO
DESCRIPTION
CLI Discord bridge with Codex-first runtime and legacy Claude compatibility.
README
CLI Discord Bridge
Single-file Discord bridge for Codex CLI operation.
The actively maintained runtime targets Codex: one Discord channel connects to one Codex CLI process. Legacy artifacts remain only for rollback and command continuity.
Command surface remains compatible with earlier bridge flows:
/new /status /connect /handoff /help.
Deployment Topology
- Single process, single channel, single vendor (Codex)
- One process listens to exactly one
CHANNEL_ID - Multi-channel or multi-vendor HA is done by duplicating processes, not by mixing routes in one process
Runtime Flow
Discord message -> bridge.py -> codex exec/resume --json -> parse JSON events -> Discord reply
Bridge state:
- State dir:
~/.cli-discord-bridge/ - Session file:
~/.cli-discord-bridge/session.json- Primary key:
thread_id - Backward-compatible read: legacy
session_id
- Primary key:
- Handoff dir:
~/.cli-discord-bridge/handoffs/
Codex Session Protocol
- New thread:
codex exec --json --skip-git-repo-check [--dangerously-bypass-approvals-and-sandbox] [-m MODEL] "<prompt>"
- Resume thread:
codex exec resume --json --skip-git-repo-check [--dangerously-bypass-approvals-and-sandbox] [-m MODEL] <thread_id> "<prompt>"
- Parser rules:
- Parse JSON lines only, ignore non-JSON noise
- Use
thread.started.thread_idas authoritative thread ID - Aggregate
item.completed.item.type=="agent_message"text as reply body
/connect safety:
- Explicit
/connect <thread_id>is strict. - If resume returns a different
thread.started.thread_id, bridge treats it as failure and blocks auto-fallback.
Implicit fallback:
- In non-explicit mode, resume failure may switch to a new thread and update local state.
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
DISCORD_TOKEN | Yes | — | Discord bot token |
CHANNEL_ID | Yes | — | Discord channel ID |
CODEX_BIN | No | codex | Codex CLI binary path |
CODEX_MODEL | No | empty | Optional model override |
CODEX_TIMEOUT | No | 300 | Max seconds per Codex call |
CODEX_CWD | No | $HOME | Working directory for Codex call |
CODEX_FULL_ACCESS | No | 0 | 1 enables --dangerously-bypass-approvals-and-sandbox |
SELFTEST_ON_START | No | 0 | 1 runs startup selftest |
Compatibility fallback (for smooth migration):
CLAUDE_CWDcan still be used ifCODEX_CWDis not setCLAUDE_TIMEOUTcan still be used ifCODEX_TIMEOUTis not set
Commands
| Command | Behavior |
|---|---|
/new | Clear current thread; next message creates a new thread |
/status | Show current thread, cwd, timeout, backend |
/connect [thread-id] | Bind explicit thread (no arg = reset) |
/handoff | Summarize old thread -> coldstart new thread; rollback old thread if new bootstrap fails |
/help | Show command help |
Local Run
python3 -m venv .venv .venv/bin/pip install -r requirements.txt
DISCORD_TOKEN="xxx"
CHANNEL_ID="1234567890"
CODEX_FULL_ACCESS="1"
.venv/bin/python3 bridge.py
LaunchAgent (CLI)
Legacy rollback example:
com.claude.discord-bridge.plist.example(legacy)
Use the active CLI bridge example:
com.cli.discord-bridge.plist.example
Install example:
cp com.cli.discord-bridge.plist.example ~/Library/LaunchAgents/com.cli.discord-bridge.plist
# edit token/channel/paths
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.cli.discord-bridge.plist
Stop:
launchctl bootout gui/$(id -u)/com.cli.discord-bridge
Logs:
tail -f ~/.cli-discord-bridge/bridge.log
tail -f ~/.cli-discord-bridge/bridge.err.log
Gray Release and Rollback
Recommended migration sequence:
- Start
com.cli.discord-bridgein a new Discord channel. - Keep the legacy rollback service running in parallel for observation.
- Observe 24h for stuck process, leaks, thread loss, and command compatibility.
- Switch OpenClaw DR entry to the new CLI bridge channel.
- If needed, rollback by stopping
com.cli.discord-bridgeand continuing with legacy service.
Notes
- This project does not implement dynamic multi-vendor switching in one process.
- If you need more HA lanes, copy service instances with different
CHANNEL_IDand state dirs.