Skip to content

Universal AI Proxy for Claude Code, Codex, Cursor | OpenAI, Claude, Gemini, Copilot

Notifications You must be signed in to change notification settings

decolua/9router

Repository files navigation

9Router Dashboard

9Router - Free AI Router

Never stop coding. Auto-route to FREE & cheap AI models with smart fallback.

Free AI Provider for OpenClaw.

OpenClaw

npm Downloads License

πŸš€ Quick Start β€’ πŸ’‘ Features β€’ πŸ“– Setup β€’ 🌐 Website


πŸ€” Why 9Router?

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

9Router 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
       ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           9Router (Smart Router)        β”‚
β”‚  β€’ Format translation (OpenAI ↔ Claude) β”‚
β”‚  β€’ Quota tracking                       β”‚
β”‚  β€’ Auto token refresh                   β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”œβ”€β†’ [Tier 1: SUBSCRIPTION] Claude Code, Codex, Gemini CLI
       β”‚   ↓ quota exhausted
       β”œβ”€β†’ [Tier 2: CHEAP] GLM ($0.6/1M), MiniMax ($0.2/1M)
       β”‚   ↓ budget limit
       └─→ [Tier 3: FREE] iFlow, Qwen, Kiro (unlimited)

Result: Never stop coding, minimal cost

⚑ Quick Start

1. Install globally:

npm install -g 9router
9router

πŸŽ‰ Dashboard opens at http://localhost:20128

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):

This repository package is private (9router-app), so source/Docker execution is the expected local development path.

cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev

Production mode:

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
πŸ“ 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
πŸ“– 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 β†’ 9Router 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
πŸ’° 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)

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. 9Router tracks quota per model!

OpenAI Codex (Plus/Pro)

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!)

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

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
  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
  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
  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)

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)

Dashboard β†’ Connect Qwen
β†’ Device code authorization
β†’ Unlimited usage

Models:
  qw/qwen3-coder-plus
  qw/qwen3-coder-flash

Kiro (Claude FREE)

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 9router dashboard]
  Model: cc/claude-opus-4-6

Or use combo: premium-coding

Claude Code

Edit ~/.claude/config.json:

{
  "anthropic_api_base": "http://localhost:20128/v1",
  "anthropic_api_key": "your-9router-api-key"
}

Codex CLI

export OPENAI_BASE_URL="http://localhost:20128"
export OPENAI_API_KEY="your-9router-api-key"

codex "your prompt"

OpenClaw

Option 1 β€” Dashboard (recommended):

Dashboard β†’ CLI Tools β†’ OpenClaw β†’ Select Model β†’ Apply

Option 2 β€” Manual: Edit ~/.openclaw/openclaw.json:

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "9router/if/glm-4.7"
      }
    }
  },
  "models": {
    "providers": {
      "9router": {
        "baseUrl": "http://127.0.0.1:20128/v1",
        "apiKey": "sk_9router",
        "api": "openai-completions",
        "models": [
          {
            "id": "if/glm-4.7",
            "name": "glm-4.7"
          }
        ]
      }
    }
  }
}

Note: OpenClaw only works with local 9Router. Use 127.0.0.1 instead of localhost to avoid IPv6 resolution issues.

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

# Clone and install
git clone https://github.com/decolua/9router.git
cd 9router
npm install
npm run build

# Configure
export JWT_SECRET="your-secure-secret-change-this"
export INITIAL_PASSWORD="your-password"
export DATA_DIR="/var/lib/9router"
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://9router.com"
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 9router -- start
pm2 save
pm2 startup

Docker

# Build image (from repository root)
docker build -t 9router .

# Run container (command used in current setup)
docker run -d \
  --name 9router \
  -p 20128:20128 \
  --env-file /root/dev/9router/.env \
  -v 9router-data:/app/data \
  -v 9router-usage:/root/.9router \
  9router

Portable command (if you are already at repository root):

docker run -d \
  --name 9router \
  -p 20128:20128 \
  --env-file ./.env \
  -v 9router-data:/app/data \
  -v 9router-usage:/root/.9router \
  9router

Container defaults:

  • PORT=20128
  • HOSTNAME=0.0.0.0

Useful commands:

docker logs -f 9router
docker restart 9router
docker stop 9router && docker rm 9router

Environment Variables

Variable Default Description
JWT_SECRET 9router-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 ~/.9router Main app database location (db.json)
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://9router.com 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://9router.com 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)
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.
  • 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: ~/.9router/usage.json and ~/.9router/log.txt, managed by src/lib/usageDb.js.
  • Optional request/translator logs: <repo>/logs/... when ENABLE_REQUEST_LOGS=true.
  • Usage storage currently follows ~/.9router path logic and is independent from DATA_DIR.

πŸ“Š 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

πŸ› 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 9Router
  • 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://9router.com)
  • 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://9router.com/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 9Router 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.

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
  • Database: LowDB (JSON file-based)
  • Streaming: Server-Sent Events (SSE)
  • Auth: OAuth 2.0 (PKCE) + JWT + API Keys

πŸ“ API Reference

Chat Completions

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
}

List Models

GET http://localhost:20128/v1/models
Authorization: Bearer your-api-key

β†’ Returns all models + combos in OpenAI format

Compatibility Endpoints

  • POST /v1/chat/completions
  • POST /v1/messages
  • POST /v1/responses
  • GET /v1/models
  • 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://9router.com/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.

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:
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://9router.com/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/*
  • CLI helpers: /api/cli-tools/claude-settings, /api/cli-tools/codex-settings, /api/cli-tools/droid-settings, /api/cli-tools/openclaw-settings

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).
  3. Model is resolved (direct provider/model or alias/combo resolution).
  4. Credentials are selected from local DB with account availability filtering.
  5. handleChatCore (open-sse/handlers/chatCore.js) detects format and translates request.
  6. Provider executor sends upstream request.
  7. Stream is translated back to client format when needed.
  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


πŸ“§ Support


πŸ‘₯ Contributors

Thanks to all contributors who helped make 9Router better!

Contributors


πŸ“Š Star Chart

Star Chart

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 for detailed guidelines.


πŸ™ Acknowledgments

Special thanks to CLIProxyAPI - the original Go implementation that inspired this JavaScript port.


πŸ“„ License

MIT License - see LICENSE for details.


Built with ❀️ for developers who code 24/7

About

Universal AI Proxy for Claude Code, Codex, Cursor | OpenAI, Claude, Gemini, Copilot

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors 12

Languages