Local OpenAI-compatible proxy for Codex/ChatGPT OAuth with a built-in dashboard, multi-account pool management, public access tunneling, request audit, and an Electron desktop shell.
This project now defaults to AUTH_MODE=codex-oauth, so the built-in dashboard can drive ChatGPT/Codex OAuth directly without an external auth bootstrap.
The dashboard and ops workflow take inspiration from:
- OpenAI-compatible proxy endpoints for
Codex/ChatGPT,Gemini, andAnthropic - Built-in dashboard for auth, config, runtime health, pool operations, and request inspection
- Multi-account Codex OAuth pool with usage probes and account switching
Account Auto RMbackground cleanup for invalidated or probe-failed accounts- Request audit with recent request history and detail modal
- Desktop Electron app with embedded backend and per-user writable data paths
- Bundled
cloudflaredbinaries for packaged desktop builds - Windows NSIS installer with standard uninstall support
Runtime:
- Node.js 20+
- npm
Build:
- Windows host for
.exeinstaller output - macOS host for
.dmg - Linux host or compatible AppImage toolchain for final Linux package output
Install dependencies:
cd codex-pro-max
npm installCreate local config:
cp .env.example .envStart the proxy server:
npm startOpen the dashboard:
http://127.0.0.1:8787/dashboard/
Minimal default setup:
AUTH_MODE=codex-oauth
UPSTREAM_MODE=codex-chatgpt
UPSTREAM_BASE_URL=https://chatgpt.com/backend-api
CODEX_DEFAULT_MODEL=gpt-5.5
CODEX_DEFAULT_SERVICE_TIER=priority
CODEX_MULTI_ACCOUNT_ENABLED=true
CODEX_MULTI_ACCOUNT_STRATEGY=smart
CODEX_AUTO_LOGOUT_EXPIRED_ACCOUNTS=false
UPSTREAM_STREAM_IDLE_TIMEOUT_MS=900000Provider quick switch examples:
# Gemini
UPSTREAM_MODE=gemini-v1beta
GEMINI_API_KEY=
GEMINI_DEFAULT_MODEL=gemini-2.5-pro
# Anthropic
UPSTREAM_MODE=anthropic-v1
ANTHROPIC_API_KEY=
ANTHROPIC_DEFAULT_MODEL=claude-sonnet-4-20250514See .env.example for the current env surface.
UPSTREAM_STREAM_IDLE_TIMEOUT_MS controls how long the proxy will tolerate a silent upstream SSE stream before aborting it. The default is 900000 (15 minutes), which is safer for long-running gpt-5.5 xhigh or multi-step agent tasks than the previous 3-minute default.
The dashboard can:
- start OAuth login/logout and manage the active account
- import/export account tokens in bulk
- refresh usage and inspect the account pool
- autosave
Proxy Configinto.env - edit Model Router mappings
- preserve client-provided
service_tier, or inject the configured service tier when the client omits it - run upstream self-test
- run
Preheatmanually for the selected model or all supported Codex models - inspect recent proxy requests and clear request history
- configure and start public access through
cloudflared
Run the Electron shell in development:
npm run desktop:devThe desktop shell:
- starts the embedded backend automatically
- opens the dashboard inside Electron
- writes runtime state into Electron
userData - keeps writable data out of the install directory
Desktop-mode persistence:
- proxy config autosave ->
userData/.env - token stores / API keys / request history / preheat history ->
userData/data/ - cloudflared runtime downloads ->
userData/bin/ - bundled
cloudflared-> appextraResources/cloudflared/
Relevant files:
- electron/main.mjs
- electron/preload.mjs
- src/app-server.js
- src/server.js
Build packaged desktop resources first:
npm run build:desktop-resourcesThis builds:
- bundled
cloudflaredbinaries forwin32-x64,linux-x64,darwin-x64,darwin-arm64
Platform packaging commands:
npm run dist:win
npm run dist:mac
npm run dist:linuxArtifacts are written to dist-electron/.
If you want to remove only rebuildable desktop packaging output without touching runtime data in data/, run:
npm run clean:build-cache- packaging target: NSIS
- installer output:
dist-electron/codex-pro-max Setup <version>.exe - unpacked Windows validation build:
dist-electron/win-builds/<timestamp>/win-unpacked/ - standard uninstall entry is included
- uninstall keeps Electron
userDataby default - assisted uninstall now includes an optional checkbox to remove the current user's
AppData\Roaming\codex-pro-max
- current packaging target:
AppImage - if
electron-buildercannot finishAppImageon the current host,dist-electron/linux-unpacked/is still useful for validation - this project was validated on Kali using the unpacked Linux build plus bundled
cloudflared
If you copy linux-unpacked from Windows to Linux via scp or similar, executable bits may be lost. Reapply them before running:
chmod +x dist-electron/linux-unpacked/codex-pro-max
chmod +x dist-electron/linux-unpacked/chrome-sandbox
chmod +x dist-electron/linux-unpacked/chrome_crashpad_handler
chmod +x dist-electron/linux-unpacked/resources/cloudflared/linux-x64/cloudflared.dmgoutput must be built on macOS- the packaged resources already include both
darwin-x64anddarwin-arm64binaries forcloudflared
Base URL:
http://127.0.0.1:8787/v1
Supported proxy endpoints:
codex-chatgpt:/v1/models,/v1/responses,/v1/chat/completionsgemini-v1beta:/v1/chat/completions, native Gemini/v1beta/*anthropic-v1:/v1/chat/completions, native Anthropic/v1/messages
API key behavior:
- if no proxy API keys are configured, calls can be sent without a proxy API key
- after generating dashboard API keys, callers must send one of those keys
- Gemini/Anthropic can run in local facade mode with empty upstream provider keys
Example:
curl http://127.0.0.1:8787/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"gpt-5.5",
"messages":[{"role":"user","content":"say hello"}],
"stream": true
}'Model Router supports exact and wildcard mappings:
{
"gpt-5.5": "gemini-2.5-pro",
"gpt-4*": "gemini-2.5-flash",
"claude-*": "claude-sonnet-4-6"
}Priority:
- exact mapping first
- wildcard mapping second
- system fallback last
codex-oauth- built-in ChatGPT OAuth
- default mode
- callback listener:
http://localhost:1455/auth/callback
profile-store- reuses an existing
auth-profiles.json
- reuses an existing
custom-oauth- bring your own OAuth provider
- tool calling is supported
- multi-account follow-up requests are pinned by
previous_response_id - Codex-backed Responses continuations replay known local chains and reject missing chain IDs instead of silently starting a fresh turn
- vision inputs are translated to the correct provider-compatible payloads
- SSE responses are normalized into OpenAI-compatible stream shapes where needed
- recent requests are stored in memory immediately and persisted in debounced batches
Proxy Configautosave persists operational proxy settings into.env; request-level reasoning effort stays owned by the Codex client request, while missingservice_tieris filled from the dashboard setting- docs/openai-responses-v1-alignment-audit.md tracks the current OpenAI Responses v1 parity audit, official-vs-extension surface split, and known compatibility divergences
Run tests:
npm testRun the full release gate:
npm run release:gateUse that as the canonical pre-release validation command. It chains the repo's real validation entrypoints in one place:
npm run lintnpm run format:checknpm run typechecknpm run test:smokenpm test
Current validation focus includes:
- request body caching
- proxy audit serialization
- debounced recent-request persistence
- multi-account token import concurrency
- account auto-remove behavior
- desktop lifecycle boot/shutdown
Typical release sequence:
npm run release:gate
npm run dist:win
git add .
git commit -m "..."
git push origin master
gh release create <tag> <artifact...>If Linux/macOS release artifacts are needed, build them on matching hosts before publishing the release.