Skip to content

PLASMA-FR/ccbridge

Claude x Codex Local OAuth Bridge

Local dashboard, account manager, and Anthropic-compatible proxy for routing Claude Code through one of multiple OpenAI Codex OAuth accounts.

The project is built for a very specific workflow: keep several Codex accounts on one machine, isolate each account's auth state, switch the active route without touching Claude manually, and expose a local bridge that Claude Code can talk to as if it were an Anthropic-compatible backend.

What It Does

  • Runs a local dashboard on http://127.0.0.1:9000
  • Launches the real codex login browser OAuth flow per account
  • Stores each account in its own isolated CODEX_HOME
  • Lets you choose an active account and a default account
  • Persists model selection per account
  • Supports global fast mode and per-account fast mode overrides
  • Shows live account state, recent events, and real-time rate-limit telemetry
  • Generates and optionally writes Claude Code settings for the local bridge
  • Exposes Anthropic-compatible /v1/models, /v1/messages, and /v1/messages/count_tokens
  • Supports foreground runs, background service control, and optional systemd --user install

Why This Exists

Codex OAuth is tied to local CLI state, which makes multi-account usage awkward. This app makes that state explicit and manageable:

  • each account gets its own auth directory
  • switching accounts becomes a UI action instead of shell surgery
  • Claude Code integration is generated from the currently active account
  • live limits are surfaced in the dashboard so you can see when a route is nearly exhausted

Feature Summary

Area Details
Account management Add, rename, enable, disable, delete, activate, and mark default accounts
OAuth flow Uses the installed codex CLI instead of reimplementing login
Model routing Persists preferred model per account and exposes available models to the dashboard
Fast mode Global default plus per-account override
Limits Displays account limit summaries and app-server rate-limit windows, including reset times and stale-data warnings
Claude integration Builds ANTHROPIC_* and related environment variables and can write them to Claude settings
Proxy Anthropic-compatible message endpoints backed by the active Codex account
Operations Health endpoint, logs, service commands, optional systemd user unit

Architecture

