OmniRoute Documentation

Never stop coding. Free MIT AI gateway: one endpoint, 330+ providers (90+ free), 1200+ models — Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax.

46,673 stars TypeScript TypeScript 1 file · ~16,425 tokens #a2a#ai-agents#ai-gateway#anthropic#claude#claude-code#cline#codex
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy OmniRoute on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name omniroute -p 6379:6379 --restart always omniroute:base
Configured Services & Ports
⚙️ redis
image: docker.io/library/redis:8.6.5-alpine
🔌 Ports: ${REDIS_BIND_HOST:-127.0.0.1}:${REDIS_PORT:-6379}:6379
⚙️ omniroute-base
image: omniroute:base
🔌 Ports: ${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}, ${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}, ${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}
⚙️ omniroute-web
image: omniroute:web
🔌 Ports: ${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}, ${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}, ${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}
⚙️ chatgpt-web-codex-browser
image: omniroute:chatgpt-web-codex-browser
⚙️ omniroute-cli
image: omniroute:cli
🔌 Ports: ${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}, ${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}, ${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}
⚙️ omniroute-host
image: omniroute:base
🔌 Ports: ${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}, ${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}, ${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}
⚙️ qdrant
image: docker.io/qdrant/qdrant:v1.12.4
🔌 Ports: ${QDRANT_BIND_HOST:-127.0.0.1}:${QDRANT_PORT:-6333}:6333, ${QDRANT_BIND_HOST:-127.0.0.1}:${QDRANT_GRPC_PORT:-6334}:6334
⚙️ bifrost
image: ghcr.io/maximhq/bifrost:v1.6.11
🔌 Ports: ${BIFROST_BIND_HOST:-127.0.0.1}:${BIFROST_PORT:-8080}:8080
⚙️ cliproxyapi
image: docker.io/eceasy/cli-proxy-api:v6.9.7
🔌 Ports: ${CLIPROXY_BIND_HOST:-127.0.0.1}:${CLIPROXYAPI_PORT:-8317}:${CLIPROXYAPI_PORT:-8317}
⚙️ codex-app-server
image: omniroute:base
docker-compose.yml
yaml (docker-compose.yml)
# ──────────────────────────────────────────────────────────────────────
#  OmniRoute — Docker Compose
# ──────────────────────────────────────────────────────────────────────
#
#  Profiles:
#    base  → minimal image, no CLI tools
#    web   → runner-web (+Chromium/Playwright) for web-cookie providers
#    cli   → bundled CLIs installed inside the container (portable)
#    host  → runner-base + host-mounted CLI binaries (Linux-first; Linux only)
#    cliproxyapi → CLIProxyAPI sidecar on port 8317
#    memory  → Qdrant sidecar on port 6333 (semantic memory offload)
#    bifrost → Bifrost Go sidecar on port 8080 (Tier-1 LLM router)
#
#  Usage:
#    docker compose --profile base up -d
#    docker compose --profile web up -d   # gemini-web / claude-web / claude-turnstile
#    docker compose --profile cli up -d
#    # Windows Docker Desktop: use the bundled CLI image and rebuild it
#    docker compose --profile cli up -d --build
#    docker compose --profile host up -d
#    docker compose --profile cliproxyapi up -d
#    docker compose --profile cli --profile cliproxyapi up -d
#    docker compose --profile base --profile memory up -d   # adds Qdrant sidecar
#    docker compose --profile base --profile bifrost up -d  # adds Bifrost sidecar
#
#  Docker Compose uses `--profile  `; `load profile` is not a
#  valid command. The `base` profile has no CLI tools, and `host` is Linux-only.
#  Windows Docker Desktop users who need the four bundled CLI packages should use `cli`.
#
#  See docs/architecture/cluster-decisions.md for the per-component rationale
#  (Qdrant=opt-in, Bifrost=opt-in, Caddy=upstream LB, no Dragonfly/NATS/PG/Neo4j/MinIO).
#
#  Before first run, copy .env.example → .env and edit your secrets.
# ──────────────────────────────────────────────────────────────────────

