OmniRoute Dashboard # OmniRoute - Free AI Router **Never stop coding. Auto-route to FREE & cheap AI models with smart fallback.** **28 Providers β€’ Embeddings β€’ Image Generation β€’ Think Tag Parsing** **Free AI Provider for OpenClaw.**

OpenClaw

> *This project is inspired by and originally forked from [9router](https://github.com/decolua/9router) by [decolua](https://github.com/decolua). Thank you for the incredible foundation!* [![npm version](https://img.shields.io/npm/v/omniroute?color=cb3837&logo=npm)](https://www.npmjs.com/package/omniroute) [![License](https://img.shields.io/github/license/diegosouzapw/OmniRoute)](https://github.com/diegosouzapw/OmniRoute/blob/main/LICENSE) [πŸš€ Quick Start](#-quick-start) β€’ [πŸ’‘ Features](#-key-features) β€’ [πŸ“– Setup](#-setup-guide)
--- ## πŸ€” Why OmniRoute? **Stop wasting money and hitting limits:** - ❌ Subscription quota expires unused every month - ❌ Rate limits stop you mid-coding - ❌ Expensive APIs ($20-50/month per provider) - ❌ Manual switching between providers **OmniRoute solves this:** - βœ… **Maximize subscriptions** - Track quota, use every bit before reset - βœ… **Auto fallback** - Subscription β†’ Cheap β†’ Free, zero downtime - βœ… **Multi-account** - Round-robin between accounts per provider - βœ… **Universal** - Works with Claude Code, Codex, Gemini CLI, Cursor, Cline, any CLI tool --- ## πŸ”„ How It Works ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Your CLI β”‚ (Claude Code, Codex, Gemini CLI, OpenClaw, Cursor, Cline...) β”‚ Tool β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚ http://localhost:20128/v1 ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ OmniRoute (Smart Router) β”‚ β”‚ β€’ Format translation (OpenAI ↔ Claude) β”‚ β”‚ β€’ Quota tracking + Embeddings + Images β”‚ β”‚ β€’ Auto token refresh β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”œβ”€β†’ [Tier 1: SUBSCRIPTION] Claude Code, Codex, Gemini CLI β”‚ ↓ quota exhausted β”œβ”€β†’ [Tier 2: API KEY] DeepSeek, Groq, xAI, Mistral, Together, etc. β”‚ ↓ budget limit β”œβ”€β†’ [Tier 3: CHEAP] GLM ($0.6/1M), MiniMax ($0.2/1M) β”‚ ↓ budget limit └─→ [Tier 4: FREE] iFlow, Qwen, Kiro (unlimited) Result: Never stop coding, minimal cost ``` --- ## ⚑ Quick Start **1. Install globally:** ```bash npm install -g omniroute omniroute ``` πŸŽ‰ Dashboard opens at `http://localhost:20128` **CLI Options:** | Command | Description | | ----------------------- | --------------------------------- | | `omniroute` | Start server (default port 20128) | | `omniroute --port 3000` | Use custom port | | `omniroute --no-open` | Don't auto-open browser | | `omniroute --help` | Show help | | `omniroute --version` | Show version | **2. Connect a FREE provider (no signup needed):** Dashboard β†’ Providers β†’ Connect **Claude Code** or **Antigravity** β†’ OAuth login β†’ Done! **3. Use in your CLI tool:** ``` Claude Code/Codex/Gemini CLI/OpenClaw/Cursor/Cline Settings: Endpoint: http://localhost:20128/v1 API Key: [copy from dashboard] Model: if/kimi-k2-thinking ``` **That's it!** Start coding with FREE AI models. **Alternative: run from source (this repository):** ```bash cp .env.example .env npm install PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev ``` Production mode: ```bash npm run build PORT=20128 HOSTNAME=0.0.0.0 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run start ``` Default URLs: - Dashboard: `http://localhost:20128/dashboard` - OpenAI-compatible API: `http://localhost:20128/v1` --- ## πŸ’‘ Key Features | Feature | What It Does | Why It Matters | | -------------------------------- | ------------------------------------------ | ----------------------------------- | | 🎯 **Smart 3-Tier Fallback** | Auto-route: Subscription β†’ Cheap β†’ Free | Never stop coding, zero downtime | | πŸ“Š **Real-Time Quota Tracking** | Live token count + reset countdown | Maximize subscription value | | πŸ”„ **Format Translation** | OpenAI ↔ Claude ↔ Gemini seamless | Works with any CLI tool | | πŸ‘₯ **Multi-Account Support** | Multiple accounts per provider | Load balancing + redundancy | | πŸ”„ **Auto Token Refresh** | OAuth tokens refresh automatically | No manual re-login needed | | 🎨 **Custom Combos** | Create unlimited model combinations | Tailor fallback to your needs | | 🧩 **Custom Models** | Add any model ID to any provider | No app update needed for new models | | πŸ›£οΈ **Dedicated Provider Routes** | Per-provider API endpoints | Direct routing, model validation | | 🌐 **Network Proxy** | Hierarchical outbound proxy + env fallback | Works behind firewalls/VPNs | | πŸ“‹ **Model Catalog API** | All models grouped by provider + type | Discover available models easily | | πŸ“ **Request Logging** | Debug mode with full request/response logs | Troubleshoot issues easily | | πŸ’Ύ **Cloud Sync** | Sync config across devices | Same setup everywhere | | πŸ“Š **Usage Analytics** | Track tokens, cost, trends over time | Optimize spending | | 🌐 **Deploy Anywhere** | Localhost, VPS, Docker, Cloudflare Workers | Flexible deployment options | | πŸ›‘οΈ **IP Allowlist/Blocklist** | Restrict API access by IP address | Security for exposed deployments | | 🧠 **Thinking Budget** | Control reasoning token budget per model | Optimize cost vs quality | | πŸ’¬ **System Prompt Injection** | Global system prompt for all requests | Consistent behavior across models | | πŸ“Š **Session Tracking** | Track active sessions with fingerprinting | Monitor connected clients | | ⚑ **Rate Limiting** | Per-account request rate management | Prevent abuse and quota waste | | πŸ’° **Model Pricing** | Per-model cost tracking and calculation | Precise usage cost analytics |
πŸ“– Feature Details ### 🎯 Smart 3-Tier Fallback Create combos with automatic fallback: ``` Combo: "my-coding-stack" 1. cc/claude-opus-4-6 (your subscription) 2. glm/glm-4.7 (cheap backup, $0.6/1M) 3. if/kimi-k2-thinking (free fallback) β†’ Auto switches when quota runs out or errors occur ``` ### πŸ“Š Real-Time Quota Tracking - Token consumption per provider - Reset countdown (5-hour, daily, weekly) - Cost estimation for paid tiers - Monthly spending reports ### πŸ”„ Format Translation Seamless translation between formats: - **OpenAI** ↔ **Claude** ↔ **Gemini** ↔ **OpenAI Responses** - Your CLI tool sends OpenAI format β†’ OmniRoute translates β†’ Provider receives native format - Works with any tool that supports custom OpenAI endpoints ### πŸ‘₯ Multi-Account Support - Add multiple accounts per provider - Auto round-robin or priority-based routing - Fallback to next account when one hits quota ### πŸ”„ Auto Token Refresh - OAuth tokens automatically refresh before expiration - No manual re-authentication needed - Seamless experience across all providers ### 🎨 Custom Combos - Create unlimited model combinations - Mix subscription, cheap, and free tiers - Name your combos for easy access - Share combos across devices with Cloud Sync ### πŸ“ Request Logging - Enable debug mode for full request/response logs - Track API calls, headers, and payloads - Troubleshoot integration issues - Export logs for analysis ### πŸ’Ύ Cloud Sync - Sync providers, combos, and settings across devices - Automatic background sync - Secure encrypted storage - Access your setup from anywhere #### Cloud Runtime Notes - Prefer server-side cloud variables in production: - `BASE_URL` (internal callback URL used by sync scheduler) - `CLOUD_URL` (cloud sync endpoint base) - `NEXT_PUBLIC_BASE_URL` and `NEXT_PUBLIC_CLOUD_URL` are still supported for compatibility/UI, but server runtime now prioritizes `BASE_URL`/`CLOUD_URL`. - Cloud sync requests now use timeout + fail-fast behavior to avoid UI hanging when cloud DNS/network is unavailable. ### πŸ“Š Usage Analytics - Track token usage per provider and model - Cost estimation and spending trends - Monthly reports and insights - Optimize your AI spending ### 🌐 Deploy Anywhere - πŸ’» **Localhost** - Default, works offline - ☁️ **VPS/Cloud** - Share across devices - 🐳 **Docker** - One-command deployment - πŸš€ **Cloudflare Workers** - Global edge network
--- ## πŸ’° Pricing at a Glance | Tier | Provider | Cost | Quota Reset | Best For | | ------------------- | ----------------- | ----------- | ---------------- | -------------------- | | **πŸ’³ SUBSCRIPTION** | Claude Code (Pro) | $20/mo | 5h + weekly | Already subscribed | | | Codex (Plus/Pro) | $20-200/mo | 5h + weekly | OpenAI users | | | Gemini CLI | **FREE** | 180K/mo + 1K/day | Everyone! | | | GitHub Copilot | $10-19/mo | Monthly | GitHub users | | **πŸ”‘ API KEY** | DeepSeek | Pay per use | None | Cheap reasoning | | | Groq | Pay per use | None | Ultra-fast inference | | | xAI (Grok) | Pay per use | None | Grok 4 reasoning | | | Mistral | Pay per use | None | EU-hosted models | | | Perplexity | Pay per use | None | Search-augmented | | | Together AI | Pay per use | None | Open-source models | | | Fireworks AI | Pay per use | None | Fast FLUX images | | | Cerebras | Pay per use | None | Wafer-scale speed | | | Cohere | Pay per use | None | Command R+ RAG | | | NVIDIA NIM | Pay per use | None | Enterprise models | | **πŸ’° CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup | | | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option | | | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost | | **πŸ†“ FREE** | iFlow | $0 | Unlimited | 8 models free | | | Qwen | $0 | Unlimited | 3 models free | | | Kiro | $0 | Unlimited | Claude free | **πŸ’‘ Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost! --- ## 🎯 Use Cases ### Case 1: "I have Claude Pro subscription" **Problem:** Quota expires unused, rate limits during heavy coding **Solution:** ``` Combo: "maximize-claude" 1. cc/claude-opus-4-6 (use subscription fully) 2. glm/glm-4.7 (cheap backup when quota out) 3. if/kimi-k2-thinking (free emergency fallback) Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total vs. $20 + hitting limits = frustration ``` ### Case 2: "I want zero cost" **Problem:** Can't afford subscriptions, need reliable AI coding **Solution:** ``` Combo: "free-forever" 1. gc/gemini-3-flash (180K free/month) 2. if/kimi-k2-thinking (unlimited free) 3. qw/qwen3-coder-plus (unlimited free) Monthly cost: $0 Quality: Production-ready models ``` ### Case 3: "I need 24/7 coding, no interruptions" **Problem:** Deadlines, can't afford downtime **Solution:** ``` Combo: "always-on" 1. cc/claude-opus-4-6 (best quality) 2. cx/gpt-5.2-codex (second subscription) 3. glm/glm-4.7 (cheap, resets daily) 4. minimax/MiniMax-M2.1 (cheapest, 5h reset) 5. if/kimi-k2-thinking (free unlimited) Result: 5 layers of fallback = zero downtime Monthly cost: $20-200 (subscriptions) + $10-20 (backup) ``` ### Case 4: "I want FREE AI in OpenClaw" **Problem:** Need AI assistant in messaging apps (WhatsApp, Telegram, Slack...), completely free **Solution:** ``` Combo: "openclaw-free" 1. if/glm-4.7 (unlimited free) 2. if/minimax-m2.1 (unlimited free) 3. if/kimi-k2-thinking (unlimited free) Monthly cost: $0 Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal... ``` --- ## πŸ“– Setup Guide
πŸ” Subscription Providers (Maximize Value) ### Claude Code (Pro/Max) ```bash Dashboard β†’ Providers β†’ Connect Claude Code β†’ OAuth login β†’ Auto token refresh β†’ 5-hour + weekly quota tracking Models: cc/claude-opus-4-6 cc/claude-sonnet-4-5-20250929 cc/claude-haiku-4-5-20251001 ``` **Pro Tip:** Use Opus for complex tasks, Sonnet for speed. OmniRoute tracks quota per model! ### OpenAI Codex (Plus/Pro) ```bash Dashboard β†’ Providers β†’ Connect Codex β†’ OAuth login (port 1455) β†’ 5-hour + weekly reset Models: cx/gpt-5.2-codex cx/gpt-5.1-codex-max ``` ### Gemini CLI (FREE 180K/month!) ```bash Dashboard β†’ Providers β†’ Connect Gemini CLI β†’ Google OAuth β†’ 180K completions/month + 1K/day Models: gc/gemini-3-flash-preview gc/gemini-2.5-pro ``` **Best Value:** Huge free tier! Use this before paid tiers. ### GitHub Copilot ```bash Dashboard β†’ Providers β†’ Connect GitHub β†’ OAuth via GitHub β†’ Monthly reset (1st of month) Models: gh/gpt-5 gh/claude-4.5-sonnet gh/gemini-3-pro ```
πŸ’° Cheap Providers (Backup) ### GLM-4.7 (Daily reset, $0.6/1M) 1. Sign up: [Zhipu AI](https://open.bigmodel.cn/) 2. Get API key from Coding Plan 3. Dashboard β†’ Add API Key: - Provider: `glm` - API Key: `your-key` **Use:** `glm/glm-4.7` **Pro Tip:** Coding Plan offers 3Γ— quota at 1/7 cost! Reset daily 10:00 AM. ### MiniMax M2.1 (5h reset, $0.20/1M) 1. Sign up: [MiniMax](https://www.minimax.io/) 2. Get API key 3. Dashboard β†’ Add API Key **Use:** `minimax/MiniMax-M2.1` **Pro Tip:** Cheapest option for long context (1M tokens)! ### Kimi K2 ($9/month flat) 1. Subscribe: [Moonshot AI](https://platform.moonshot.ai/) 2. Get API key 3. Dashboard β†’ Add API Key **Use:** `kimi/kimi-latest` **Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!
πŸ†“ FREE Providers (Emergency Backup) ### iFlow (8 FREE models) ```bash Dashboard β†’ Connect iFlow β†’ iFlow OAuth login β†’ Unlimited usage Models: if/kimi-k2-thinking if/qwen3-coder-plus if/glm-4.7 if/minimax-m2 if/deepseek-r1 ``` ### Qwen (3 FREE models) ```bash Dashboard β†’ Connect Qwen β†’ Device code authorization β†’ Unlimited usage Models: qw/qwen3-coder-plus qw/qwen3-coder-flash ``` ### Kiro (Claude FREE) ```bash Dashboard β†’ Connect Kiro β†’ AWS Builder ID or Google/GitHub β†’ Unlimited usage Models: kr/claude-sonnet-4.5 kr/claude-haiku-4.5 ```
🎨 Create Combos ### Example 1: Maximize Subscription β†’ Cheap Backup ``` Dashboard β†’ Combos β†’ Create New Name: premium-coding Models: 1. cc/claude-opus-4-6 (Subscription primary) 2. glm/glm-4.7 (Cheap backup, $0.6/1M) 3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M) Use in CLI: premium-coding Monthly cost example (100M tokens): 80M via Claude (subscription): $0 extra 15M via GLM: $9 5M via MiniMax: $1 Total: $10 + your subscription ``` ### Example 2: Free-Only (Zero Cost) ``` Name: free-combo Models: 1. gc/gemini-3-flash-preview (180K free/month) 2. if/kimi-k2-thinking (unlimited) 3. qw/qwen3-coder-plus (unlimited) Cost: $0 forever! ```
πŸ”§ CLI Integration ### Cursor IDE ``` Settings β†’ Models β†’ Advanced: OpenAI API Base URL: http://localhost:20128/v1 OpenAI API Key: [from omniroute dashboard] Model: cc/claude-opus-4-6 ``` Or use combo: `premium-coding` ### Claude Code Edit `~/.claude/config.json`: ```json { "anthropic_api_base": "http://localhost:20128/v1", "anthropic_api_key": "your-omniroute-api-key" } ``` ### Codex CLI ```bash export OPENAI_BASE_URL="http://localhost:20128" export OPENAI_API_KEY="your-omniroute-api-key" codex "your prompt" ``` ### OpenClaw Edit `~/.openclaw/openclaw.json`: ```json { "agents": { "defaults": { "model": { "primary": "omniroute/if/glm-4.7" } } }, "models": { "providers": { "omniroute": { "baseUrl": "http://localhost:20128/v1", "apiKey": "your-omniroute-api-key", "api": "openai-completions", "models": [ { "id": "if/glm-4.7", "name": "glm-4.7" } ] } } } } ``` **Or use Dashboard:** CLI Tools β†’ OpenClaw β†’ Auto-config ### Cline / Continue / RooCode ``` Provider: OpenAI Compatible Base URL: http://localhost:20128/v1 API Key: [from dashboard] Model: cc/claude-opus-4-6 ```
πŸš€ Deployment ### VPS Deployment ```bash # Clone and install git clone https://github.com/diegosouzapw/OmniRoute.git cd OmniRoute npm install npm run build # Configure export JWT_SECRET="your-secure-secret-change-this" export INITIAL_PASSWORD="your-password" export DATA_DIR="/var/lib/omniroute" export PORT="20128" export HOSTNAME="0.0.0.0" export NODE_ENV="production" export NEXT_PUBLIC_BASE_URL="http://localhost:20128" export NEXT_PUBLIC_CLOUD_URL="https://omniroute.dev" export API_KEY_SECRET="endpoint-proxy-api-key-secret" export MACHINE_ID_SALT="endpoint-proxy-salt" # Start npm run start # Or use PM2 npm install -g pm2 pm2 start npm --name omniroute -- start pm2 save pm2 startup ``` ### Docker ```bash # Build image (default target = runner-cli with codex/claude/droid preinstalled) docker build -t omniroute:cli . # Build minimal image without bundled CLIs docker build --target runner-base -t omniroute:base . # Build explicit CLI profile docker build --target runner-cli -t omniroute:cli . ``` Portable mode (recommended for Docker Desktop and generic hosts): ```bash docker run -d \ --name omniroute \ -p 20128:20128 \ --env-file ./.env \ -v omniroute-data:/app/data \ omniroute:cli ``` Host-integrated mode (Linux-first; use host mounts for CLI bins/configs): Host prerequisites example (real host binaries): ```bash # Install host CLIs (example) npm install -g @openai/codex @anthropic-ai/claude-code droid openclaw@latest cline @continuedev/cli ``` Run using host-mounted CLIs (`codex` from host tool dir + npm global CLIs from Node root): ```bash docker run -d \ --name omniroute \ -p 20128:20128 \ --env-file ./.env \ -e CLI_MODE=host \ -e CLI_EXTRA_PATHS=/host-local/bin:/host-node/bin:/host-codex \ -e CLI_CURSOR_BIN=agent \ -e CLI_CLINE_BIN=cline \ -e CLI_CONTINUE_BIN=cn \ -e CLI_CONFIG_HOME=/host-home \ -e CLI_ALLOW_CONFIG_WRITES=true \ -v ~/.local/bin:/host-local/bin:ro \ -v ~/.nvm/versions/node/v22.16.0:/host-node:ro \ -v /path/to/host/codex/bin:/host-codex:ro \ -v ~/.codex:/host-home/.codex:rw \ -v ~/.claude:/host-home/.claude:rw \ -v ~/.factory:/host-home/.factory:rw \ -v ~/.openclaw:/host-home/.openclaw:rw \ -v ~/.cursor:/host-home/.cursor:rw \ -v ~/.config/cursor:/host-home/.config/cursor:rw \ -v omniroute-data:/app/data \ omniroute:base ``` Notes: - `runner-cli` currently bundles `@openai/codex`, `@anthropic-ai/claude-code`, `droid`, and `openclaw@latest`. - `runner-cli` uses Node 22 Debian slim to satisfy OpenClaw runtime requirements. - Host CLI mount mode is Linux-first. On Docker Desktop (Mac/Windows), prefer `runner-cli`. - `Continue CLI` executable is usually `cn`, so set `CLI_CONTINUE_BIN=cn` in host mode. - `Cursor Agent` executable is commonly `agent` in `~/.local/bin`, so set `CLI_CURSOR_BIN=agent` and include that directory in `CLI_EXTRA_PATHS`. - Cursor auth/config typically live in `~/.config/cursor` and `~/.cursor`; mount both for host-integrated mode. Quick runtime validation: ```bash curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}' curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}' curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}' curl -s http://localhost:20128/api/cli-tools/runtime/cursor | jq '{installed,runnable,command,commandPath,configPath,runtimeMode,reason}' curl -s http://localhost:20128/api/cli-tools/runtime/cline | jq '{installed,runnable,commandPath,runtimeMode,reason}' curl -s http://localhost:20128/api/cli-tools/runtime/continue | jq '{installed,runnable,commandPath,runtimeMode,reason}' ``` Container defaults: - `PORT=20128` - `HOSTNAME=0.0.0.0` Useful commands: ```bash docker logs -f omniroute docker restart omniroute docker stop omniroute && docker rm omniroute ``` ### Environment Variables | Variable | Default | Description | | ---------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------- | | `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret for dashboard auth cookie (**change in production**) | | `INITIAL_PASSWORD` | `123456` | First login password when no saved hash exists | | `DATA_DIR` | `~/.omniroute` | Primary data directory (`db.json`, `usage.json`, `log.txt`, `call_logs/`) | | `XDG_CONFIG_HOME` | unset | Optional base dir on Linux/macOS when `DATA_DIR` is unset (`$XDG_CONFIG_HOME/omniroute`) | | `PORT` | framework default | Service port (`20128` in examples) | | `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) | | `NODE_ENV` | runtime default | Set `production` for deploy | | `BASE_URL` | `http://localhost:20128` | Server-side internal base URL used by cloud sync jobs | | `CLOUD_URL` | `https://omniroute.dev` | Server-side cloud sync endpoint base URL | | `NEXT_PUBLIC_BASE_URL` | `http://localhost:3000` | Backward-compatible/public base URL (prefer `BASE_URL` for server runtime) | | `NEXT_PUBLIC_CLOUD_URL` | `https://omniroute.dev` | Backward-compatible/public cloud URL (prefer `CLOUD_URL` for server runtime) | | `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys | | `MACHINE_ID_SALT` | `endpoint-proxy-salt` | Salt for stable machine ID hashing | | `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs under `logs/` | | `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (set `true` behind HTTPS reverse proxy) | | `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` routes (recommended for internet-exposed deploys) | | `ENABLE_SOCKS5_PROXY` | `false` | Enables backend/runtime SOCKS5 support for outbound proxy | | `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY` | `false` | Shows SOCKS5 option in dashboard proxy UI | | `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE` | `false` | Allow multiple connections for each OpenAI/Anthropic-compatible custom node | | `CLI_MODE` | `auto` | CLI runtime profile: `auto`, `host`, or `container` | | `CLI_EXTRA_PATHS` | empty | Extra `PATH` entries used for CLI detection/healthcheck (split by `:` on Linux) | | `CLI_CONFIG_HOME` | runtime home (`os.homedir`) | Base directory used to read/write CLI config files | | `CLI_ALLOW_CONFIG_WRITES` | `true` | If `false`, `/api/cli-tools/*` `POST`/`DELETE` return `403` | | `CLI_CLAUDE_BIN` | `claude` | Override command/path used for Claude CLI detection | | `CLI_CODEX_BIN` | `codex` | Override command/path used for Codex CLI detection | | `CLI_DROID_BIN` | `droid` | Override command/path used for Droid CLI detection | | `CLI_OPENCLAW_BIN` | `openclaw` | Override command/path used for OpenClaw CLI detection | | `CLI_CURSOR_BIN` | `agent` | Override command/path used for Cursor Agent detection (`agent`, fallback `cursor`) | | `CLI_CLINE_BIN` | empty | Optional override for Cline runtime detection (set `cline` if you have local CLI) | | `CLI_ROO_BIN` | empty | Optional override for Roo runtime detection | | `CLI_CONTINUE_BIN` | empty | Optional override for Continue runtime detection (commonly `cn`) | | `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` | empty | Optional outbound proxy for upstream provider calls | Notes: - Lowercase proxy variables are also supported: `http_proxy`, `https_proxy`, `all_proxy`, `no_proxy`. - `.env` is not baked into Docker image (`.dockerignore`); inject runtime config with `--env-file` or `-e`. - On Windows, `APPDATA` can be used for local storage path resolution. - `CLI_EXTRA_PATHS` uses the platform delimiter (`:` on Linux/macOS, `;` on Windows). - `INSTANCE_NAME` appears in older docs/env templates, but is currently not used at runtime. ### Runtime Files and Storage - Main app state: `${DATA_DIR}/db.json` (providers, combos, aliases, keys, settings), managed by `src/lib/localDb.js`. - Usage history and logs: `${DATA_DIR}/usage.json`, `${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, managed by `src/lib/usageDb.js`. - Optional request/translator logs: `/logs/...` when `ENABLE_REQUEST_LOGS=true`. - Legacy files under `~/.omniroute` are migrated automatically when `DATA_DIR` (or `XDG_CONFIG_HOME`) points to a different location.
--- ## πŸ“Š Available Models
View all available models **Claude Code (`cc/`)** - Pro/Max: - `cc/claude-opus-4-6` - `cc/claude-sonnet-4-5-20250929` - `cc/claude-haiku-4-5-20251001` **Codex (`cx/`)** - Plus/Pro: - `cx/gpt-5.2-codex` - `cx/gpt-5.1-codex-max` **Gemini CLI (`gc/`)** - FREE: - `gc/gemini-3-flash-preview` - `gc/gemini-2.5-pro` **GitHub Copilot (`gh/`)**: - `gh/gpt-5` - `gh/claude-4.5-sonnet` **GLM (`glm/`)** - $0.6/1M: - `glm/glm-4.7` **MiniMax (`minimax/`)** - $0.2/1M: - `minimax/MiniMax-M2.1` **iFlow (`if/`)** - FREE: - `if/kimi-k2-thinking` - `if/qwen3-coder-plus` - `if/deepseek-r1` **Qwen (`qw/`)** - FREE: - `qw/qwen3-coder-plus` - `qw/qwen3-coder-flash` **Kiro (`kr/`)** - FREE: - `kr/claude-sonnet-4.5` - `kr/claude-haiku-4.5` **DeepSeek (`ds/`)** - API Key: - `ds/deepseek-chat` - `ds/deepseek-reasoner` **Groq (`groq/`)** - API Key: - `groq/llama-3.3-70b-versatile` - `groq/llama-4-maverick-17b-128e-instruct` - `groq/qwen-qwq-32b` - `groq/gpt-oss-120b` **xAI (`xai/`)** - API Key: - `xai/grok-4` - `xai/grok-4-0709-fast-reasoning` - `xai/grok-code-mini` - `xai/grok-3-beta` **Mistral (`mistral/`)** - API Key: - `mistral/mistral-large-2501` - `mistral/codestral-2501` - `mistral/mistral-medium-2505` **Perplexity (`pplx/`)** - API Key: - `pplx/sonar-pro` - `pplx/sonar` **Together AI (`together/`)** - API Key: - `together/meta-llama/Llama-3.3-70B-Instruct-Turbo` - `together/deepseek-ai/DeepSeek-R1` - `together/Qwen/Qwen3-235B-A22B` **Fireworks AI (`fireworks/`)** - API Key: - `fireworks/accounts/fireworks/models/deepseek-v3p1` - `fireworks/accounts/fireworks/models/llama-v3p3-70b-instruct` **Cerebras (`cerebras/`)** - API Key: - `cerebras/llama-3.3-70b` - `cerebras/llama-4-scout-17b-16e-instruct` - `cerebras/qwen-3-32b` **Cohere (`cohere/`)** - API Key: - `cohere/command-r-plus-08-2024` - `cohere/command-a-03-2025` **NVIDIA NIM (`nvidia/`)** - API Key: - `nvidia/nvidia/llama-3.3-70b-instruct` - `nvidia/deepseek/deepseek-r1`
--- ## 🧩 Advanced Features
Custom Models Add any model ID to any provider without waiting for an app update: ```bash # Via API curl -X POST http://localhost:20128/api/provider-models \ -H "Content-Type: application/json" \ -d '{"provider": "openai", "modelId": "gpt-4.5-preview", "modelName": "GPT-4.5 Preview"}' # List custom models curl http://localhost:20128/api/provider-models?provider=openai # Remove curl -X DELETE "http://localhost:20128/api/provider-models?provider=openai&model=gpt-4.5-preview" ``` Or use the Dashboard: **Providers β†’ [Provider] β†’ Custom Models** section. Custom models appear in `/v1/models` with `custom: true` flag.
Dedicated Provider Routes Route requests directly to a specific provider with model validation: ```bash # Chat completions for a specific provider curl -X POST http://localhost:20128/v1/providers/openai/chat/completions \ -H "Content-Type: application/json" \ -d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "Hello"}]}' # Embeddings for a specific provider curl -X POST http://localhost:20128/v1/providers/openai/embeddings \ -H "Content-Type: application/json" \ -d '{"model": "text-embedding-3-small", "input": "Hello world"}' # Image generation for a specific provider curl -X POST http://localhost:20128/v1/providers/fireworks/images/generations \ -H "Content-Type: application/json" \ -d '{"model": "flux-1-schnell", "prompt": "A sunset over the ocean"}' ``` The provider prefix is auto-added if missing. Mismatched models return `400`.
Network Proxy Configuration Configure outbound proxies globally, or per-provider via structured proxy objects: ```bash # Set global proxy curl -X PUT http://localhost:20128/api/settings/proxy \ -H "Content-Type: application/json" \ -d '{"global": {"type":"http","host":"proxy.example.com","port":"8080"}}' # Set per-provider proxy curl -X PUT http://localhost:20128/api/settings/proxy \ -H "Content-Type: application/json" \ -d '{"providers": {"openai": {"type":"socks5","host":"proxy.example.com","port":"1080"}}}' # Test a proxy before saving curl -X POST http://localhost:20128/api/settings/proxy/test \ -H "Content-Type: application/json" \ -d '{"proxy":{"type":"socks5","host":"proxy.example.com","port":"1080"}}' # Get current config curl http://localhost:20128/api/settings/proxy ``` Notes: - SOCKS5 is feature-flagged. Enable backend/runtime with `ENABLE_SOCKS5_PROXY=true`. - To display SOCKS5 in the dashboard UI, also set `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true`. - Requests are fail-closed when a configured proxy fails (no direct-connection fallback). **Precedence:** Key-specific β†’ Combo-specific β†’ Provider-specific β†’ Global β†’ Environment (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`).
Model Catalog API Get all available models grouped by provider with type metadata: ```bash curl http://localhost:20128/api/models/catalog ``` Returns: ```json { "catalog": { "openai": { "provider": "OpenAI", "active": true, "models": [ { "id": "openai/gpt-4o", "name": "GPT-4o", "type": "chat", "custom": false }, { "id": "openai/text-embedding-3-small", "type": "embedding", "custom": false } ] } } } ``` Types: `chat`, `embedding`, `image`. Custom models are flagged with `custom: true`.
--- ## πŸ› Troubleshooting **"Language model did not provide messages"** - Provider quota exhausted β†’ Check dashboard quota tracker - Solution: Use combo fallback or switch to cheaper tier **Rate limiting** - Subscription quota out β†’ Fallback to GLM/MiniMax - Add combo: `cc/claude-opus-4-6 β†’ glm/glm-4.7 β†’ if/kimi-k2-thinking` **OAuth token expired** - Auto-refreshed by OmniRoute - If issues persist: Dashboard β†’ Provider β†’ Reconnect **High costs** - Check usage stats in Dashboard - Switch primary model to GLM/MiniMax - Use free tier (Gemini CLI, iFlow) for non-critical tasks **Dashboard opens on wrong port** - Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` **Cloud sync errors** - Verify `BASE_URL` points to your running instance (example: `http://localhost:20128`) - Verify `CLOUD_URL` points to your expected cloud endpoint (example: `https://omniroute.dev`) - Keep `NEXT_PUBLIC_*` values aligned with server-side values when possible. **Cloud endpoint `stream=false` returns 500 (`Unexpected token 'd'...`)** - Symptom usually appears on public cloud endpoint (`https://omniroute.dev/v1`) for non-streaming calls. - Root cause: upstream returns SSE payload (`data: ...`) while client expects JSON. - Workaround: use `stream=true` for cloud direct calls. - Local OmniRoute runtime includes SSEβ†’JSON fallback for non-streaming calls when upstream returns `text/event-stream`. **Cloud says connected, but request still fails with `Invalid API key`** - Create a fresh key from local dashboard (`/api/keys`) and run cloud sync (`Enable Cloud` then `Sync Now`). - Old/non-synced keys can still return `401` on cloud even if local endpoint works. **CLI tool shows not installed inside Docker** - Check runtime fields from `/api/cli-tools/*` (`installed`, `runnable`, `reason`, `commandPath`). - For portable mode, use image target `runner-cli` (bundled `codex`/`claude`/`droid`). - For host mount mode, set `CLI_EXTRA_PATHS` and mount host bin directory as read-only. - If `installed=true` and `runnable=false`, binary was found but failed healthcheck. **First login not working** - Check `INITIAL_PASSWORD` in `.env` - If unset, fallback password is `123456` **No request logs under `logs/`** - Set `ENABLE_REQUEST_LOGS=true` --- ## πŸ› οΈ Tech Stack - **Runtime**: Node.js 20+ - **Framework**: Next.js 16 - **UI**: React 19 + Tailwind CSS 4 - **Charts**: Recharts (SVG, accessible) - **Database**: LowDB (JSON file-based) - **Streaming**: Server-Sent Events (SSE) - **Auth**: OAuth 2.0 (PKCE) + JWT + API Keys - **Testing**: Playwright (E2E) + Node.js test runner (unit) - **Monorepo**: npm workspaces (`@omniroute/open-sse`) - **CI/CD**: GitHub Actions (auto npm publish on release) + Dependabot - **Package**: [npmjs.com/package/omniroute](https://www.npmjs.com/package/omniroute) - **Compliance**: `/terms` and `/privacy` pages --- ## πŸ“ API Reference ### Chat Completions ```bash POST http://localhost:20128/v1/chat/completions Authorization: Bearer your-api-key Content-Type: application/json { "model": "cc/claude-opus-4-6", "messages": [ {"role": "user", "content": "Write a function to..."} ], "stream": true } ``` ### Embeddings ```bash POST http://localhost:20128/v1/embeddings Authorization: Bearer your-api-key Content-Type: application/json { "model": "nebius/Qwen/Qwen3-Embedding-8B", "input": "The food was delicious" } ``` Available embedding providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA. ```bash # List all embedding models GET http://localhost:20128/v1/embeddings ``` ### Image Generation ```bash POST http://localhost:20128/v1/images/generations Authorization: Bearer your-api-key Content-Type: application/json { "model": "openai/dall-e-3", "prompt": "A beautiful sunset over mountains", "size": "1024x1024" } ``` Available image providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI. ```bash # List all image models GET http://localhost:20128/v1/images/generations ``` ### List Models ```bash GET http://localhost:20128/v1/models Authorization: Bearer your-api-key β†’ Returns all chat, embedding, and image models + combos in OpenAI format ``` ### Compatibility Endpoints - `POST /v1/chat/completions` - `POST /v1/messages` - `POST /v1/responses` - `POST /v1/embeddings` (**NEW**) - `POST /v1/images/generations` (**NEW**) - `GET /v1/models` (chat + embedding + image) - `POST /v1/messages/count_tokens` - `GET /v1beta/models` - `POST /v1beta/models/{...path}` (Gemini-style `generateContent`) - `POST /v1/api/chat` (Ollama-style transform path) ### Cloud Validation Scripts Added test scripts under `tester/security/`: - `tester/security/test-docker-hardening.sh` - Builds Docker image and validates hardening checks (`/api/cloud/auth` auth guard, `REQUIRE_API_KEY`, secure auth cookie behavior). - `tester/security/test-cloud-openai-compatible.sh` - Sends a direct OpenAI-compatible request to cloud endpoint (`https://omniroute.dev/v1/chat/completions`) with provided model/key. - `tester/security/test-cloud-sync-and-call.sh` - End-to-end flow: create local key -> enable/sync cloud -> call cloud endpoint with retry. - Includes fallback check with `stream=true` to distinguish auth errors from non-streaming parse issues. - `tester/security/test-cli-runtime.sh` - Validates Docker CLI runtime profiles (`runner-base`, `runner-cli`, host mount mode, write policy, non-executable regression). Security note for cloud test scripts: - Never hardcode real API keys in scripts/commits. - Provide keys only via environment variables: - `API_KEY`, `CLOUD_API_KEY`, or `OPENAI_API_KEY` (supported by `test-cloud-openai-compatible.sh`) - Example: ```bash OPENAI_API_KEY="your-cloud-key" bash tester/security/test-cloud-openai-compatible.sh ``` Expected behavior from recent validation: - Local runtime (`http://127.0.0.1:20128/v1/chat/completions`): works with `stream=false` and `stream=true`. - Docker runtime (same API path exposed by container): hardening checks pass, cloud auth guard works, strict API key mode works when enabled. - Public cloud endpoint (`https://omniroute.dev/v1/chat/completions`): - `stream=true`: expected to succeed (SSE chunks returned). - `stream=false`: may fail with `500` + parse error (`Unexpected token 'd'`) when upstream returns SSE content to a non-streaming client path. ### Dashboard and Management API - Auth/settings: `/api/auth/login`, `/api/auth/logout`, `/api/settings`, `/api/settings/require-login` - Provider management: `/api/providers`, `/api/providers/[id]`, `/api/providers/[id]/test`, `/api/providers/[id]/models`, `/api/providers/validate`, `/api/provider-nodes*` - OAuth flows: `/api/oauth/[provider]/[action]` (+ provider-specific imports like Cursor/Kiro) - Routing config: `/api/models/alias`, `/api/combos*`, `/api/keys*`, `/api/pricing` - Usage/logs: `/api/usage/history`, `/api/usage/logs`, `/api/usage/request-logs`, `/api/usage/[connectionId]` - Cloud sync: `/api/sync/cloud`, `/api/sync/initialize`, `/api/cloud/*` - IP filter: `/api/settings/ip-filter` (GET/PUT) β€” Allowlist/blocklist management - Thinking budget: `/api/settings/thinking-budget` (GET/PUT) β€” Reasoning token budget config - System prompt: `/api/settings/system-prompt` (GET/PUT) β€” Global system prompt injection - Sessions: `/api/sessions` (GET) β€” Active session tracking - Rate limits: `/api/rate-limits` (GET) β€” Per-account rate limit status - CLI helpers: `/api/cli-tools/claude-settings`, `/api/cli-tools/codex-settings`, `/api/cli-tools/droid-settings`, `/api/cli-tools/openclaw-settings` - Generic runtime status: `/api/cli-tools/runtime/[toolId]` (covers `claude`, `codex`, `droid`, `openclaw`, `cursor`, `cline`, `roo`, `continue`) - CLI `GET` responses expose runtime fields: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason` ### Authentication Behavior - Dashboard routes (`/dashboard/*`) use `auth_token` cookie protection. - Login uses saved password hash when present; otherwise it falls back to `INITIAL_PASSWORD`. - `requireLogin` can be toggled via `/api/settings/require-login`. ### Request Processing (High Level) 1. Client sends request to `/v1/*`. 2. Route handler calls `handleChat` (`src/sse/handlers/chat.js`), `handleEmbedding`, or `handleImageGeneration`. 3. Model is resolved (direct provider/model or alias/combo resolution). 4. Credentials are selected from local DB with account availability filtering. 5. For chat: `handleChatCore` detects format and translates request. For embeddings/images: handler proxies directly to upstream. 6. Provider executor sends upstream request. 7. Stream is translated back to client format when needed (chat). Embeddings and images return JSON. 8. Usage/logging is recorded (`src/lib/usageDb.js`). 9. Fallback applies on provider/account/model errors according to combo rules. Full architecture reference: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) --- ## πŸ“§ Support - **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute) - **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues) - **Original Project**: [9router by decolua](https://github.com/decolua/9router) --- ## πŸ‘₯ Contributors Thanks to all contributors who helped make OmniRoute better! [![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors) --- ## πŸ“Š Star Chart [![Star Chart](https://starchart.cc/diegosouzapw/OmniRoute.svg?variant=adaptive)](https://starchart.cc/diegosouzapw/OmniRoute) ### How to Contribute 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines. ### Releasing a New Version When a new GitHub Release is created (e.g. `v0.2.0`), the package is **automatically published to npm** via GitHub Actions: ```bash # Create a release β€” npm publish happens automatically gh release create v0.2.0 --title "v0.2.0" --generate-notes ``` The workflow syncs the version from the release tag, builds the standalone app, and publishes to npm. --- ## πŸ™ Acknowledgments Special thanks to **CLIProxyAPI** - the original Go implementation that inspired this JavaScript port. --- ## πŸ“„ License MIT License - see [LICENSE](LICENSE) for details. ---
Built with ❀️ for developers who code 24/7