Claude Code
  -> local Anthropic-compatible bridge (/anthropic/v1/*)
  -> active Codex account selected in app state
  -> Codex provider adapter
  -> local codex CLI / app-server / OAuth files

Dashboard UI
  -> Fastify API (/api/*)
  -> state store + event log + login session manager + Claude settings service

Main areas:

src/client/                     React dashboard
src/server/                     Fastify backend and bridge entrypoints
src/server/providers/codex/     Codex provider adapter and Anthropic protocol bridge
src/server/services/            Login session management and Claude settings integration
src/server/store/               State and event persistence
src/shared/                     Shared types and validation
scripts/                        Setup, smoke test, and systemd helper scripts
.local-data/                    Runtime state, account homes, logs, PID files

Requirements

  • Node.js 20+
  • npm
  • codex CLI available on PATH
  • claude CLI is optional for running the bridge itself, but expected if you want to wire Claude Code to it

Quick Start

  1. Clone the repository.
  2. Copy the example environment file.
  3. Install dependencies.
  4. Build the app.
  5. Start the service.
  6. Open the dashboard and connect accounts.
cp .env.example .env
npm install
npm run build
npm run service:start

Open http://127.0.0.1:9000.

One-Command Setup

If you just want the app built and started with one command:

npm run setup:start

That script installs dependencies if needed, builds the production bundle, starts the background service, and prints current status.

Dashboard Workflow

  1. Open the dashboard.
  2. Add an account from the Accounts section.
  3. Click Connect to start the real Codex OAuth browser flow.
  4. Finish authentication in the browser window opened by codex login.
  5. Wait for the login session to report success in the UI.
  6. Choose the active account.
  7. Pick a model for that account.
  8. Decide whether fast mode should be global or account-specific.
  9. Review the generated Claude integration block.
  10. Apply the generated settings to Claude if desired.

Live Limits

The dashboard exposes two kinds of limit information:

  • Account-level limit metadata derived from the auth payload when available
  • Real-time rate-limit windows fetched from the Codex app-server

The rate-limit panel is designed to show the full remaining capacity for the current account, including:

  • 5-hour windows
  • weekly windows
  • per-limit buckets such as model- or tier-specific quotas
  • reset timestamps
  • warnings when the app-server data may be stale

If the live meter is marked stale or unavailable, the account can still exist and be connected; it only means the separate rate-limit snapshot could not be refreshed at that moment.

Development

Run the client and server in development mode:

npm run dev

Default dev ports:

  • Vite frontend: 127.0.0.1:5173
  • Fastify backend: 127.0.0.1:9000

Production

Build the project:

npm run build

Run in the foreground:

npm start

Run as the managed background service:

npm run service:start
npm run service:status
npm run service:restart
npm run service:stop

Service logs are written to:

.local-data/runtime/service.log

Global CLI

After building, you can install the bundled CLI globally using either symlink or package install.

Symlinked install:

npm install
npm run build
npm link

Global package install:

npm install
npm run build
npm install -g .

This installs:

  • ccbridge
  • claude-codex-bridge

Examples:

ccbridge start
ccbridge status
ccbridge health
ccbridge logs
ccbridge restart
ccbridge stop

Notes:

  • The global CLI uses the installed package directory as the app root.
  • The default global data directory is ~/.local/share/claude-codex-oauth-bridge.
  • You can override persistence with DATA_DIR=/custom/path.
  • npm install -g by itself is not enough; use npm install -g . from this repository.

Scripts

Command Purpose
npm run dev Start Vite and the Fastify server in development mode
npm run build Clean dist/, compile the server, and build the client
npm start Run the built production server
npm test Run the smoke suite
npm run test:smoke Execute the end-to-end smoke checks
npm run ci Run the build and smoke suite together
npm run setup:start Install if needed, build, and start the managed service
npm run service:start Start the background service
npm run service:status Print service status
npm run service:restart Restart the background service
npm run service:stop Stop the background service
npm run systemd:install Install a systemd --user unit
npm run systemd:uninstall Remove the systemd --user unit
npm run global:install Install the package globally
npm run global:link Link the package globally for local development

API Surface

The server exposes two public groups of routes: dashboard API routes and Anthropic-compatible bridge routes.

Core Health

Method Route Purpose
GET /health Lightweight runtime health summary

Dashboard API

Method Route Purpose
GET /api/state Full dashboard state, including service info, accounts, models, integration preview, and recent events
GET /api/logs?limit=120 Recent event log entries
POST /api/accounts Create an account
PATCH /api/accounts/:accountId Rename, enable/disable, change model, or update fast mode override
DELETE /api/accounts/:accountId Delete an account and its isolated auth directory
POST /api/accounts/:accountId/activate Set the active account
POST /api/accounts/:accountId/default Set the default account
POST /api/accounts/:accountId/connect Start a Codex OAuth browser-login session
POST /api/accounts/:accountId/test Test upstream connectivity for one account
GET /api/login-sessions/:sessionId Poll a login session
DELETE /api/login-sessions/:sessionId Cancel a login session
PATCH /api/settings Update global fast mode, port fallback, and CORS settings
PATCH /api/integration Update Claude settings path and auto-apply behavior
POST /api/integration/apply Write generated environment variables into Claude settings
POST /api/integration/test Test the active account through the integration layer

Anthropic-Compatible Bridge

These routes require the locally generated auth token from the integration preview. The token can be sent as either:

  • Authorization: Bearer <token>
  • x-api-key: <token>

Routes:

Method Route Purpose
GET /anthropic/v1/models List models known to the active Codex account
POST /anthropic/v1/messages/count_tokens Return an input token estimate for a request body
POST /anthropic/v1/messages Execute a completion or stream events using Anthropic-style message semantics

Base URL for Claude Code:

http://127.0.0.1:9000/anthropic

Claude Code Integration

The dashboard generates and can write the following environment variables into your Claude settings file:

  • ANTHROPIC_BASE_URL
  • ANTHROPIC_AUTH_TOKEN
  • ANTHROPIC_MODEL
  • ANTHROPIC_DEFAULT_OPUS_MODEL
  • ANTHROPIC_DEFAULT_SONNET_MODEL
  • ANTHROPIC_DEFAULT_HAIKU_MODEL
  • CLAUDE_CODE_SUBAGENT_MODEL
  • ENABLE_EXPERIMENTAL_MCP_CLI

Default Claude settings path:

~/.claude/settings.json

You can override it with CLAUDE_SETTINGS_PATH in .env or from the dashboard.

Environment Configuration

Example .env:

PORT=9000
HOST=127.0.0.1
ALLOW_PORT_FALLBACK=false
DATA_DIR=.local-data
CLAUDE_SETTINGS_PATH=
AUTO_APPLY_CLAUDE_SETTINGS=true
CORS_ORIGIN=
SERVICE_LOG_LEVEL=info
Variable Default Meaning
PORT 9000 Server port
HOST 127.0.0.1 Bind address
ALLOW_PORT_FALLBACK false Fail if the configured port is busy instead of silently switching
DATA_DIR .local-data Persistent app state, event logs, PID files, and account homes
CLAUDE_SETTINGS_PATH empty Override the Claude settings file path
AUTO_APPLY_CLAUDE_SETTINGS true Auto-write integration settings when state changes
CORS_ORIGIN empty Optional explicit local origin for browser access
SERVICE_LOG_LEVEL info Service logging verbosity

Behavior notes:

  • ALLOW_PORT_FALLBACK=true allows the service to move to the next free port on startup.
  • CORS_ORIGIN is intentionally blank by default for local-only usage.
  • Changes to startup behavior apply on the next process start, not retroactively to a running service.

Persistence and Data Layout

State that survives restarts:

  • account registry
  • active/default account selection
  • per-account model preference
  • fast mode settings
  • Claude integration settings
  • recent runtime metadata and events

Per-account Codex auth state is isolated under:

.local-data/accounts/<account-id>/codex-home/

That separation matters because the Codex CLI keeps auth and refresh state on disk. Without isolated homes, one account can overwrite another.

Verification

Run the production build and smoke suite:

npm run build
npm run test:smoke

The smoke test covers:

  • account persistence and active/default behavior
  • integration preview and Claude settings application
  • event log read/write flow
  • auth status detection from isolated Codex account homes
  • request shaping for the Codex bridge
  • non-retryable upstream error mapping
  • client API request header behavior
  • browser-auth flow wiring

For the same sequence used in CI:

npm run ci

The package also builds cleanly for distribution because dist/ is cleared before each build and prepack rebuilds automatically.

Systemd User Service

Install a managed systemd --user service:

npm run systemd:install

Remove it:

npm run systemd:uninstall

Notes:

  • The installer builds the app before writing the unit file.
  • The service is configured to restart on failure.
  • The unit binds to 127.0.0.1 by default.
  • For boot-time startup before interactive login, your Linux machine may need:
sudo loginctl enable-linger "$USER"

Health and Monitoring

Basic health check:

curl http://127.0.0.1:9000/health

The dashboard also shows:

  • current active account and model
  • integration preview state
  • effective fast mode
  • auth freshness
  • recent proxy, OAuth, integration, and system events
  • live limits and stale-limit warnings

Troubleshooting

Port 9000 Is Busy

  • Leave ALLOW_PORT_FALLBACK=false if you want startup to fail loudly.
  • Set ALLOW_PORT_FALLBACK=true if you prefer the service to choose the next open port.
  • If the port changes, regenerate or reapply Claude settings so the ANTHROPIC_BASE_URL matches.

OAuth Login Succeeds in Browser but the Account Still Looks Disconnected

  • Make sure the codex CLI is installed and callable from the same environment that launched the server.
  • Poll the login session until it reaches a terminal state.
  • Review the recent event log for oauth and system entries.
  • Check the account's isolated CODEX_HOME under .local-data/accounts/<account-id>/codex-home/.

Limits Show as Stale or Unavailable

  • The account can still be connected even when the rate-limit snapshot is stale.
  • A stale warning usually means the auxiliary app-server rate-limit request did not return fresh data.
  • Refresh the dashboard or retry the account status/test path after a short delay.

Claude Code Is Still Talking to the Wrong Backend

  • Reapply the integration settings from the dashboard.
  • Confirm that ANTHROPIC_BASE_URL points to this bridge and not another local proxy.
  • Confirm that the auth token in Claude settings matches the current integration preview.

Security Assumptions and Limitations

  • The service is local-only by default and binds to 127.0.0.1.
  • The Anthropic-compatible bridge is protected by a locally generated bearer token.
  • Codex OAuth state is file-based because the upstream CLI expects local auth files.
  • Account auth/config files are written with restricted permissions where possible.
  • There is no built-in TLS termination.
  • This should not be exposed directly to remote networks without a reverse proxy, TLS, and stronger auth.
  • CORS is disabled by default and should only be enabled intentionally for a known local origin.

Implementation Notes

  • Backend: Fastify
  • Frontend: React + Vite
  • Validation: Zod
  • Persistence: JSON and JSONL with atomic writes
  • OAuth: delegated to the real codex login browser flow
  • Token refresh and rate-limit queries: delegated to Codex CLI tooling against the account-specific CODEX_HOME
  • Extensibility: provider-specific logic lives under src/server/providers/

Repository Docs

License

This repository is currently UNLICENSED. No reuse rights are granted unless the owner adds a different license later.

About

Local dashboard and Anthropic-compatible bridge for routing Claude Code through multiple OpenAI Codex OAuth accounts.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors