| name | codex-lb-load-balancer |
| description | ChatGPT/Codex multi-account load balancer with usage tracking, API key management, and OpenAI-compatible proxy |
| triggers | ["set up codex load balancer for multiple accounts","configure chatgpt account pooling","track openai api usage across accounts","manage api keys with rate limits","deploy codex-lb with docker","balance load across multiple chatgpt accounts","set up openai compatible proxy","monitor chatgpt usage and costs"] |
codex-lb Load Balancer
Skill by ara.so — Codex Skills collection.
Overview
codex-lb is a load balancer and proxy for ChatGPT/Codex accounts that pools multiple OpenAI accounts, tracks usage per account and API key, enforces rate limits, and provides a web dashboard for management. It exposes OpenAI-compatible endpoints (/v1/* and /backend-api/codex/*) for any client (Codex CLI, OpenCode, OpenClaw, OpenAI SDK).
Key features:
- Pool multiple ChatGPT accounts with automatic load balancing
- Per-account usage tracking (tokens, cost, 28-day trends)
- API key management with per-key rate limits (token, cost, time window, model)
- Dashboard with password + optional TOTP authentication
- Auto-sync available models from upstream
- WebSocket support for native Codex streaming
Installation
Docker (Recommended)
docker volume create codex-lb-data
docker run -d --name codex-lb \
-p 2455:2455 -p 1455:1455 \
-v codex-lb-data:/var/lib/codex-lb \
ghcr.io/soju06/codex-lb:latest
uvx (Python)
uvx codex-lb
Dashboard: http://localhost:2455
Proxy endpoints:
- OpenAI v1:
http://localhost:2455/v1
- Codex backend:
http://localhost:2455/backend-api/codex
Health check: http://localhost:1455/health
Configuration
First-Run Setup (Remote Access)
When accessing the dashboard remotely for the first time, you need a bootstrap token to set the password.
Auto-generated token (default):
docker logs codex-lb
Open dashboard → enter token + new password → done.
Manual bootstrap token:
docker run -d --name codex-lb \
-e CODEX_LB_DASHBOARD_BOOTSTRAP_TOKEN=your-secret-token \
-p 2455:2455 -p 1455:1455 \
-v codex-lb-data:/var/lib/codex-lb \
ghcr.io/soju06/codex-lb:latest
Local access (localhost) bypasses bootstrap entirely.
Adding Accounts
- Open dashboard → Accounts → Add Account
- Paste OpenAI session token or login credentials
- Account syncs available models automatically
API Key Authentication
API key auth is disabled by default. Enable in Settings → API Key Auth when:
- Clients connect remotely
- Running in Docker/VM/container with non-local networking
When enabled, clients must pass a Bearer token:
Authorization: Bearer sk-clb-YOUR_KEY_HERE
Create API keys in dashboard → API Keys → Create Key.
Configure rate limits per key:
- Token limit (per window)
- Cost limit (USD, per window)
- Time window (e.g., 1 hour, 1 day)
- Allowed models
Environment Variables
| Variable | Default | Description |
|---|
CODEX_LB_DASHBOARD_BOOTSTRAP_TOKEN | auto-generated | Bootstrap token for first-run password setup |
CODEX_LB_UPSTREAM_STREAM_TRANSPORT | auto | auto, websocket, or http for Codex streaming |
CODEX_LB_UPSTREAM_WEBSOCKET_TRUST_ENV | false | Use environment proxies for WebSocket handshakes |
CODEX_LB_DATA_DIR | /var/lib/codex-lb | Data directory for SQLite DB and state |
Client Configuration
Codex CLI
~/.codex/config.toml:
model = "gpt-5.3-codex"
model_reasoning_effort = "xhigh"
model_provider = "codex-lb"
[model_providers.codex-lb]
name = "OpenAI"
base_url = "http://127.0.0.1:2455/backend-api/codex"
wire_api = "responses"
supports_websockets = true
requires_openai_auth = true
With API key auth:
[model_providers.codex-lb]
name = "OpenAI"
base_url = "http://127.0.0.1:2455/backend-api/codex"
wire_api = "responses"
env_key = "CODEX_LB_API_KEY"
supports_websockets = true
requires_openai_auth = true
export CODEX_LB_API_KEY="sk-clb-..."
codex
Enable native WebSocket streaming:
export CODEX_LB_UPSTREAM_STREAM_TRANSPORT=websocket
Verify WebSocket transport:
RUST_LOG=debug codex exec "Reply with OK only."
Healthy signals:
- CLI logs:
connecting to websocket, successfully connected to websocket
- codex-lb logs:
WebSocket /backend-api/codex/responses
- No fallback
POST /backend-api/codex/responses
Migrate existing sessions from OpenAI provider:
find ~/.codex/sessions -name '*.jsonl' \
-exec sed -i '' 's/"model_provider":"openai"/"model_provider":"codex-lb"/g' {} +
sqlite3 ~/.codex/state_5.sqlite \
"UPDATE threads SET model_provider = 'codex-lb' WHERE model_provider = 'openai';"
OpenCode
Important: Use the built-in openai provider with baseURL override. Custom providers with @ai-sdk/openai-compatible drop reasoning content.
Clear existing OpenAI credentials:
jq 'del(.openai)' ~/.local/share/opencode/auth.json > auth.json.tmp && mv auth.json.tmp ~/.local/share/opencode/auth.json
~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"options": {
"baseURL": "http://127.0.0.1:2455/v1",
"apiKey": "{env:CODEX_LB_API_KEY}"
},
"models": {
"gpt-5.4": {
"name": "GPT-5.4",
"reasoning": true,
"options": { "reasoningEffort": "high", "reasoningSummary": "detailed" },
"limit": { "context": 1050000, "output": 128000 }
},
"gpt-5.3-codex": {
"name": "GPT-5.3 Codex",
"reasoning": true,
"options": { "reasoningEffort": "high", "reasoningSummary": "detailed" },
"limit": { "context": 272000, "output": 65536 }
}
}
}
},
"model": "openai/gpt-5.3-codex"
}
export CODEX_LB_API_KEY="sk-clb-..."
opencode
OpenClaw
~/.openclaw/openclaw.json:
{
"agents": {
"defaults": {
"model": { "primary": "codex-lb/gpt-5.4" },
"models": {
"codex-lb/gpt-5.4": { "params": { "cacheRetention": "short" } },
"codex-lb/gpt-5.3-codex": { "params": { "cacheRetention": "short" } }
}
}
},
"models": {
"mode": "merge",
"providers": {
"codex-lb": {
"baseUrl": "http://127.0.0.1:2455/v1",
"apiKey": "${CODEX_LB_API_KEY}",
"api": "openai-responses",
"models": [
{
"id": "gpt-5.4",
"name": "gpt-5.4 (codex-lb)",
"contextWindow": 1050000,
"contextTokens": 272000,
"maxTokens": 4096,
"input": ["text"],
"reasoning": false
},
{
"id": "gpt-5.3-codex",
"name": "gpt-5.3-codex (codex-lb)",
"contextWindow": 400000,
"contextTokens": 272000,
"maxTokens": 4096,
"input": ["text"],
"reasoning": false
}
]
}
}
}
}
export CODEX_LB_API_KEY="sk-clb-..."
OpenAI Python SDK
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:2455/v1",
api_key=os.environ["CODEX_LB_API_KEY"],
)
response = client.chat.completions.create(
model="gpt-5.3-codex",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)
Any OpenAI-Compatible Client
Point the base URL to:
- Chat Completions API:
http://127.0.0.1:2455/v1
- Codex Backend API:
http://127.0.0.1:2455/backend-api/codex
Pass API key as Authorization: Bearer sk-clb-... header if auth is enabled.
Usage Patterns
Multi-Account Load Balancing
codex-lb automatically distributes requests across healthy accounts based on:
- Account availability
- Usage limits
- Model availability per account
Add accounts in dashboard → Accounts → Add Account. Disable individual accounts temporarily without removing them.
Rate Limiting
Configure per-API-key limits in dashboard → API Keys → Edit Key:
Token limit:
Max tokens: 100000
Window: 1 hour
Cost limit:
Max cost: 5.00 USD
Window: 1 day
Model restrictions:
Allowed models: gpt-5.3-codex, gpt-5.4-mini
Usage Tracking
Dashboard → Accounts shows per-account:
- Total tokens used
- Total cost (USD)
- 28-day usage trends
- Model availability
Dashboard → API Keys shows per-key:
- Requests made
- Tokens consumed
- Cost incurred
- Rate limit status
WebSocket Streaming (Codex)
codex-lb supports native WebSocket streaming for Codex CLI:
Auto mode (default):
Force WebSocket:
export CODEX_LB_UPSTREAM_STREAM_TRANSPORT=websocket
Force HTTP:
export CODEX_LB_UPSTREAM_STREAM_TRANSPORT=http
Reverse proxy setup — ensure your reverse proxy forwards WebSocket upgrades:
nginx:
location / {
proxy_pass http://codex-lb:2455;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Caddy:
reverse_proxy localhost:2455
(Caddy handles WebSockets automatically)
Troubleshooting
Bootstrap token not working
API key rejected
- Auth disabled: Set
Authorization: Bearer dummy or any non-empty string. If remote request is rejected, enable API key auth in dashboard.
- Auth enabled: Create API key in dashboard → API Keys. Pass as
Authorization: Bearer sk-clb-....
- Rate limit: Check dashboard → API Keys for limit status. Increase limits or wait for window reset.
WebSocket connection fails (Codex)
- Verify transport: Run
RUST_LOG=debug codex exec "test" and check logs for connecting to websocket.
- Reverse proxy: Ensure proxy forwards WebSocket upgrades (see nginx/Caddy examples above).
- Direct connection: Set
CODEX_LB_UPSTREAM_WEBSOCKET_TRUST_ENV=false to bypass environment proxies.
- Fallback to HTTP: codex-lb automatically falls back. Check logs for
POST /backend-api/codex/responses instead of WebSocket.
Account sync fails
Usage not tracking
Codex sessions not appearing after migration
Run migration commands to update model_provider in session files and SQLite DB:
find ~/.codex/sessions -name '*.jsonl' \
-exec sed -i '' 's/"model_provider":"openai"/"model_provider":"codex-lb"/g' {} +
sqlite3 ~/.codex/state_5.sqlite \
"UPDATE threads SET model_provider = 'codex-lb' WHERE model_provider = 'openai';"
Dashboard won't load
High latency or timeout
- Add more accounts: Distribute load across more ChatGPT accounts.
- Check account health: Dashboard → Accounts → disable slow or failing accounts.
- Increase timeout: Configure client timeout (e.g., OpenAI SDK
timeout=120).
Advanced Configuration
Multi-Replica Setup
For high availability, run multiple codex-lb replicas sharing the same encryption key:
SHARED_KEY=$(openssl rand -hex 32)
docker run -d --name codex-lb-1 \
-e CODEX_LB_ENCRYPTION_KEY=$SHARED_KEY \
-p 2455:2455 -p 1455:1455 \
-v codex-lb-data:/var/lib/codex-lb \
ghcr.io/soju06/codex-lb:latest
docker run -d --name codex-lb-2 \
-e CODEX_LB_ENCRYPTION_KEY=$SHARED_KEY \
-p 2456:2455 -p 1456:1455 \
-v codex-lb-data:/var/lib/codex-lb \
ghcr.io/soju06/codex-lb:latest
Put replicas behind a load balancer (nginx, HAProxy, etc.).
Custom Data Directory
docker run -d --name codex-lb \
-e CODEX_LB_DATA_DIR=/custom/path \
-v /host/custom/path:/custom/path \
-p 2455:2455 -p 1455:1455 \
ghcr.io/soju06/codex-lb:latest
Kubernetes/Helm
See project repository for Helm chart. Key points:
- Share encryption key across pods via Secret
- Use PersistentVolumeClaim for SQLite database
- Configure Ingress for WebSocket support
Common Patterns
Development Team Usage
Each developer gets an API key with daily cost limit:
client = OpenAI(
base_url="https://codex-lb.company.com/v1",
api_key=os.environ["DEV_A_API_KEY"],
)
client = OpenAI(
base_url="https://codex-lb.company.com/v1",
api_key=os.environ["DEV_B_API_KEY"],
)
Monitor usage in dashboard → API Keys.
CI/CD Integration
Separate API key for CI with token limit:
- name: Run AI tests
env:
CODEX_LB_API_KEY: ${{ secrets.CI_CODEX_KEY }}
run: |
pytest tests/ai/
Model-Specific Routing
Restrict expensive models to specific keys:
Production key: gpt-5.4, gpt-5.3-codex allowed, $50/day
Development key: gpt-5.4-mini, gpt-5.1-codex-mini allowed, $10/day
Configure in dashboard → API Keys → Allowed Models.
This skill enables AI coding agents to help developers deploy, configure, and troubleshoot codex-lb for managing multiple ChatGPT/Codex accounts with load balancing, usage tracking, and rate limiting.