x-common: &common
  restart: unless-stopped
  stop_grace_period: 40s
  env_file: .env
  environment:
    - DATA_DIR=/app/data # Must match the volume mount below
    - OMNIROUTE_BASE_PATH=${OMNIROUTE_BASE_PATH:-}
    - PORT=${PORT:-20128}
    - DASHBOARD_PORT=${DASHBOARD_PORT:-20128}
    - API_PORT=${API_PORT:-20129}
    - API_HOST=${API_HOST:-127.0.0.1}
    - LIVE_WS_PORT=${LIVE_WS_PORT:-20132}
    - LIVE_WS_HOST=${LIVE_WS_HOST:-127.0.0.1}
    - LIVE_WS_ALLOWED_ORIGINS=${LIVE_WS_ALLOWED_ORIGINS:-http://localhost:20128,http://127.0.0.1:20128}
    - REDIS_URL=${REDIS_URL:-redis://redis:6379}
    - NODE_OPTIONS=--max-old-space-size=2048
    # Codex App-Server transport (provider: codex-app-server). Inert unless the
    # `codex-app-server` compose profile is up (the sidecar below). Points the app
    # at the internal sidecar; the capability token is shared via the mounted file.
    - OMNIROUTE_CODEX_APPSERVER_WS=${OMNIROUTE_CODEX_APPSERVER_WS:-ws://codex-app-server:1456}
    - OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE=${OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE:-/run/codex-appserver/token}
  volumes:
    - ./data:/app/data
    # Shared capability token + codex auth for the app-server WS. Only meaningful
    # when the codex-app-server profile is active. The token dir carries the WS
    # capability token; the codex home is where the dashboard "Apply auth" writes
    # ~/.codex/auth.json (getCliConfigPaths("codex") = /.codex; the base
    # image runs as `node`, so /home/node/.codex) and the SAME volume is mounted
    # into the sidecar so its `codex app-server` reads the same auth.
    - codex-appserver-token:/run/codex-appserver
    - codex-appserver-home:/home/node/.codex
  healthcheck:
    test: ["CMD", "node", "healthcheck.mjs"]
    interval: 30s
    timeout: 5s
    retries: 3
    start_period: 15s

services:
  # ── Redis (Rate Limiter Backend) ──────────────────────────────────
  redis:
    image: docker.io/library/redis:8.6.5-alpine
    container_name: omniroute-redis
    restart: unless-stopped
    ports:
      # Loopback-only by default: this Redis has no `requirepass`, and the app
      # containers reach it over the compose network (redis:6379), so the
      # published port exists purely for host-side tooling (redis-cli, a local
      # `npm run dev`). A bare "6379:6379" binds 0.0.0.0 — that puts an
      # unauthenticated Redis on every LAN interface. Override REDIS_BIND_HOST
      # only together with a password (`--requirepass`).
      - "${REDIS_BIND_HOST:-127.0.0.1}:${REDIS_PORT:-6379}:6379"
    volumes:
      - redis-data:/data
    command: redis-server --save 60 1 --loglevel warning
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  # ── Profile: base (minimal, no CLI tools) ──────────────────────────
  omniroute-base:
    <<: *common
    container_name: omniroute
    build:
      context: .
      target: runner-base
      args:
        OMNIROUTE_BASE_PATH: ${OMNIROUTE_BASE_PATH:-}
    image: omniroute:base
    ports:
      # Loopback-only by default (#12568): with REQUIRE_API_KEY=false shipping
      # as the .env.example default, an unqualified publish spec here binds
      # 0.0.0.0 and exposes the anonymous /v1 LLM proxy on every LAN/WAN
      # interface. Set APP_BIND_HOST=0.0.0.0 only once you've confirmed
      # REQUIRE_API_KEY=true or an upstream reverse proxy enforces its own auth.
      - "${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}"
      - "${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}"
      - "${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}"
    profiles:
      - base

  # ── Profile: web (runner-web + Chromium/Playwright) ────────────────
  # Required for web-cookie providers (gemini-web, claude-web, claude-turnstile).
  # The default `base` image ships without Chromium, so those providers fail
  # with "Executable doesn't exist at .../ms-playwright/chromium..." (#2832).
  omniroute-web:
    <<: *common
    container_name: omniroute
    build:
      context: .
      target: runner-web
      args:
        OMNIROUTE_BASE_PATH: ${OMNIROUTE_BASE_PATH:-}
    image: omniroute:web
    depends_on:
      chatgpt-web-codex-browser:
        condition: service_started
    environment:
      - DATA_DIR=/app/data
      - PORT=${PORT:-20128}
      - DASHBOARD_PORT=${DASHBOARD_PORT:-20128}
      - API_PORT=${API_PORT:-20129}
      - API_HOST=${API_HOST:-127.0.0.1}
      - LIVE_WS_PORT=${LIVE_WS_PORT:-20132}
      - LIVE_WS_HOST=${LIVE_WS_HOST:-127.0.0.1}
      - LIVE_WS_ALLOWED_ORIGINS=${LIVE_WS_ALLOWED_ORIGINS:-http://localhost:20128,http://127.0.0.1:20128}
      - REDIS_URL=${REDIS_URL:-redis://redis:6379}
      - OMNIROUTE_BASE_PATH=${OMNIROUTE_BASE_PATH:-}
      - CHATGPT_WEB_CODEX_CDP_URL=http://chatgpt-web-codex-browser:9223
      - CDP_PROXY_TOKEN=${CDP_PROXY_TOKEN:-}
      - CDP_PROXY_TOKEN_FILE=/cdp-token/token
    volumes:
      - chatgpt-web-codex-cdp-token:/cdp-token:ro
    ports:
      - "${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}"
      - "${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}"
      - "${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}"
    # SECURITY (#13679): joins BOTH `default` (to keep reaching redis and the
    # other sidecars) AND the dedicated `chatgpt-web-codex-net` (the one
    # legitimate consumer of the CDP proxy below).
    networks:
      - default
      - chatgpt-web-codex-net
    profiles:
      - web

  # Internal-only Chromium runtime for ChatGPT Web (Codex). No CDP or browser
  # UI port is published to the host.
  #
  # SECURITY (#13679): isolated onto its own `chatgpt-web-codex-net` network
  # instead of the shared implicit default bridge — its cdp-proxy.mjs
  # sidecar republishes Chromium's CDP on 0.0.0.0:9223, and CDP grants full
  # control over a live browser session. Without this isolation, any
  # compromised sibling container (redis, qdrant, bifrost, cliproxyapi,
  # codex-app-server, ...) on the default network could reach it.
  chatgpt-web-codex-browser:
    build:
      context: .
      dockerfile: docker/chatgpt-web-codex-browser/Dockerfile
    image: omniroute:chatgpt-web-codex-browser
    restart: unless-stopped
    shm_size: "2gb"
    environment:
      # #14486: fail-closed. Empty CDP_PROXY_TOKEN => the proxy generates a
      # secret into the shared cdp-token volume that omniroute-web reads.
      - CDP_PROXY_TOKEN=${CDP_PROXY_TOKEN:-}
      - CDP_PROXY_TOKEN_FILE=/cdp-token/token
    volumes:
      - chatgpt-web-codex-browser-data:/browser-profile
      - chatgpt-web-codex-cdp-token:/cdp-token
    networks:
      - chatgpt-web-codex-net
    profiles:
      - web

  # ── Profile: cli (CLIs installed inside container) ─────────────────
  omniroute-cli:
    <<: *common
    container_name: omniroute
    build:
      context: .
      target: runner-cli
      args:
        OMNIROUTE_BASE_PATH: ${OMNIROUTE_BASE_PATH:-}
    image: omniroute:cli
    ports:
      - "${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}"
      - "${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}"
      - "${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}"
    volumes:
      - ./data:/app/data
      # SECURITY: mounting the host Docker socket gives this container full
      # control over the host Docker daemon — it can create/list/stop/rm any
      # container the host runs. It is here so the in-container auto-updater
      # (src/lib/system/autoUpdate.ts) can recreate the stack. Only use this
      # profile on a single-tenant workstation you trust, and never publish
      # its ports beyond 127.0.0.1. See docs/guides/DOCKER_GUIDE.md →
      # "Escape hatch: configure the container's own CLIs" for the threat model.
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/libexec/docker/cli-plugins:/usr/libexec/docker/cli-plugins:ro
      - ${AUTO_UPDATE_HOST_REPO_DIR:-.}:/workspace/omniroute:rw
    profiles:
      - cli

  # ── Profile: host (host-mounted CLI binaries, Linux-first) ────────
  omniroute-host:
    <<: *common
    container_name: omniroute
    build:
      context: .
      target: runner-base
      args:
        OMNIROUTE_BASE_PATH: ${OMNIROUTE_BASE_PATH:-}
    image: omniroute:base
    ports:
      - "${APP_BIND_HOST:-127.0.0.1}:${DASHBOARD_PORT:-20128}:${DASHBOARD_PORT:-20128}"
      - "${APP_BIND_HOST:-127.0.0.1}:${API_PORT:-20129}:${API_PORT:-20129}"
      - "${APP_BIND_HOST:-127.0.0.1}:${LIVE_WS_PORT:-20132}:${LIVE_WS_PORT:-20132}"
    environment:
      - DATA_DIR=/app/data
      - PORT=${PORT:-20128}
      - DASHBOARD_PORT=${DASHBOARD_PORT:-20128}
      - API_PORT=${API_PORT:-20129}
      - API_HOST=${API_HOST:-127.0.0.1}
      - LIVE_WS_PORT=${LIVE_WS_PORT:-20132}
      - LIVE_WS_HOST=${LIVE_WS_HOST:-127.0.0.1}
      - LIVE_WS_ALLOWED_ORIGINS=${LIVE_WS_ALLOWED_ORIGINS:-http://localhost:20128,http://127.0.0.1:20128}
      - CLI_MODE=host
      - CLI_EXTRA_PATHS=/host-local/bin:/host-node/bin
      - CLI_CONFIG_HOME=/host-home
      - CLI_ALLOW_CONFIG_WRITES=true
      # Uncomment per-tool overrides as needed:
      # - CLI_CURSOR_BIN=agent
      # - CLI_CLINE_BIN=cline
      # - CLI_CONTINUE_BIN=cn
    volumes:
      - ./data:/app/data
      # ── Host binary mounts (read-only) ──
      # Adjust paths below to match YOUR host system.
      - ~/.local/bin:/host-local/bin:ro
      # Node global binaries (adjust node version path)
      # - ~/.nvm/versions/node/v24.14.1/bin:/host-node/bin:ro
      # ── Host config mounts (read-write) ──
      - ~/.codex:/host-home/.codex:rw
      - ~/.claude:/host-home/.claude:rw
      - ~/.factory:/host-home/.factory:rw
      - ~/.openclaw:/host-home/.openclaw:rw
      - ~/.cursor:/host-home/.cursor:rw
      - ~/.config/cursor:/host-home/.config/cursor:rw
    profiles:
      - host

  # ── Profile: memory (Qdrant semantic-memory sidecar) ─────────────
  # Off by default. SQLite + sqlite-vec + FTS5 (RRF) is the primary vector
  # store (see src/lib/memory/vectorStore.ts). Enable only when you need
  # cross-instance memory sharing or >1M points — at which point the
  # QDRANT_ENABLED=true flag activates the dual-write path in
  # src/lib/memory/qdrant.ts:37. See docs/architecture/cluster-decisions.md
  # for the workload analysis behind this profile.
  qdrant:
    image: docker.io/qdrant/qdrant:v1.12.4
    container_name: omniroute-qdrant
    restart: unless-stopped
    ports:
      - "${QDRANT_BIND_HOST:-127.0.0.1}:${QDRANT_PORT:-6333}:6333"
      - "${QDRANT_BIND_HOST:-127.0.0.1}:${QDRANT_GRPC_PORT:-6334}:6334"
    volumes:
      - qdrant-data:/qdrant/storage
    environment:
      - QDRANT__SERVICE__GRPC_PORT=6334
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:6333/readyz"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 10s
    profiles:
      - memory

  # ── Profile: bifrost (Bifrost Go LLM-router sidecar) ─────────────
  # Off by default. Bifrost is the Tier-1 LLM router (per ADR-031 and
  # open-sse/executors/bifrost.ts). When BIFROST_ENABLED=true is set in
  # .env, OmniRoute delegates /v1/chat/completions, /v1/responses, and
  # /v1/embeddings to this sidecar instead of handling them in chatCore.
  # The kill switch is the BIFROST_ENABLED env var — flip to false to
  # fall back to the chatCore path with zero code changes. See
  # docs/architecture/cluster-decisions.md for the activation plan.
  bifrost:
    image: ghcr.io/maximhq/bifrost:v1.6.11
    container_name: omniroute-bifrost
    restart: unless-stopped
    ports:
      - "${BIFROST_BIND_HOST:-127.0.0.1}:${BIFROST_PORT:-8080}:8080"
    volumes:
      - bifrost-data:/data
    environment:
      - BIFROST_LOG_LEVEL=${BIFROST_LOG_LEVEL:-info}
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:8080/v1/models"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s
    profiles:
      - bifrost

  # ── Profile: cliproxyapi (CLIProxyAPI as sidecar) ─────────────────
  # Official pre-built image lives on Docker Hub (eceasy/cli-proxy-api);
  # ghcr.io/router-for-me/* is not publicly pullable. v6.9.7 is the pinned
  # version the sidecar integration (port 8317, /v1/models healthcheck) targets.
  cliproxyapi:
    container_name: cliproxyapi
    image: docker.io/eceasy/cli-proxy-api:v6.9.7
    restart: unless-stopped
    ports:
      # Loopback-only by default: this sidecar's data volume
      # (cliproxiapi-data:/root/.cli-proxy-api) holds provider OAuth/API
      # credentials, and the pinned image only reads api-keys from a mounted
      # config.yaml (not env vars), so an unqualified "8317:8317" publish spec
      # would put a credential-bearing service with no compose-configured
      # data-plane auth on every LAN interface. Same reasoning as Redis above.
      - "${CLIPROXY_BIND_HOST:-127.0.0.1}:${CLIPROXYAPI_PORT:-8317}:${CLIPROXYAPI_PORT:-8317}"
    volumes:
      - cliproxyapi-data:/root/.cli-proxy-api
    environment:
      - PORT=${CLIPROXYAPI_PORT:-8317}
      - HOST=0.0.0.0
      # Forwards to the one auth-related env var the pinned binary actually
      # reads (MANAGEMENT_PASSWORD) — secures the management API only; the
      # data-plane completions endpoints have no env-based override upstream.
      - MANAGEMENT_PASSWORD=${CLIPROXYAPI_MANAGEMENT_KEY:-}
    healthcheck:
      test:
        ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:${CLIPROXYAPI_PORT:-8317}/v1/models"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    profiles:
      - cliproxyapi

  # ── Profile: codex-app-server (Codex CLI app-server sidecar) ──────────
  # A PLAIN Codex app-server for the `codex-app-server` provider: OmniRoute drives
  # the Codex CLI's own `codex app-server` over JSON-RPC/WebSocket instead of
  # replaying a session token to the API. It listens ONLY on the internal compose
  # network (ws://codex-app-server:1456), guarded by a capability token — it is
  # NEVER published to the host / internet. The Codex CLI (baked into
  # omniroute:base) self-manages its OpenAI OAuth via the shared ~/.codex volume,
  # which the dashboard "Apply auth" (device-OAuth) writes and this sidecar reads.
  #
  # NOTE: this is the GENERIC public sidecar. An operator wanting residential /
  # UDP egress (via a TUN sidecar) runs that separately as an override; it is
  # intentionally not shipped here.
  codex-app-server:
    image: omniroute:base
    container_name: omniroute-codex-app-server
    restart: unless-stopped
    # Generate the WS capability token on first boot if absent, then run the
    # app-server. entrypoint is overridden because the base image's default is the
    # Next.js server.
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        set -e
        TOKEN_FILE=/run/codex-appserver/token
        mkdir -p /run/codex-appserver
        if [ ! -s "$$TOKEN_FILE" ]; then
          # 32-byte hex capability token; shared with the app via the token volume.
          TF="$$TOKEN_FILE" node -e 'require("fs").writeFileSync(process.env.TF, require("crypto").randomBytes(32).toString("hex"))' 2>/dev/null || \
            { head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$$TOKEN_FILE"; }
          chmod 600 "$$TOKEN_FILE"
        fi
        exec codex app-server \
          --listen ws://0.0.0.0:1456 \
          --ws-auth capability-token \
          --ws-token-file "$$TOKEN_FILE"
    environment:
      - CODEX_HOME=/home/node/.codex
      - RUST_LOG=${CODEX_APPSERVER_RUST_LOG:-warn}
    volumes:
      - codex-appserver-token:/run/codex-appserver
      - codex-appserver-home:/home/node/.codex
    # No `ports:` — internal-only. Reached at ws://codex-app-server:1456 over the
    # compose network by the omniroute app.
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "require('http').get('http://127.0.0.1:1456/readyz',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))",
        ]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    profiles:
      - codex-app-server

networks:
  # SECURITY (#13679): dedicated network for the unauthenticated-by-default
  # CDP proxy sidecar (docker/chatgpt-web-codex-browser/cdp-proxy.mjs) —
  # shared only with omniroute-web, not with redis/qdrant/bifrost/cliproxyapi/
  # codex-app-server or any other sibling on the implicit default network.
  chatgpt-web-codex-net: {}

volumes:
  chatgpt-web-codex-cdp-token:
    name: omniroute-chatgpt-web-codex-cdp-token
  chatgpt-web-codex-browser-data:
    name: omniroute-chatgpt-web-codex-browser-data
  cliproxyapi-data:
    name: cliproxyapi-data
  redis-data:
    name: omniroute-redis-data
  qdrant-data:
    name: omniroute-qdrant-data
  bifrost-data:
    name: omniroute-bifrost-data
  codex-appserver-token:
    name: omniroute-codex-appserver-token
  codex-appserver-home:
    name: omniroute-codex-appserver-home

File: README.md

Stacking free tiers by hand is painful — dozens of SDKs, dozens of rate limits, and no idea how much you actually have. OmniRoute aggregates the documented free tiers of 42 provider pools / 495 models into one honest number and shows it live on the dashboard (/dashboard/free-tiers).

Animated summary of the live /dashboard/free-tiers page. Full methodology (pool dedupe, credit tiers, provider terms): docs/reference/FREE_TIERS.md.

These figures are re-audited every two weeks against the live catalog and move both ways — a provider ends a free tier and the number drops; a new one lands and it climbs. We publish what the catalog actually computes, never a rounded-up best case.

🧩 Available


🚀 Start 🚀 Quick Start 📦 Install 🆓 Zero-config
💡 Learn 💥 The Promise 🤔 Why OmniRoute 🏆 What Sets Apart
⚙️ Features 🎯 Combos 🌐 Providers 🔌 CLI & MCP
🗜️ Compression 🖥️ Where It Runs 🔒 Private
👀 See it 🎬 In Action ✨ What's New 🤖 Compatible CLIs
💚 Support 💚 Support / Donate 💬 Community 💖 Sponsors
📦 Project 🛠️ Tech Stack 📖 Docs 👥 Contributors
bash
# Fresh install, zero credentials — `auto` already works:
curl http://localhost:20128/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"Hello!"}]}'

Prefer a specific free backend? Call it directly, e.g. oc/… (OpenCode Free) or felo/… (Felo). Then graduate to auto and let OmniRoute pick.

📦 Copy-paste quickstart scripts for Python, Node.js, PHP, and cURL → examples/quickstart/

Want to join as an Open Source Friend? These are the companies that back open source and help keep OmniRoute moving — and we say publicly where every token they give us goes. Reach out: [email protected]

| KimiMoonshot AI | Thanks to Kimi (Moonshot AI), our founding Open Source Friend, for backing this project! Kimi is the AI lab behind the open-weight K2 and K3 model families — Kimi K3 delivers a 1M-token context window, native vision and frontier-level coding at a fraction of closed-model prices, and works out of the box with Claude Code, Codex and every coding tool OmniRoute serves.

text
**What Kimi's support powers:** Kimi's API credits power OmniRoute's AI-validated release pipeline — the *merge validation powered by Kimi K3* stage that reviews every pull request before it ships — plus day-to-day feature development. First-class Kimi support ships on both rails: the direct [Kimi API](https://platform.kimi.ai?track_id=track-8197581fdd7d4139a0f562e4a03c3798&aff=omniroute) (`kimi-k3`) and the [Kimi Code coding plan](https://www.kimi.com/code?aff=omniroute) (OAuth and API key). OmniRoute is also the first Brazilian open-source project in Kimi's support program. [**Get a Kimi API key with 15% extra credits →**](https://platform.kimi.ai?track_id=track-8197581fdd7d4139a0f562e4a03c3798&aff=omniroute) |

| --- | --- |
| Cheaper Inferencecheaperinference.com | Thanks to Cheaper Inference, an OmniRoute Open Source Friend, for backing this project! Cheaper Inference is a cost-ranked gateway that resells 42 frontier models — Claude, GPT-5.x, Gemini, Kimi K3, GLM, DeepSeek, Grok and MiniMax — behind one OpenAI-compatible endpoint, routing each request to the cheapest eligible provider without ever charging above the model maker's list price.

text
**First-class support in OmniRoute:** Chat Completions, the native `/v1/responses` endpoint, vision, tool calling and 3 image models (`grok-imagine`, `nano-banana-pro`, `nano-banana-2`, reachable as `cheaperinference/&lt;model&gt;`). [**Get an API key →**](https://cheaperinference.com/?utm_source=omniroute) |

Links tagged aff=omniroute are partner links. They fund the project at no extra cost to you.

🎟️ Affiliates Promo — free signup coupons from providers we don't sponsor (click to expand)

This section is for referral/coupon codes only. Sponsored partnerships live in 🤝 Supported by our Open Source Friends above. OmniRoute has no sponsorship or partnership with the providers listed here — these are public coupons anyone can use.

| AgentRouteragentrouter.org | AgentRouter — affiliate signup · $100 free credits on signup (free server, expect higher latency — best for testing, not production). First-class support in OmniRoute since v3.8.50: Chat Completions, the Anthropic-compatible wire format and the OpenAI-compatible path. Available models include claude-opus-4-8, claude-opus-5, gpt-5.6-sol and more. Grab your $100 →

text
⚠️ *Affiliate link — OmniRoute has no sponsorship or partnership with this provider.* |

| --- | --- |

Know another provider with a generous free signup coupon that benefits OmniRoute users? Open an issue and we'll add it here.

A combo is a chain of models OmniRoute routes across automatically. Quota runs out, a provider fails, or costs spike — the combo silently slides to the next model. This is what makes OmniRoute unbreakable. 🛡️

⚡ Zero-config — just use `auto`

No combo to create. Set your model to auto (or a variant) and OmniRoute builds a virtual combo from your connected providers, scored live:

Model ID What it optimizes for
auto 🎯 Balanced default (LKGP — sticks to your last good provider)
auto/coding 🧑‍💻 Quality-first weights for code generation
auto/fast ⚡ Lowest latency first
auto/cheap 💰 Cheapest per token first
auto/offline 🔋 Most quota / rate-limit headroom first
auto/smart 🔭 Quality-first + 10% exploration to discover better models

🔀 Or build your own — 19 routing strategies

All 19 strategies — mix & match per combo step:

# Strategy What it does
1 priority First-target ordered list — drain each before the next 🥇
2 fill-first Fill each target's quota fully before moving on
3 weighted Weighted random by per-target weight
4 round-robin Cycle through targets in order
5 p2c Power-of-two-choices random load balancing
6 least-used Pick the target with the lowest current load
7 random Uniform random pick (deduplicated)
8 strict-random Random without de-duplicating repeats 🎲
9 cost-optimized Minimize $ per request from live catalog pricing 💸
10 headroom Pick the target with the most remaining quota
11 reset-window Prefer the target whose quota window resets soonest
12 reset-aware Rank by quota reset time — short windows first 📊
13 context-relay Hand off context across targets for long conversations 🧠
14 context-optimized Pick the best fit for the current context size
15 cache-optimized Pin each reusable prompt prefix to the same account — maximize prompt-cache hits 🎯
16 lkgp Last-Known-Good Path — sticky to the last successful target
17 auto 14-factor live scoring across every connection 🤖
18 fusion Fan out to a panel of models + a judge synthesizes one answer 🧬
19 pipeline Chain steps — each target's output feeds the next one 🔗

The Auto-Combo engine scores every candidate on 14 factors (health, quota, cost, latency, success rate, freshness…) — see docs/routing/AUTO-COMBO.md.

🧱 Resilience is built in (3 independent layers)

📖 Auto-Combo Engine · Resilience Guide

📊 Full methodology & per-feature detail vs 9router, OpenRouter, CLIProxyAPI & LiteLLM → docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md

💚 Support OmniRoute

OmniRoute is MIT-licensed and maintained in the open. If it saves you time or money, here's how to keep it independent — pick whatever fits you. Sponsorship never affects routing priority; it buys visibility, not ranking.

⭐ Star the repo Free — genuinely helps visibility Star OmniRoute
🐙 GitHub Sponsors One-off or monthly · zero platform fee github.com/sponsors/diegosouzapw
☕ Ko-fi Quick one-off tip, no signup for the donor ko-fi.com/diegosouzapw
🧋 Buy Me a Coffee Small, informal gesture buymeacoffee.com/diegosouzapw
🖐 Liberapay Recurring · non-profit · open source liberapay.com/diegosouzapw
🇧🇷 PIX (Brazil) Instant, no fees key & QR below
₿ Crypto BTC · ETH · USDT-TRC20 · USDC-Solana addresses below

🇧🇷 PIX — instant, no fees (Brazil)

Key (random): 5d865059-bc44-483a-962d-43ceb80126eb

Pix copia-e-cola:

text
00020101021126580014br.gov.bcb.pix01365d865059-bc44-483a-962d-43ceb80126eb5204000053039865802BR5922OMNIROUTE CONTRIBUICAO6006BRASIL62070503***630475DD

₿ Crypto — BTC · ETH · USDT-TRC20 · USDC-Solana (click to expand)

₿ BTC Bitcoin (SegWit) bc1qh00smz004sy85wyl28v77tenkt3ckl6eaep7fd
Ξ ETH Ethereum (ERC20) 0x64Cf6B68A6Ff34288e89172950a2d00102337a84
₮ USDT Tron (TRC20) TKAF41JpuQrHbKTnsQa9svJE2T192Hvsc2
$ USDC Solana 2emNNZzVVWQc3FQ2wk9M6qXUQmW8AKdjjL174fXR28Tu

⚠️ Send each coin only on the network shown — sending on the wrong network can lose the funds.

🐛 Found a bug or have feedback? Open a Discussion.

Developer notes: The project may generate a local .env file during npm install/postinstall for developer convenience. This file is intentionally ignored via .gitignore (see .gitignore) and must never be committed — if accidentally committed, rotate any exposed secrets and remove the file from history. See docs/DEVELOPER-ENVIRONMENT.md for guidance on managing local environment files and secrets.

📡 OmniRoute Radar

The main free-tier headline remains ~1.53B tokens/month from the documented,
pool-deduplicated catalog above. Temporary provider signup credits can separately lift the first
month to ~2.15B. Radar is an optional, signed catalog overlay for people who want fresher
free-model availability between OmniRoute releases; the community catalog and every existing free
feature remain free.

Supporters can receive the live catalog and additional provider opportunities. Its separate,
mutable ceiling is approximately 3B tokens/month at most, depending on provider availability.
That ceiling is not a guarantee: providers can change quotas, eligibility, models, or regions at
any time.

Radar is opt-in and GET-only. The OmniRoute client does not upload prompts, traffic, provider
configuration, usage telemetry, or local announcement-dismiss state. Learn about eligibility and
the current catalog at radar.omniroute.online/planos.

Recent highlights from v3.8.20 → v3.8.50. Full history in CHANGELOG.md.

  • 🎛️ OmniConductor — inbound A2A delegation to your agent fleet, Conductor skills on the Agent Card, and a dashboard panel with Faro push-to-talk voice chat. → A2A Server
  • 🛂 Adaptive admission & overload protection — heavyweight chat requests queue instead of 503ing, with atomic RPM rolling leases per connection. → Resilience Guide
  • 🗂️ Canonical /v1/models ordering — one contiguous provider-grouped block per provider (combos pinned first), stable across every catalog source. → API Reference
  • 🗜️ Compression hardening — default-on inflation guard, Caveman packs for DE / FR / JA + Chinese (wényán), RTK filters for Gradle & .NET. → Compression
  • 💸 Honest flat-rate cost — subscription / coding-plan providers read $0 in cost analytics; budget, quota & routing keep estimating. → API Reference
  • ⚖️ Quota-Share routing — split a shared account's quota fairly across pooled keys, work-conserving so idle slices are lent out. → Resilience Guide
  • 🤖 One-command CLI/agent setup — setup-* configures 12+ coding tools; omniroute run launches 7 CLIs (Claude Code, Codex, Aider, Goose, OpenCode, Qwen Code, Gemini CLI) with zero config written; omniroute configure is an interactive provider+model picker with per-context favorites. → CLI Integrations
  • 🛰️ Remote mode — drive a remote OmniRoute with scoped tokens (connect / contexts / tokens) + an antigravity OAuth helper for VPS installs. → Remote Mode
  • 🧭 Smarter auto-routing — auto/<category>:<tier> combos, Fusion (model panel + judge), task-aware routing, per-request model / mode / USD-budget overrides. → Auto-Combo
  • 🗜️ Pluggable compression — 12 composable engines + Compression Studios: LLMLingua-2, two-tier Ultra, omniglyph, per-step fidelity gate, GCF v3.2, drag-reorder editor. → Compression
  • 🕵️ Transparent MITM decrypt (TPROXY) — capture CLIs that ignore proxy env vars, with a per-SNI CA + trust-store installer. → MITM/TPROXY
  • 💸 Cost telemetry everywhere — X-OmniRoute-* cost/usage headers on every endpoint, cache-HIT savings header, per-key USD spend quotas. → API Reference
  • 🧠 Memory you control — off by default, opt-in int8 vector quantization + typed decay, per-request x-omniroute-no-memory. → Memory
  • 🛡️ Security — prompt-injection guard on every LLM route (red-team suite), opt-in credential-masking guardrail (redacts leaked API keys/secrets in both directions), free DuckDuckGo last-resort web search, and an optional OIDC login gate for the dashboard (password login always stays available). → Guardrails
  • 🖼️ New endpoints — /v1/ocr (Mistral OCR) and /v1/audio/translations (Whisper-style) round out the media surface. → API Reference
  • 🎨 Image / video / audio generation — one API for media: xAI Grok Imagine & Novita AI video, ComfyUI, Freepik, Adobe Firefly, Microsoft Designer, Segmind, EdgeTTS. → API Reference
  • 🌍 Deployment & ops — reverse-proxy basePath, browser-language auto-detect, per-key device tracking, root-less MITM trust, zh-TW localization. → Environment
  • 🤝 More providers & agents — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed 343-provider catalog. → Providers
  • 📡 Routing transparency — every response carries an X-OmniRoute-Decision header naming the strategy/provider/latency that served it, a new cache-optimized combo strategy + Auto-Combo cacheAffinity factor route repeat requests back to the connection holding the cached prefix, and a read-only /v1/auto-combo/{channel}/candidates endpoint exposes an auto/* channel's live candidate pool. → Auto-Combo
  • ⚡ Local performance & infra — one-click local Redis, Cloudflare Workers / Deno Deploy relay deployers, Bifrost & Mux as supervised embedded services. → Embedded Services

📖 Per-tool setup for all 34 tools (26 CLI Code's + 8 CLI Agents) → docs/reference/CLI-TOOLS.md · 🧩 OpenCode plugin → @omniroute/opencode-provider

Launch any supported CLI through OmniRoute in one command — no config files written,
credentials injected per process, Qwen/Gemini get a throwaway isolated home:

bash
omniroute run claude   --model openai/gpt-5.4          # Claude Code
omniroute run codex    --model glm/glm-5.2             # OpenAI Codex CLI
omniroute run aider    --model glm/glm-5.2 -- --message "reply OK"
omniroute run goose    --model glm/glm-5.2
omniroute run opencode --model glm/glm-5.2 -- run "reply OK"
omniroute run qwen     --model glm/glm-5.2 -- -p "reply OK"
omniroute run gemini   --model glm/glm-5.2 -- --skip-trust -p "reply OK"

# Or pick provider+model interactively and write the tool's own config:
omniroute configure codex          # also: claude opencode qwen aider goose cline continue kilo

Every command honors the active remote context (omniroute connect <host>), --dry-run
previews the exact env/args without executing, and --api-key-env NAME keeps secrets out
of your shell history. → CLI Integrations

The most complete catalog of any open-source router: 343 providers, 90+ with a free tier, 56 free forever.

Same app, your machine, your rules. From a global npm install to your phone via Termux.

Platform Install Highlights
📦 npm (global) npm install omniroute One command, any OS
🐳 Docker docker run … diegosouzapw/omniroute Multi-arch AMD64 + ARM64
🖥️ Desktop (Electron) npm run electron:build Native window + system tray — Windows / macOS / Linux
💪 ARM native arm64 Raspberry Pi, ARM servers, Apple Silicon
📱 Android (Termux) pkg install nodejs && npx -y omniroute Runs on your phone, 24/7, no root
📲 PWA "Add to Home Screen" Fullscreen, offline, installable from browser
🧩 OpenCode plugin @omniroute/opencode-provider Native OpenCode integration
🤖 VS Code Copilot Chat install OmniCopilot extension Every OmniRoute model in the native Copilot Chat picker — stable & Insiders
🛠️ From source npm install && npm run dev Hack on it, contribute

📖 Docker Guide · Desktop · Termux · PWA · OpenCode

No new sidebar, no new chat UI — every model OmniRoute serves shows up right in the
Copilot Chat model picker you already use. Since VS Code 1.122, provider models work
without a GitHub sign-in or a Copilot subscription — agent mode, tool calling and vision, for
free.

Install the OmniCopilot extension, point it
at your OmniRoute server (defaults to localhost:20128), then open Copilot Chat → model picker
→ Manage Models… → OmniRoute.

Store Link Works with
🧩 VS Code Marketplace Install → VS Code — stable & Insiders
🔓 Open VSX Registry Install → Cursor, Windsurf, VSCodium, Theia, code-server, Gitpod, Antigravity, Kiro…

From inside the editor: open the Extensions view, search "OmniRoute", click Install
— works the same way on both stores. Source, issues and the publishing runbook live at
diegosouzapw/OmniCopilot.

📖 VS Code Copilot Chat guide — setup, what the picker shows, dashboard-in-a-tab, troubleshooting

📖 Authorization · Guardrails · Compliance

Beyond the server, OmniRoute is a full command-line cockpit with 80+ commands, plus open agent protocols so an AI agent can drive it on its own.

⌨️ A real CLI (not just `start`)

bash
omniroute               # serve gateway + dashboard (port 20128)
omniroute chat          # interactive TUI chat client (slash: /model /combo /skill /memory)
omniroute setup         # guided first-run wizard
omniroute doctor        # diagnose providers, ports, native deps

🛰️ Remote mode — run the CLI here, OmniRoute on a VPS

OmniRoute on a server? Drive it from your laptop with the same CLI. Log in once
with a scoped access token; every command then targets the remote.

bash
omniroute connect 192.168.0.15            # password → scoped token, saved as a context
omniroute models list                     # ← runs against the REMOTE server
omniroute configure codex                 # ← picks a remote model, writes a local Codex profile
omniroute tokens create --name ci --scope read   # mint narrower tokens for other machines
omniroute contexts use default            # ← switch back to the local server

Tokens are scoped read / write / admin; process-spawning routes stay loopback-only.
📖 Remote Mode

🤝 Connect an agent — and it controls OmniRoute itself

Expose OmniRoute over MCP, A2A, a REST API, webhooks or a remote CLI — any capable agent (or your own code) gets the keys to the whole gateway: routing, providers, combos, cache, compression, memory — autonomously. HTTP endpoints below are served under http://localhost:20128.

Interface Endpoint / command Use it for
🧰 MCP (stdio) omniroute --mcp Plug into Claude Desktop, Cursor, any MCP client
🌊 MCP (HTTP) /api/mcp/stream Remote MCP — 109 tools, 33 scopes, full audit trail
📡 MCP (SSE) /api/mcp/sse Streaming MCP transport
🤝 A2A /.well-known/agent.json Agent-to-agent, JSON-RPC 2.0 + SSE, 6 skills
🌐 REST API /v1/* OpenAI-compatible — chat, embeddings, images, audio, OCR
🔔 Webhooks /api/webhooks Push events (usage, quota, errors, routing) to your URL
🛰️ Remote CLI omniroute connect Drive a remote instance with scoped access tokens
bash
# Give Claude Code the full OmniRoute toolset over MCP:
claude mcp add-server omniroute --type http --url http://localhost:20128/api/mcp/stream

📖 MCP Server · A2A Server · Agent Protocols

📖 How it works — pipeline, architecture & savings math

Default stacked combo runs RTK → Caveman. When both act on the same tool/context payload, savings compound:

txt
combined = 1 − (1 − RTK) × (1 − Caveman_input)
average  = 1 − (1 − 0.80) × (1 − 0.46) = 89.2%
range    = 78.4 – 94.6%

Code blocks, URLs, JSON and structured data are always protected by the preservation engine.

Why use many tokens when few tokens do the trick? Every request passes through OmniRoute's compression pipeline transparently — no client changes. It's now a stack of 12 composable engines that run in order and mix & match per routing combo — building on ideas from RTK, Caveman (⭐ 90K+), LLMLingua-2, and Troglodita (PT-BR).

🧱 The 12-engine stack

Engines run in pipeline order; each is independently toggleable and configurable per combo:

# Engine What it does
1 Session-Dedup Drops content repeated across turns (content-addressed, cross-turn)
2 CCR Archives large blocks behind retrieve markers, fetched on demand
3 Lite Whitespace + image-URL trimming (latency-light baseline)
4 RTK Smart tool-result filtering, dedup & truncation (command-aware)
5 Responses Tool Output Lossless-first JSON + bounded diagnostic compression for shell/patch/search/build outputs (Responses API)
6 Headroom Lossless tabular compaction of JSON arrays (~30%) via a vendored GCF codec
7 Relevance Extractive sentence scoring against the last user query
8 Caveman Rule-based prose compression (~65–75% on output)
9 Aggressive Summarization + progressive aging of old turns
10 LLMLingua-2 ML semantic pruning via MobileBERT ONNX — code-safe, async
11 Ultra Heuristic token pruning with an optional small-model (SLM) tier
12 OmniGlyph Experimental context-as-image encoding for measured Claude Fable 5 on the direct Anthropic wire; GPT 5.6 transformers remain fail-closed pending provider receipts. Four compression profiles (aggressive default, balanced, coding-safe, passthrough) (most aggressive; opt-in)

Code blocks, URLs and structured data are always preserved byte-perfect. One-click presets combine the engines:

Mode Savings Best for
🪶 Lite ~15% Always-on safe default
🪨 Standard (Caveman) ~30% Daily coding
⚡ Aggressive ~50% Long tool-heavy sessions
🔥 Ultra ~75% Maximum savings
🧰 RTK 60–90% Shell/test/build/git output
🔗 Stacked (RTK → Caveman) 78–95% Mixed prompts + tool logs

Real example — Standard mode:

Before (69 tokens): "The reason your React component is re-rendering is likely because you're creating a new object reference on each render cycle. When you pass an inline object as a prop, React's shallow comparison sees it as a different object every time, which triggers a re-render. I would recommend using useMemo to memoize the object."

After (19 tokens): "New object ref each render. Inline object prop = new ref = re-render. Wrap in useMemo."

Same answer. 72% fewer tokens. Zero accuracy loss. ✅

PT-BR example — Troglodita mode:

Antes (42 tokens): "O problema é que o componente está re-renderizando porque uma nova referência de objeto está sendo criada em cada ciclo de renderização. Eu recomendaria usar useMemo."

Depois (12 tokens): "Re-render: ref nova cada ciclo (objeto inline recriado). Usar useMemo."

Mesma resposta. ~70% menos tokens. Precisão técnica intacta. ✅

🎚️ Beyond the engines — output styles, the adaptive dial & per-request control

The 12 engines above shrink what goes in. Three more layers shape how, when, and what comes out:

  • 🪄 Output Styles (output-axis steering) — inject deterministic, cache-safe response-shaping instructions; combinable, each at lite / full / ultra intensity. Adding a style is a one-line registry entry:
    • Terse prose — drop filler / articles / hedging; keep technical substance exact.
    • Less code — "lazy senior dev" YAGNI: smallest working change, no unrequested scaffolding.
    • Terse CJK (文言) — classical-Chinese ultra-terse style (locale-gated to zh).
  • 🎯 Adaptive context-budget (the dial) — instead of one on/off token threshold, escalate the cheapest, most-lossless engines only as far as needed to fit the model's context window. Policy: reserve-output (default, model-aware) · percentage · absolute. Mode: floor (guarantee fit) · replace-autotrigger (your explicit choice wins) · off (legacy threshold).
  • 🎛️ Where compression is decided (precedence, high → low) — per-request x-omniroute-compression header › routing-combo override › active named profile › adaptive / auto-trigger › panel default › off. The applied plan echoes back in the X-OmniRoute-Compression: <mode>; source= response header.

Auto-trigger by token threshold, flip on the adaptive dial, pin a named profile, set a one-off per request, or assign a pipeline per routing combo — whichever fits the workload. An opt-in offline eval harness (npm run eval:compression) scores fidelity vs. savings on a pinned corpus before you promote a change.

📖 COMPRESSION_GUIDE.md · RTK_COMPRESSION.md · COMPRESSION_ENGINES.md

1) Install & run

bash
npm install omniroute
omniroute

💡 See npm warn ERESOLVE or peer-dep warnings? They're harmless.

Dashboard at http://localhost:20128 · API at http://localhost:20128/v1.

2) Connect a FREE provider (no signup)

Dashboard → Providers → connect Kiro AI (free Claude, ~50 credits/month per account) or OpenCode Free (no auth) → done.

3) Point your coding tool

txt
Base URL: http://localhost:20128/v1
API Key:  [copy from Dashboard → Endpoints]
Model:    auto            (zero-config smart routing — or any provider/model)

4) Verify it's working

bash
curl http://localhost:20128/v1/models -H "Authorization: Bearer YOUR_KEY"

You should see your connected models listed. 🎉 That's it — start coding, and OmniRoute auto-routes & falls back for you.

If your client cannot send custom headers, OmniRoute also exposes tokenized compatibility aliases:

txt
OpenAI catalog:   http://localhost:20128/vscode/YOUR_KEY/
OpenAI models:    http://localhost:20128/vscode/YOUR_KEY/models
OpenAI chat:      http://localhost:20128/vscode/YOUR_KEY/chat/completions
OpenAI responses: http://localhost:20128/vscode/YOUR_KEY/responses
Ollama chat:      http://localhost:20128/vscode/YOUR_KEY/api/chat
Ollama tags:      http://localhost:20128/vscode/YOUR_KEY/api/tags

Use these only for clients that cannot attach Authorization: Bearer .... Header auth remains the preferred mode.

📦 More install methods — Docker, source, pnpm, Arch

🐳 Docker

bash
docker run -d --name omniroute --restart unless-stopped --stop-timeout 40 \
  -p 127.0.0.1:20128:20128 -v omniroute-data:/app/data diegosouzapw/omniroute:latest

:latest follows the highest published stable SemVer. It does not track git main. Pin :X.Y.Z for GitOps. See Docker Release Channels.

Pre-release Docker channel: diegosouzapw/omniroute:next and
diegosouzapw/omniroute:next-web follow the current default release/v*
branch. These mutable tags are intended only for testing unreleased fixes and
are not supported for production. See
Docker Release Channels.

🛠️ From source

bash
cp .env.example .env && npm install
PORT=20128 npm run dev

📦 pnpm

bash
pnpm add omniroute@latest --allow-build=better-sqlite3 --allow-build=@swc/core && omniroute

🐧 Arch Linux (AUR)

bash
yay -S omniroute-bin && systemctl --user enable --now omniroute.service

🔧 Nix (Flake)

bash
# Using Nix flakes
nix develop
npm run dev

# Or using devbox
devbox run npm run dev

📖 Docker Guide — Compose profiles, Caddy HTTPS, Cloudflare tunnels.

🦭 Podman

bash
# 1. Prepare the bind-mounted data directory
mkdir -p data

# 2. Linux + local rootless Podman only (never a remote Podman Machine client):
podman unshare chown 1000:1000 ./data

# 3. Set the runtime hint, build the local Compose image, and start
echo "CONTAINER_HOST=podman" >> .env
podman compose --profile base up -d --build

On macOS or Windows, Podman uses a remote Podman Machine: skip podman unshare and
follow the topology-specific data directory guidance.

📖 Podman Guide — Compose builds, Podman Machine, and
Linux/systemd Quadlet setup.

⚡ Faster / leaner install (skip the native build)

The native SQLite engine (better-sqlite3) is an optional dependency, so a global
install never blocks on compiling from source: it uses a prebuilt binary when one matches
your platform/Node, and otherwise falls back transparently to a pure-JS engine
(node:sqlite on Node 22+, else the bundled sql.js WASM) — no build tools required.

To skip the post-install native warm-up entirely (CI, headless, or slow machines):

bash
OMNIROUTE_SKIP_POSTINSTALL=1 npm install omniroute   # CI=1 also skips it

For the fastest installs prefer pnpm (content-addressed store + hard links — see above).
For a dashboard-free, headless runtime use the Docker base profile (above) or the
Termux guide. The CLI and the web dashboard are served by the
same process on one port, so there is no separate CLI-only package today.

📹 Video Guides

Ranking completo (v > 0, maior alcance):

#1 #2 #3 #4 #5
nick_saraev — Instagram — 1,628,910 milesreevesai — TikTok — 620,400 Vaibhav Sisinty — YouTube — 373,084 Nick Automates — YouTube Shorts — 207,714 midudev — TikTok — 177,800
#6 #7 #8 #9 #10
theopenstack — Instagram — 155,453 t.ghoush.ai — TikTok — 152,800 Valency Labs — YouTube — 135,974 Asati — YouTube — 126,130 Vaibhav Sisinty — YouTube — 122,672

Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações conhecidas · 595 perfis/canais · 13+ idiomas · 13+ criadores.

🎬 Made a video about OmniRoute? Open an issue or discussion with the link — we'll feature it here.


Layer Technology
Runtime Node.js 22.x / 24.x LTS — &gt;=22.22.2 &lt;23 &gt;=24.0.0 &lt;27
Language TypeScript 6.0 — 100% TypeScript across src/ and open-sse/ (zero any in core since v2.0)
Framework Next.js 16 + React 19 + Tailwind CSS 4
Database better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 120 domain modules, 154 migrations
Memory SQLite FTS5 full-text + int8-quantized vector embeddings, typed decay
Schemas Zod 4 — MCP tool I/O validation + API contracts
Protocols MCP (stdio / HTTP / SSE) + A2A v0.3 (JSON-RPC 2.0 + SSE)
Streaming Server-Sent Events (SSE) + WebSocket bridge (/v1/ws)
Compression 12-engine pipeline — RTK, Caveman, LLMLingua-2 (MobileBERT ONNX), GCF, OmniGlyph
Auth & security OAuth 2.0 (PKCE) + JWT + API Keys + MCP scoped auth · AES-256-GCM at rest · DOMPurify
Stealth wreq-js — JA3 / JA4 TLS fingerprint impersonation, 3-level proxy
Resilience Circuit breaker, exponential backoff, anti-thundering-herd, auto-combo self-healing
Logging pino — structured JSON logs with request context
Testing Node.js test runner + Vitest — 25,000+ test cases across 3,300+ files (unit, integration, E2E, security, ecosystem)
Platforms Desktop (Electron) · Android (Termux) · PWA (any browser)
CI/CD GitHub Actions — auto npm publish + Docker Hub on release
Links Website · npm · Docker Hub

📘 Getting Started

Document Description
User Guide Providers, combos, CLI integration, deployment
Setup Guide Full install methods, CLI tool configs, protocol setup, timeout tuning
CLI Tools Guide Per-tool setup for Claude Code, Codex, Cursor, Cline, OpenClaw, Kilo, Copilot
Remote Mode Drive a remote OmniRoute (VPS) from your laptop CLI via scoped access tokens
Claude Code Config Point Claude Code at OmniRoute (local/remote) with launch + per-model profiles
Quick Start 3-step install → connect → configure

🔧 Operations & Deployment

Document Description
Docker Guide Docker run, Compose profiles, Caddy HTTPS, tunnels, image tags
Podman Guide Quadlet systemd integration, podman-compose, SELinux
VM Deployment Complete guide: VM + nginx + Cloudflare setup
Fly.io Deployment Deploy to Fly.io with persistent storage
Termux Guide Run OmniRoute on Android via Termux
PWA Guide Progressive Web App install, caching, architecture
Uninstall Guide Clean removal for all install methods
Environment Config Complete .env variables and references

🧠 Features & Architecture

Document Description
Architecture System architecture, data flow, and internals
Compression Guide 7-option pipeline: off / lite / standard / aggressive / ultra / RTK / stacked
RTK Compression Command-output compression, filters, trust, verify, raw-output recovery
Compression Engines Caveman, RTK, stacked pipelines, dashboard/API/MCP surfaces
Compression Rules Format JSON rule-pack schemas for Caveman and RTK filters
Compression Language Packs Language detection and Caveman rule-pack authoring
Resilience Guide Circuit breakers, cooldowns, queue, anti-thundering herd, TLS spoofing
Auto-Combo Engine 14-factor scoring, mode packs, self-healing
Proxy Guide 3-level proxy system, 1proxy marketplace, registry CRUD
Free Tiers 90+ free providers consolidated directory (42 documented token pools / 495 models)
Features Gallery Visual dashboard tour with screenshots
Codebase Documentation Beginner-friendly codebase walkthrough

🤖 Protocols & APIs

Document Description
API Reference All endpoints with examples
OpenAPI Spec OpenAPI 3.0 specification
MCP Server 109 MCP tools, IDE configs, Python/TS/Go clients
MCP Server Guide MCP installation, transports, and tool reference
A2A Server JSON-RPC 2.0 protocol, skills, streaming, task mgmt
A2A Server Guide A2A agent card, tasks, skills, and streaming

📋 Project & Quality

Document Description
Contributing Development setup and guidelines
Branching & Release Model Where PRs target (release/*), what main and tags mean
Changelog Full per-version release history
Security Policy Vulnerability reporting and security practices
i18n Guide 43-language support, translation workflow, RTL
Release Checklist Pre-release validation steps
Coverage Plan Test coverage strategy and 25,000+ test suite

💖 Sponsors

How to Contribute

  1. Fork the repository
  2. Branch from the active release/vX.Y.Z tip (not main) — see Branching & Release Model
  3. Create your feature branch (git checkout -b feat/amazing-feature)
  4. Commit your changes (git commit -m 'feat: add amazing feature')
  5. Push to the branch (git push origin feat/amazing-feature)
  6. Open a Pull Request with base = that release/vX.Y.Z branch

See CONTRIBUTING.md for detailed guidelines.

Releasing a New Version

bash
# Create a release — npm publish happens automatically
gh release create v3.8.2 --title "v3.8.2" --generate-notes

OmniRoute stands on the shoulders of giants. It started as a fork of 9router and a TypeScript port of the Go project CLIProxyAPI — and from there, every subsystem below was inspired by an open-source project that got there first. Each one shaped a concrete piece of OmniRoute. This is our thank-you to all of them. 🙏

⭐ star counts as of July 2026 — go give these projects a star.

🧬 Lineage & gateway

Project ⭐ How it inspired OmniRoute
9router 22.7k The original project this fork is built on — extended here with multi-modal APIs and a full TypeScript rewrite.
CLIProxyAPI 43.6k The Go implementation that inspired this JavaScript / TypeScript port.
LiteLLM 54.0k The AI gateway whose public pricing dataset feeds our cost-tracking sync and whose provider-normalization model informed our routing.

🗜️ Context & token compression — engines

Project ⭐ How it inspired OmniRoute
Caveman 90.8k The viral "why use many token when few token do trick" project — its caveman-speak philosophy powers our standard compression mode and 30+ filler/condensation rules.
RTK – Rust Token Killer 71.8k High-performance command-output compression — inspired our RTK engine, JSON filter DSL, raw-output recovery and the stacked RTK → Caveman pipeline.
headroom 60.1k Reversible context-compression (SmartCrusher) — inspired our headroom engine and the ccr retrieve-marker pattern.
LLMLingua 6.5k Prompt-compression research (LLMLingua / LLMLingua-2) — inspired our async, code-safe, fail-open llmlingua engine.
llmlingua-2-js 30 The JS/ONNX port (MobileBERT / XLM-RoBERTa) used as the worker-thread backend for our LLMLingua engine.
Troglodita 26 PT-BR token compression — powers our pt-BR language pack: pleonasm reduction and filler removal tuned for Brazilian-Portuguese grammar.
ponytail 86.0k The viral "lazy senior dev" YAGNI-coder skill — inspired our less-code Output Style: smallest-working-change steering that cuts generated code (the output-axis sibling to Caveman's terse prose).

🧩 Compact formats, token research & code-aware tooling

Project ⭐ How it inspired OmniRoute
TOON 24.9k Token-Oriented Object Notation — its columnar, header-plus-rows model shaped our tabular compaction stage.
GCF – Graph Compact Format 22 First inspired our tabular compaction stage; now its zero-dependency, lossless generic-profile encoder is vendored directly as the Headroom codec (MIT, SPDX-marked), current with GCF spec v3.2.
token-optimizer-mcp 444 Brotli/SQLite cache + per-session context-delta — inspired our session-dedup engine.
token-savior 1.1k Bash-output compaction + MCP profiles — inspired our compression bail-out discipline and MCP tool-manifest reduction.
token-saver 117 Content-aware, per-file-type output compression with failure-aware bail-out — validated our per-type dispatch and minimum-gain skip.
token-optimizer 1.7k "Find the ghost tokens" — its offload + recoverable-handle pattern informed our CCR offload thinking.
TokenMizer 16 A session-graph + cross-turn line-dedup blueprint that informed our session-dedup design.
OmniCompress 3 Rust columnar-JSON + content-addressed retrieve + cross-message dedup — validated our headroom/ccr/session-dedup engine design and the cache-stable "compressed form is position-independent" invariant.
mcp-compressor 98 MCP tool-schema/description compression — informed our MCP tool-manifest cardinality reduction.
RepoMapper 187 Aider-style repo-map ranking — informed our repo-map / retrieval-ranking exploration.
quiet-shell-mcp 4 Declarative shell-output reduction over MCP — validated our declarative bash-output compaction.
ts-morph 6.1k TypeScript Compiler API toolkit — inspired our parser-based comment removal that preserves string, template and regex literals.

🧠 Memory & RAG

Project ⭐ How it inspired OmniRoute
Mem0 61.2k Universal memory layer — its proxy-as-write/read-boundary model shaped our memory architecture.
Letta (MemGPT) 23.9k Stateful agents with tiered memory — inspired our Context Control & Recovery (CCR) tiered model.
WFGY 1.8k The ProblemMap taxonomy of 16 recurring RAG/LLM failure modes — the shared vocabulary in our troubleshooting guide.

🛰️ Traffic inspection, MITM & transparent proxy

Project ⭐ How it inspired OmniRoute
llm-interceptor 49 MITM interception/analysis of coding-assistant ↔ LLM traffic — our Traffic Inspector ports its SSE merge, conversation normalization, host passthrough and secret masking (MIT).
ProxyBridge 5.5k Transparent per-process proxy routing — inspired our crash-safe MITM teardown, socket idle-timeouts, /proc process attribution and TPROXY capture.

📚 Model data, observability & UI

Project ⭐ How it inspired OmniRoute
models.dev 6.0k Open database of AI model specs, pricing and capabilities — synced natively into our model catalog.
React Flow / xyflow 37.7k The node-based graph library powering our real-time Compression Studio and Combo/Routing Studio.
LangGraph 37.6k LangGraph Studio's live workflow-graph visualization inspired our Studios' real-time cascade view.
Langfuse 31.4k Its trace → span → generation observability model shaped our Compression Studio waterfall.
Kiali 3.6k Istio service-mesh observability — inspired our circuit-breaker badges and error-edge visuals in the Routing/Combo Studio.
lobe-icons 2.2k AI/LLM brand logos that render the provider icons across our dashboard.

🛡️ Security

Project ⭐ How it inspired OmniRoute
awesome-secure-defaults 710 A curated list of secure-by-default libraries that guides our security choices (Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink).

🧭 Complementary tools

Project ⭐ How it inspired OmniRoute

📄 License

MIT License - see LICENSE for details.



File: docs/README.md


title: "OmniRoute Documentation" version: 3.8.40 lastUpdated: 2026-06-28

OmniRoute Documentation

Navigable index of the OmniRoute documentation set. Topics are grouped by intent so you can find what you need quickly.

Looking for the project overview, install steps, or release notes? See the root README.md, ROADMAP.md, CHANGELOG.md, and CONTRIBUTING.md.


For Non-Tech Users

Simple guides for using OmniRoute — no technical background needed.

getting-started/

guides/


For Tech Users

Technical documentation for developers and contributors.

architecture/

How the system is put together — read these to understand the runtime, code layout, and resilience model.

reference/

Lookup material — API surface, environment variables, CLI flags, provider catalog.

frameworks/

Pluggable subsystems exposed to clients, agents, and operators.

routing/

Combo routing, scoring, and replay.

security/

Guardrails, compliance, stealth, and the mandatory patterns for handling public credentials and error messages.

compression/

Prompt compression engines, rules, and language packs.

providers/

Provider-specific integration guides.

comparison/

ops/

Release, deployment, proxies, tunnels, coverage, database, monitoring.

diagrams/

Mermaid sources and exported SVG/PNG diagrams referenced from the docs above. See diagrams/README.md.

i18n/

Translated mirrors of the documentation in 43 locales. See i18n/README.md for the supported language list.

screenshots/

Static screenshots used by the dashboard and the README. Not part of the doc body.


Auto-generated artifacts

  • reference/PROVIDER_REFERENCE.md is generated by scripts/docs/gen-provider-reference.ts from src/shared/constants/providers.ts. Do not edit by hand.
  • The /docs UI is backed by Fumadocs MDX source generation from the subfolders above.