Drive the Codex CLI running on your own computer from your phone, from anywhere.
Phone (iPhone / Android Web App, or native iOS app)
│ WSS / HTTPS
▼
Cloud relay :8002 (FastAPI + SQLite + Redis — auth, routing, offline cache only)
▲ outbound-only WebSocket (your computer opens NO inbound ports)
│
Windows / macOS / Linux agent ──► codex CLI (any provider you are logged into)
└─► usage quota query (API keys stay on your machine, never sent to the relay)
- Zero inbound ports at home — the agent only makes outbound WebSocket connections to your relay.
- API keys never leave your machine — model keys and usage-query keys live only in the local
agent/.env. - The relay is a dumb pipe — authentication + routing + SQLite event persistence + Redis offline buffer. Single user, single agent.
- Cross-platform — agent runs on Windows / macOS / Linux; any phone browser works.
Note: the built-in Web App and iOS UI currently ship with Chinese labels. The protocol, API and docs are language-agnostic; i18n is on the roadmap. The interactive demo replay (screenshot below) is also in Chinese.
All three were captured from python scripts/webapp_demo.py — a fake-agent demo with zero real calls.
- Sessions — create / resume (auto-forks a thread when the desktop app holds the write lock) / stop / archive
- Live event stream — reasoning, command execution (status + output), file changes, answers, token usage
- Projects — auto-scans git projects under
PROJECT_ROOT; can resume sessions started in the desktop Codex app - Model switching — model / reasoning effort (low→max) / sandbox mode (read-only · confirm · auto · full access)
- Usage quota — pluggable quota query with three parsers (see below), keys stay local
- Offline buffer — commands sent while the agent is offline are queued in Redis and replayed on reconnect
- Three clients — responsive PWA (recommended), native SwiftUI iOS app (
ios/), desktop browser
| Component | Requirement |
|---|---|
| Relay | Any Linux server (Ubuntu/Debian/CentOS), 1 vCPU / 1 GB is enough, one open port (default 8002) |
| Agent | Windows 10+ / macOS / Linux, Python 3.10+, and the codex CLI installed and logged into your own model provider (codex --version must work) |
| iOS native app (optional) | Xcode 15+ on a Mac, or the included GitHub Actions workflow that builds an unsigned IPA in the cloud |
Third-party accounts you need: this project does not bundle any model access. You must install and log into the codex CLI with your own provider account/API key (OpenAI, MiniMax, or whatever your codex setup uses). The optional usage-quota widget needs your own provider API key (e.g. a MiniMax key, or any one-api/new-api gateway key). Nothing is proxied through the project's authors.
~15 minutes end to end. Full walkthrough (HTTPS, Docker, building the iOS app without a Mac): docs/deploy.md.
1. Get the code (on both machines):
git clone https://github.com/Clannadad/codex-bridge-oss.git
cd codex-bridge-oss2. Relay — on your Linux server:
cd relay
cp .env.example .env
# edit .env: set APP_TOKEN and AGENT_TOKEN, each "openssl rand -hex 32"
sudo bash ../scripts/install-relay.sh # venv + redis + systemd service
bash ../scripts/smoke_test.sh # optional 24-check channel self-test
curl http://127.0.0.1:8002/api/health # {"status":"ok",...}3. Agent — on your own computer:
cd agent
copy .env.example .env :: macOS/Linux: cp .env.example .env
:: edit .env: RELAY_URL=ws://<server>:8002/ws/agent, AGENT_TOKEN (same as relay), PROJECT_ROOT
install-agent.bat :: macOS/Linux: bash install-agent.shPrerequisite: codex --version works and codex is logged in (see Requirements).
4. Phone: on the server, install-relay.sh generated connect-web.png — scan it with the phone camera, the Web App opens pre-configured; "Add to Home Screen" makes it feel native.
Everything is configured through two .env files (copy from the committed .env.example files; real .env files are git-ignored).
| Variable | Required | Default | Purpose |
|---|---|---|---|
APP_TOKEN |
yes | — | Phone-side token. Generate: openssl rand -hex 32. Leaked? Change it and re-scan the QR. |
AGENT_TOKEN |
yes | — | Agent-side token, must match agent/.env. Generate the same way. |
DOMAIN |
no | localhost |
Your domain, if any (WebSocket auto-upgrades to wss://). |
PUBLIC_BASE |
no | http://$DOMAIN:8002 |
Base URL baked into QR codes; set https://your.domain behind Caddy. |
REDIS_URL |
no | redis://127.0.0.1:6379/1 |
Redis used for offline buffering. |
DB_PATH |
no | ./data/relay.db |
SQLite event store location. |
AGENT_OFFLINE_TIMEOUT_SEC |
no | 45 |
Agent declared offline after this long without a heartbeat. |
OFFLINE_MSG_BUFFER |
no | 100 |
Max commands buffered while the agent is offline. |
| Variable | Required | Default | Purpose |
|---|---|---|---|
RELAY_URL |
yes | — | e.g. ws://1.2.3.4:8002/ws/agent (or wss:// behind HTTPS). |
AGENT_TOKEN |
yes | — | Must equal relay's AGENT_TOKEN. |
PROJECT_ROOT |
no | home dir | Root the agent may operate on; the phone's project list scans it. Keep it tight. |
CODEX_PATH |
no | auto |
Path to the codex executable; auto detects codex/codex.cmd. |
CODEX_MODEL |
no | MiniMax-M3 |
Default model slug passed to codex. |
CODEX_BACKEND |
no | appserver |
appserver (shares the session store with the desktop Codex app) or exec (plain CLI fallback). |
CODEX_SANDBOX |
no | danger-full-access |
codex sandbox level. Understand what full access means before exposing PROJECT_ROOT to your phone. |
CODEX_MODEL_CATALOG |
no | ~/.codex/mmx-model-catalog.json |
JSON file feeding the model picker (`models[].slug |
MINIMAX_API_KEY |
no | — | MiniMax coding-plan quota key (only used locally for the usage widget). |
USAGE_API_URL |
no | MiniMax endpoint | Any quota endpoint returning JSON. |
USAGE_API_KEY |
no | falls back to MINIMAX_API_KEY |
Key for that endpoint. |
USAGE_PARSE |
no | minimax |
minimax (5h/week dual rings + per-model detail) · oneapi (one-api/new-api gateway quota) · raw (render raw JSON). |
USAGE_POLL_INTERVAL_SEC |
no | 300 |
Quota refresh interval. |
MAX_CONCURRENT_SESSIONS |
no | 4 |
Concurrent turn cap. |
HEARTBEAT_INTERVAL_SEC |
no | 15 |
Agent heartbeat period. |
pip install fakeredis # only extra needed for tests
python scripts/local_relay_test.py # spins a fakeredis relay + 24 end-to-end checks
python scripts/webapp_demo.py # zero-config Web App demo (fake agent, see screenshots)
cd relay && uvicorn app.main:app --port 8002 # foreground relay (needs redis)
python agent/agent.py # foreground agent (needs .env)Protocol internals: docs/protocol.md · HTTP API: docs/api.md · Deployment: docs/deploy.md
APP_TOKEN/AGENT_TOKENare remote-execution power over your machine. If leaked: change both inrelay/.env, restart, re-scan the QR..envfiles and the generated QR PNGs (they embed tokens) are git-ignored — never commit or share them.- Plain
http://ip:portdeployments send tokens in cleartext. For anything long-lived on the public internet, use the Caddy/HTTPS path (relay/Dockerfile,docker-compose.yml). CODEX_SANDBOX=danger-full-accessmeans codex can run arbitrary commands on the agent machine — that is the point of "remote control", but scopePROJECT_ROOTaccordingly.
Agent shows offline in the app.
Run it in the foreground first: python agent/agent.py. Common causes: wrong RELAY_URL scheme (ws:// vs wss://), AGENT_TOKEN mismatch, or a proxy on the agent machine intercepting WebSockets (the agent already forces proxy=None; if you still see handshake failures, check your proxy software's rules).
Relay health returns ok but the phone can't connect.
Cloud security group / firewall must allow your chosen port (default 8002). If you use a domain, verify PUBLIC_BASE matches the real reachable URL, then regenerate the QR codes (python scripts/gen_qr.py --env relay/.env).
install-agent.bat fails to create the service.
It needs an Administrator shell for the NSSM service path; without admin rights it falls back to a scheduled-task + startup-folder install, which is fine for normal use.
A session says it's "being used on the desktop". The desktop Codex app holds a write lock on loaded threads. Close that tab in the desktop app, or just continue on the phone — the appserver backend auto-forks the thread (context preserved) when the lock is held.
Commands silently stop after a while / turn never completes.
Check logs/agent.log under the agent data dir (Windows %LOCALAPPDATA%\CodexAgent, macOS ~/Library/Application Support/CodexAgent, Linux ~/.local/share/CodexAgent). An agent process killed without cleanup can leave an orphan app-server child holding locks — restart the agent or kill codex.exe leftovers.
Images in chat fail.
Depends on whether the model provider behind your codex CLI exposes a vision channel; failures surface as error events in the stream.
How do I install the iOS app without a Mac?
Push to your fork; the build-ios Actions workflow produces an unsigned IPA artifact (macOS runner). Sideload with Sideloadly and your own Apple ID (7-day re-sign with a free account), or open ios/CodexBridge in Xcode on a Mac.
Is my data sent anywhere besides my server? No. The relay is yours; the agent talks only to it. Usage/quota requests go directly from the agent machine to your provider, never through the relay.
Issues and PRs are welcome. Before submitting:
python scripts/local_relay_test.pymust pass (24 checks).- Keep the zero-third-party-dependency constraint of the Web App (single-file, no build step) and the iOS app.
- Describe the scenario you're fixing; English or Chinese both fine.
MIT © codex-bridge contributors


