Skip to content

Repository files navigation

SwitchLM

npm version license

Local OpenAI-compatible routing proxy for Codex. SwitchLM exposes the Responses API and routes coding requests between Luna for simple work and Sol for heavier reasoning.

SwitchLM is published on npm as switchlm. The current release is 1.0.2.

Key benefits

  • Automatically routes simple tasks to Luna and heavier tasks to Sol using transparent deterministic heuristics.
  • Supports explicit model selection through router/luna and router/sol when automatic routing is not desired.
  • Connects to ChatGPT/Codex through OAuth, including local token storage and automatic access-token refresh.
  • Preserves OpenAI Responses API compatibility, including server-sent event streaming.
  • Exposes routing and token statistics through GET /stats and switchlm stats.
  • Runs locally with a small configuration and no database or additional classifier model.

Install

Install the published package globally:

npm install --global switchlm

Upgrade to the latest published version:

npm update --global switchlm

To run from source instead:

npm install
npm run build

Configure

Create the global user config at ~/.switchlm/config.json (%USERPROFILE%\.switchlm\config.json on Windows) so SwitchLM commands work from any directory. A project-level ./switchlm.config.json overrides the global config when both exist.

To move an existing project config on PowerShell:

New-Item -ItemType Directory -Force "$HOME\.switchlm"
Move-Item .\switchlm.config.json "$HOME\.switchlm\config.json"

Configuration example:

{
  "host": "127.0.0.1",
  "port": 8787,
  "bodyLimit": 16777216,
  "routing": {
    "solThreshold": 5
  },
  "providers": {
    "luna": {
      "type": "codex-chatgpt",
      "responsesUrl": "https://chatgpt.com/backend-api/codex/responses",
      "model": "gpt-5.6-luna",
      "account": "default"
    },
    "sol": {
      "type": "codex-chatgpt",
      "responsesUrl": "https://chatgpt.com/backend-api/codex/responses",
      "model": "gpt-5.6-sol",
      "account": "default"
    }
  },
  "logLevel": "info"
}

bodyLimit is the maximum request body size in bytes. The default is 16 MiB; increase it if Codex sends a larger repository context.

Authenticate once before starting SwitchLM:

switchlm login chatgpt

OAuth tokens are stored in ~/.switchlm/auth.json and refreshed automatically when possible.

OpenAI-compatible providers with API keys are also supported:

{
  "providers": {
    "luna": {
      "baseUrl": "https://luna.example.com/v1",
      "model": "luna-code",
      "apiKeyEnv": "LUNA_API_KEY"
    },
    "sol": {
      "baseUrl": "https://sol.example.com/v1",
      "model": "sol-reasoning",
      "apiKeyEnv": "SOL_API_KEY"
    }
  }
}

Provider entries without type are treated as openai-compatible. Set their credentials through the configured environment variables.

ChatGPT OAuth defaults:

authorizeUrl: https://auth.openai.com/oauth/authorize
tokenUrl: https://auth.openai.com/oauth/token
clientId: app_EMoamEEZ73f0CkXaXp7hrann
scopes: openid profile email offline_access
redirectUri: http://localhost:1455/auth/callback

Override them with env if needed:

set SWITCHLM_CHATGPT_AUTHORIZE_URL=...
set SWITCHLM_CHATGPT_TOKEN_URL=...
set SWITCHLM_CHATGPT_CLIENT_ID=...
set SWITCHLM_CHATGPT_SCOPES=openid profile

Run

switchlm start

Or from TypeScript during development:

npm run dev

Check health:

switchlm status

Show token usage:

npx switchlm stats

ChatGPT auth:

switchlm login chatgpt
switchlm auth status
switchlm logout chatgpt

API

Health:

curl http://127.0.0.1:8787/health

Responses:

curl http://127.0.0.1:8787/v1/responses ^
  -H "content-type: application/json" ^
  -d "{\"model\":\"router/auto\",\"input\":\"Fix this TypeScript error\"}"

Streaming:

curl http://127.0.0.1:8787/v1/responses ^
  -H "content-type: application/json" ^
  -d "{\"model\":\"router/auto\",\"input\":\"Fix this TypeScript error\",\"stream\":true}"

Virtual models:

  • router/auto routes by deterministic heuristics over user messages only; developer/system context and tool items are ignored.
  • router/luna always routes to Luna.
  • router/sol always routes to Sol.

Streaming requests are passed through as server-sent events.

The codex-chatgpt provider authenticates through the SwitchLM OAuth flow and uses the configured Codex Responses transport URL.

Token statistics:

curl http://127.0.0.1:8787/stats

The response contains routing and token totals for Luna, Sol, and both providers combined. routedRequests counts model selections, while measuredResponses counts completed responses with valid provider usage. The CLI shows their difference as missing. Statistics reset when SwitchLM restarts.

With logLevel: "info", each routing log includes the requested virtual model, selected target, score, and matching reasons without logging prompt contents.

The codex-chatgpt provider uses the configured Codex Responses transport URL. SwitchLM does not bundle provider-specific OAuth client credentials; set them explicitly through env.

Codex

Add the following provider to the user-level ~/.codex/config.toml:

model = "router/auto"
model_provider = "switchlm"

[model_providers.switchlm]
name = "SwitchLM"
base_url = "http://127.0.0.1:8787/v1"
wire_api = "responses"

Use router/luna or router/sol when a request must bypass automatic routing.

License

SwitchLM is distributed under the MIT License. See LICENSE.

Parts of the ChatGPT/Codex OAuth integration are based on or adapted from OmniRoute. See THIRD_PARTY_NOTICES.md for attribution and third-party license terms.

About

Route coding requests to the right model based on complexity. OpenAI-compatible proxy for Codex with automatic escalation, routing strategies, and manual overrides.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages