A zero-dependency local proxy that lets Codex CLI talk to
DeepSeek, Xiaomi MiMo, and OpenAI through a single
base_url.
English · 简体中文 · 日本語 · 한국어 · Español
Codex CLI speaks the OpenAI Responses API. DeepSeek and MiMo speak Chat Completions. codex-bridge translates between them in both directions — streaming SSE, tool calls, and thinking-mode round-trips — so you can use any supported model inside Codex without patching the client.
- Multi-provider routing — DeepSeek / MiMo / OpenAI, auto-selected by model name
- Bi-directional protocol translation — Responses API ↔ Chat Completions with streaming SSE bridge
- Per-provider reasoning effort translation — Codex's
none | minimal | low | medium | high | xhighmapped to each upstream's native format - Thinking-mode tool-call round-trip — caches
reasoning_contentand replays it so DeepSeek's thinking mode survives multi-turn tool calls - Inbound auth gate —
PROXY_AUTH_KEY/PROXY_KEYSwith optional per-key provider locking - Session continuity —
previous_response_idworks across providers (LRU-bounded store) - Built-in
web_fetchtool — bypasses sandbox restrictions for URL-heavy conversations - Tool-call circuit breaker — soft warning + hard tool stripping on runaway tool loops
- Single-file, zero dependencies — one
proxy.mjs(~2000 lines), nonpm install
git clone https://github.com/wujfeng712-ui/codex-bridge.git
cd codex-bridge
cp env.example .envEdit .env — at minimum:
PROXY_AUTH_KEY=sk-proxy-local-$(openssl rand -hex 24) # generate one
DEEPSEEK_API_KEY=sk-... # from platform.deepseek.comnode --env-file=.env proxy.mjsNeed Node 18–19 or background mode? See Advanced Usage.
Edit ~/.codex/config.toml:
model = "deepseek-v4-flash"
model_provider = "local_proxy"
[model_providers.local_proxy]
name = "local_proxy"
base_url = "http://127.0.0.1:4000/v1"
wire_api = "responses"
requires_openai_auth = trueSet the auth key for Codex:
# ~/.codex/auth.json
{ "OPENAI_API_KEY": "<same PROXY_AUTH_KEY from .env>" }Using CC Switch? Skip the manual edit — add a provider in the GUI instead. See Using with CC Switch.
Run codex — done.
┌─────────────┐ Responses API ┌──────────────┐
│ Codex CLI │────────────────────▶│ codex-bridge │
│ │ Authorization: │ :4000 │
└─────────────┘ Bearer <key> └──────┬───────┘
│ model-based routing
┌───────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌──────────────┐
│ DeepSeek V4 │ │ Xiaomi MiMo │ │ OpenAI │
│ Chat Complet. │ │ Chat Complet. │ │ Responses │
└────────────────┘ └────────────────┘ └──────────────┘
All settings via environment variables (see env.example for full documentation):
| Variable | Default | Description |
|---|---|---|
PROXY_AUTH_KEY |
— | Single inbound key (no provider lock) |
PROXY_KEYS |
— | Multi-key table: <key>:<provider>,... where provider ∈ deepseek/mimo/openai/* |
Both empty = auth disabled (not recommended).
| Variable | Default | Description |
|---|---|---|
DEEPSEEK_API_KEY |
— | DeepSeek upstream key |
DEEPSEEK_BASE_URL |
https://api.deepseek.com/v1 |
DeepSeek base URL |
DEEPSEEK_MODELS |
deepseek-v4-pro,deepseek-v4-flash |
Models to advertise |
MIMO_API_KEY |
— | Xiaomi MiMo upstream key |
MIMO_BASE_URL |
https://token-plan-cn.xiaomimimo.com/v1 |
MiMo base URL |
MIMO_MODELS |
mimo-v2.5-pro |
Models to advertise (must be lowercase) |
OPENAI_API_KEY |
— | OpenAI upstream key (opt-in) |
OPENAI_BASE_URL |
https://api.openai.com/v1 |
OpenAI base URL |
OPENAI_MODELS |
— | Explicit OpenAI model list |
OPENAI_MODEL_PREFIXES |
gpt-,o1,o3,o4,codex-,chatgpt- |
Heuristic routing prefixes |
| Variable | Default | Description |
|---|---|---|
MODEL_CATALOG_PATH |
— | Path to a proxy-models.json file. Overrides *_MODELS vars. Same file Codex reads via model_catalog_json |
| Variable | Default | Description |
|---|---|---|
PROXY_PORT |
4000 |
Listen port |
DEFAULT_PROVIDER |
auto | Fallback when model is unknown |
LOG_LEVEL |
info |
silent / error / warn / info / debug |
ACCESS_LOG |
on | Set 0 to suppress per-request access logs |
UPSTREAM_TIMEOUT_MS |
120000 |
Upstream request timeout |
STORE_TTL_MS |
3600000 |
Response store entry TTL |
STORE_MAX |
500 |
Response store LRU capacity |
GITHUB_TOKEN |
— | Optional; falls back to gh auth token lazily |
Each request is routed by model name, in priority order:
- Exact match — model appears in
DEEPSEEK_MODELS,MIMO_MODELS, orOPENAI_MODELS - Prefix heuristic — model starts with an
OPENAI_MODEL_PREFIXESentry → OpenAI - Name hint — model contains
deepseekormimo→ corresponding provider - Fallback —
DEFAULT_PROVIDER, then first provider with a configured key
Codex sends none | minimal | low | medium | high | xhigh. Each upstream accepts a different subset:
| Codex effort | DeepSeek | MiMo | OpenAI |
|---|---|---|---|
none |
thinking: {type: "disabled"} |
thinking: {type: "disabled"} |
field removed |
minimal |
reasoning_effort: "low" |
reasoning_effort: "low" |
passthrough |
low / medium / high |
passthrough | passthrough | passthrough |
xhigh |
reasoning_effort: "xhigh" |
clamped to high |
clamped to high |
Note: DeepSeek silently ignores
enable_thinking: false. The proxy usesthinking: {type: "disabled"}instead.
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/health |
No | Health check |
GET |
/v1/models |
Yes | Merged model list |
POST |
/v1/responses |
Yes | Codex CLI main endpoint (Responses API) |
POST |
/v1/chat/completions |
Yes | Direct Chat Completions passthrough |
GET |
/cop?url=... |
Yes | URL fetch (Jina Reader / native HTTP) |
POST |
/cop |
Yes | URL fetch with custom method/headers/body |
./scripts/smoke.sh # uses localhost:4000 by default
./scripts/smoke.sh http://host:4000 # custom target
MODEL=mimo-v2.5-pro ./scripts/smoke.sh # test a different modelRuns 30 checks covering endpoints, input shapes, auth gate, streaming completion, effort translation, tool-call round-trips, and provider locking.
CC Switch is a popular desktop app for managing provider profiles across AI CLI tools (Claude Code, Codex, Gemini CLI, etc.). You can use it to switch between codex-bridge and other providers with one click.
-
Open CC Switch → Codex tab → Add Provider
-
Fill in the provider fields:
Field Value Name codex-bridge(or any label you prefer)API Key Your PROXY_AUTH_KEYfrom.envBase URL http://127.0.0.1:4000/v1 -
Click Enable to activate — CC Switch writes the key to
~/.codex/auth.jsonand updatesconfig.tomlautomatically.
If you have multiple upstream keys (e.g., one for DeepSeek, one for MiMo), use PROXY_KEYS in .env to create per-provider inbound keys:
PROXY_KEYS=sk-deepseek-aaa:deepseek,sk-mimo-bbb:mimo,sk-all-ccc:*Then create a separate CC Switch profile for each key — switching profiles swaps which upstream provider codex-bridge routes to.
If you prefer the terminal, cc-switch-cli provides the same profile switching without a GUI:
# List profiles
cc-switch list
# Switch to the codex-bridge profile
cc-switch use codex-bridgeTip: After switching profiles, restart your terminal (or run
codexin a new shell) for the new auth to take effect.
- Node 18–19 startup —
--env-filewas added in Node 20. On older versions:set -a && source .env && set +a && node proxy.mjs
- Background mode:
nohup node --env-file=.env proxy.mjs > /tmp/codex-bridge.log 2>&1 &
- Multi-key provider locking — assign each inbound key to a specific provider for multi-profile setups. See
env.examplefor thePROXY_KEYSformat. - Model catalog single source of truth — point
MODEL_CATALOG_PATHat the same JSON file Codex uses (model_catalog_jsoninconfig.toml) to keep model lists in sync automatically.
| Symptom | Cause | Fix |
|---|---|---|
EADDRINUSE :4000 |
Port already in use | lsof -ti:4000 | xargs kill or change PROXY_PORT in .env |
401 Unauthorized |
Auth key mismatch | Ensure OPENAI_API_KEY in ~/.codex/auth.json matches PROXY_AUTH_KEY in .env |
--env-file: not recognized |
Node.js < 20 | Use set -a && source .env && set +a && node proxy.mjs |
| Upstream timeout | Slow provider response | Increase UPSTREAM_TIMEOUT_MS in .env (default 120 000 ms) |
| Model not found | Model not in any *_MODELS list |
Add it to DEEPSEEK_MODELS / MIMO_MODELS / OPENAI_MODELS, or use MODEL_CATALOG_PATH |
- Node.js 18+
- macOS / Linux / Windows
- At least one upstream API key (DeepSeek, MiMo, or OpenAI)
MIT — see LICENSE.