The Problem

Developers using the Codex desktop client must switch between many external LLM providers (Anthropic, Kimi, DeepSeek, etc.). Each provider requires its own credential handling, service installation, and UI integration, leading to duplicated configuration, potential credential leakage, and a fragmented user experience.

What This Does

codex-router installs a single background service that acts as a credential‑isolated gateway for all supported providers. The router speaks the Codex Responses API, merges external models into Codex’s native catalog, and exposes a unified endpoint for the Gemini CLI and DeepSeek Harness.

Key files:

  • apps/desktop/src-tauri/src/main.rs – Rust entry point that launches the Tauri service.
  • apps/desktop/ui/app.js – Front‑end bootstrap that registers the router UI.
  • src/router.mjs – Core request dispatcher (35 outgoing imports, highest instability).
  • src/paths.mjs and src/file-security.mjs – Central path resolution and security checks; 75 and 39 modules depend on them respectively.

How It Is Wired

  1. Startup – The OS launches the Tauri binary (main.rs). It reads apps/desktop/src-tauri/tauri.conf.json and spawns the Node environment defined in apps/desktop/package.json.
  2. UI → Serviceui/app.js loads src/router.mjs which registers HTTP routes on the local gateway. Incoming calls from the Codex client hit src/router.mjs, which forwards them to provider‑specific adapters located under src/provider‑selection.
  3. Path & Security – Every request first passes through src/paths.mjs (path resolution) and src/file-security.mjs (credential sandboxing). Their high inbound fan‑in makes them the primary blast‑radius; changes here affect all 114 dependent modules.
  4. Provider Selectionsrc/provider-selection.mjs consults src/model-registry.mjs (26 inbound, 2 outbound) to map a logical model name to a concrete provider config (JSON files under config/*).
  5. Command Execution – Heavy decision logic lives in src/caller-auth.mjs (30 inbound, 0 outbound) and src/spawnable-command.mjs; both exhibit high branching density (≈28 branches/93 lines). They ultimately invoke the CLI wrappers in bin/ (e.g., bin/model-router, bin/doctor).
  6. Response – The router returns a Codex‑compatible JSON payload, which the desktop UI injects into the model picker.

No circular imports were detected; the most unstable modules (src/router.mjs, src/doctor.mjs) have only outgoing edges, limiting hidden side‑effects.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/codex-router
cd codex-router

# Install the desktop app (macOS/Linux)
npm ci                # installs Node deps from apps/desktop/package.json
cargo build --release # builds the Tauri binary (src-tauri)

# Guided setup – registers providers and installs the per‑user service
./bin/model-router setup --guided

Configuration files live under config/. For example, config/kimi/kimi.json holds Kimi OAuth settings, while config/anthropic/anthropic.json stores Anthropic keys. The installer reads any existing credentials and prompts only for missing ones via a hidden terminal prompt.

Running the router manually:

./bin/model-router start   # starts the local gateway

The Codex client will automatically discover the gateway on http://127.0.0.1:<port>.

Real‑World Use

A software team wants to evaluate DeepSeek and Grok alongside OpenAI without exposing API keys to the main CI runner. They install codex-router on a developer workstation, run codex-router setup --guided, and add the generated config/deepseek/deepseek.json to their version‑controlled, encrypted secrets store. All CI jobs now reference the local gateway, keeping keys off the build server while still allowing automated tests to hit the external models.

Code Health & Issues

  • Measured Findings (125 total)
  • High‑clarity hubsrc/paths.mjs, src/file-security.mjs, src/caller-auth.mjs each have >30 dependents; keep them small and stable.
  • Medium cognitive load – 40 files show >28 branch points in ≤93 lines (e.g., src/caller-auth.mjs). Refactor into strategy tables.
  • Oversized filessrc/vision-bridge.mjs, apps/desktop/ui/i18n.mjs, src/catalog.mjs exceed 800 lines; split by responsibility.
  • Duplicated code – 543 identical 6‑line blocks across 127 files (e.g., Formula/codex-router.rb, apps/desktop/ui/app.js). Extract shared helpers.
  • Code‑Health Audit
  • MEDIUM.github/workflows/ci.yml lacks persist-credentials: false on the checkout step. Add the flag to prevent token leakage.
  • LOW – No timeout-minutes on CI jobs; set a realistic timeout to avoid overlapping runs.
  • Repository Hygiene – Tests (test/), CI (GitHub Actions), license, and lockfiles are present; no Dockerfile or committed secrets detected.

The Bottom Line

codex-router delivers a functional, single‑point integration layer for many LLM providers, with a clear installation path and solid test coverage. The core routing logic is centralized in a few high‑impact modules, so careful changes are required there. Code size and duplication issues should be addressed before scaling the project, but the repo is otherwise healthy and ready for production use by teams needing credential‑safe multi‑provider access.