Website: switchya.com · Windows preview download · User guide · Gateway v0.1.1
Switchya is a local coding workspace with a browser interface, a terminal CLI, and a native desktop shell. Open a project, choose a model, send a task, and review proposed edits and commands alongside their results. The app and CLI share saved sessions. Switchyard Gateway remains an independent API gateway for other tools and applications.
The current source also includes a persistent project workbench with file
previews, Git diffs, a real terminal, and shared agent context over MCP.
Codex, Claude Code and Antigravity can run inside the conversation view with
saved history, streamed output, tool activity and their own approval policies
(Antigravity is read-only plan mode). These additions are newer than the
published preview.2 archive; they ship in preview.3.
| Start here | Purpose | Availability |
|---|---|---|
| Switchya user guide | Provider setup, projects, sessions, approvals, account boundaries, and app/CLI handoff | Windows x64 portable preview |
| Native desktop build | Build the separate desktop shell | Separate Cargo workspace; operating-system runtime verification is distinct from gateway verification |
| Switchyard Gateway | Protocol translation, routing, credential pools, and its operations dashboard | v0.1.2 downloads for Windows, Linux and macOS |
The Switchya preview targets Windows 10/11 x64 and contains the native
shell and CLI in an unsigned portable archive, with no installer or bundled
runtime DLLs. Install the Microsoft Visual C++ v14 x64 Redistributable
and Microsoft Edge WebView2 Runtime; WebView2 is required for the desktop
shell. Extract the ZIP and open switchya-desktop.exe, or run switchya.exe serve
for the browser workspace. The first run guides you through provider setup.
No macOS app binary is available, and separate Linux checks do not constitute
a Linux desktop release. See the preview verification status
for the tested scope and remaining limits.
The gateway release (v0.1.2) includes archives for Windows x64, Linux x64 and
arm64 (glibc and static musl) and macOS arm64 and Intel, each with a SHA-256
file. The release workflow tested each target and started its binary on a
GitHub-hosted runner of that platform. A multi-architecture container image is
published as ghcr.io/ichikuruma22-star/switchyard. These gateway results do
not establish Switchya desktop availability on those platforms.
From this checkout, in a Windows PowerShell terminal:
cargo build --release --locked -p switchyard-app
.\target\release\switchya.exe serveOpen the private launch URL printed in the terminal. Choose Connect a provider to add an OpenAI, Anthropic or Gemini API key, an environment-variable reference, or an existing local Ollama server. A starter mock model is not a working coding model. Open a local project, select a real model, and send a task. By default, file edits and commands require an exact, single-use human decision. For a project you trust, you can turn on automatic approval. Commands run with your operating-system permissions.
To build the Windows desktop shell, use its separate manifest:
cargo build --manifest-path desktop/Cargo.toml --release --lockedThe desktop requires Rust 1.90+ and the platform prerequisites. See the Switchya guide for persistent sessions, CLI handoff, recovery, and the separate permission and account boundaries of existing agents.
A fast LLM API gateway in a single Rust binary. Point any OpenAI, Anthropic or Gemini client at it and route requests to any provider you have keys for — Switchyard translates between the protocols, rotates across your credentials, fails over when one is rate limited, and shows you what is happening in a built-in dashboard.
your tools Switchyard providers
───────────── ┌────────────────────┐
OpenAI SDK / Codex CLI ────► │ /v1/chat/completions│ ──► OpenAI
Claude Code / Anthropic SDK ►│ /v1/responses (+WS)│ ──► Anthropic
Gemini CLI / google-genai ──►│ /v1/messages │ ──► Gemini / Vertex AI
anything OpenAI-compatible ─►│ /v1beta/models/… │ ──► OpenRouter, Groq, Ollama, vLLM, …
└────────────────────┘
The dashboard above uses the built-in mock provider; its figures are test traffic.
- Four client protocols: OpenAI Chat Completions, OpenAI Responses,
Anthropic Messages and Gemini
generateContent— streaming and non-streaming, tools, images, reasoning, structured output, token counting. - Any client, any provider: a request in one protocol can be served by a provider that speaks another. Same-protocol requests preserve provider fields, with model normalization and any configured reasoning or payload changes.
- WebSockets: the OpenAI Responses API over WebSocket (
GET /v1/responses) for any model, a relay for the OpenAI Realtime API (/v1/realtime), and a live event feed for the dashboard. - Credential pools: several keys per provider with round-robin,
fill-first, weighted or least-latency selection, priorities, per-model
cooldowns with backoff,
Retry-Afterawareness and automatic failover. - Model routing: aliases, provider prefixes (
team-a/gpt-5), fallback chains (smart → claude-opus, then gpt-5), model discovery, exclusions. - Reasoning control:
gpt-5(high),claude-sonnet-4-5(16000),gemini-2.5-flash(none)— one suffix syntax, converted to whatever each provider expects and clamped to what the model supports. - Dashboard at
/admin/: live request stream, provider and credential health, usage and cost charts, a playground for every protocol, logs, and a config editor. Embedded in the binary; no external assets. - Operations: hot-reloaded TOML config (the dashboard edits it in place and keeps your comments), client API keys with model allow-lists and rate limits, payload rewrite rules, usage history, request/response capture, proxies (HTTP, SOCKS5) per provider or credential, optional TLS.
Upstream access is by API key or service account only. Switchyard does not log in to consumer subscriptions or impersonate vendor CLIs.
The Windows x64 download requires the Microsoft Visual C++ v14 x64
Redistributable.
Install it if Windows reports that VCRUNTIME140.dll is missing.
Download a binary from the releases page
(or build it: cargo install --git https://github.com/ichikuruma22-star/switchyard switchyard), then:
switchyardOn first start it writes switchyard.toml with a fresh admin secret and client
API key, and enables a built-in mock provider so you can try everything without
any upstream key. An interactive terminal shows the credentials once; redirected
logs omit them. Read admin.secret and the client key in the private config
file when running as a service. Open http://127.0.0.1:8317/admin/ and sign in
with the admin secret.
Add a real provider in the dashboard, or in switchyard.toml:
[[providers]]
name = "anthropic"
kind = "anthropic"
api_keys = ["env:ANTHROPIC_API_KEY"]
[[providers]]
name = "openai"
kind = "openai"
api_keys = ["env:OPENAI_API_KEY"]Then call it with whichever SDK you like:
# OpenAI Chat Completions → served by Anthropic
curl http://127.0.0.1:8317/v1/chat/completions \
-H "Authorization: Bearer $SWITCHYARD_KEY" -H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"Hello"}]}'
# Anthropic Messages → served by OpenAI
curl http://127.0.0.1:8317/v1/messages \
-H "x-api-key: $SWITCHYARD_KEY" -H "anthropic-version: 2023-06-01" -H "Content-Type: application/json" \
-d '{"model":"gpt-5","max_tokens":1024,"messages":[{"role":"user","content":"Hello"}]}'
# Gemini → served by anything
curl "http://127.0.0.1:8317/v1beta/models/gpt-5:generateContent" \
-H "x-goog-api-key: $SWITCHYARD_KEY" -H "Content-Type: application/json" \
-d '{"contents":[{"parts":[{"text":"Hello"}]}]}'| Tool | Setting |
|---|---|
| Claude Code | ANTHROPIC_BASE_URL=http://127.0.0.1:8317 and ANTHROPIC_API_KEY=<client key> |
| Codex CLI | a model_providers entry with base_url = "http://127.0.0.1:8317/v1", wire_api = "responses" |
| Gemini CLI | GOOGLE_GEMINI_BASE_URL=http://127.0.0.1:8317 and GEMINI_API_KEY=<client key> |
| OpenAI SDKs | base_url="http://127.0.0.1:8317/v1" |
POST /v1/chat/completions |
OpenAI Chat Completions |
POST /v1/completions |
legacy completions (served through chat; text prompts only, token-id prompts get a 400) |
POST /v1/responses |
OpenAI Responses |
GET /v1/responses |
Responses over WebSocket |
POST /v1/responses/input_tokens |
token count |
POST /v1/messages, /v1/messages/count_tokens |
Anthropic Messages |
POST /v1beta/models/{model}:generateContent, :streamGenerateContent, :countTokens |
Gemini |
GET /v1/models, /v1beta/models |
model lists in each vendor's shape |
GET /v1/realtime |
WebSocket relay to an OpenAI Realtime upstream |
POST /v1/ws-ticket |
authenticated, single-use browser WebSocket ticket |
POST /v1/embeddings, /v1/images/generations, /v1/moderations, /v1/audio/speech |
forwarded to an OpenAI-compatible provider |
GET /healthz |
liveness |
/admin/, /admin/api/… |
dashboard and admin API |
Clients authenticate with a key from [[auth.keys]], sent as
Authorization: Bearer, x-api-key, x-goog-api-key or ?key=.
Prefer headers. Browser WebSocket clients can mint a 30-second ticket with
POST /v1/ws-ticket using a key in a header, then connect with ?ticket= so
the long-lived key never appears in a URL.
Everything lives in one TOML file; switchyard.example.toml
documents every setting with its default. Highlights:
[routing]
strategy = "round-robin" # round-robin | fill-first | weighted | least-latency
max_attempts = 3
[[providers]]
name = "openrouter"
kind = "openai-compat" # openai | anthropic | gemini | vertex | openai-compat | mock
base_url = "https://openrouter.ai/api/v1"
api_keys = ["env:OPENROUTER_API_KEY"]
prefix = "or" # models are served as "or/<model>"
[[aliases]]
name = "smart" # a virtual model with a fallback chain
targets = ["claude-opus-4-5", "gpt-5(high)"]
[[payload.override]] # patch upstream request bodies
models = ["gpt-*"]
set = { "reasoning.summary" = "auto" }Secrets may be literal or env:NAME (also written ${NAME}). Provider
headers values accept the same references, resolved like API keys; a header
whose variable is unset makes that provider's credentials unusable instead of
sending the reference text. The file is reloaded when it changes; an
invalid edit is rejected and the running config kept.
See the security and deployment model before sharing access. Model allow-lists do not isolate files or resources within a shared upstream account, and the dashboard's Remember option stores its admin secret in the trusted browser profile.
switchyard [serve] [--config <path>] [--host <h>] [--port <p>]
switchyard init [--config <path>] [--force] write a starter config with fresh secrets
switchyard check [--config <path>] validate a config file
switchyard import-cliproxy <config.yaml> [-o <path>] convert the API-key sections of a CLIProxyAPI config
switchyard version
Environment: SWITCHYARD_CONFIG, SWITCHYARD_ADMIN_SECRET,
SWITCHYARD_ADMIN_ALLOW_REMOTE.
Release images for linux/amd64 and linux/arm64 are published to GitHub
Container Registry as ghcr.io/ichikuruma22-star/switchyard:<version> and
:latest. They run as an unprivileged user and keep their data in /data.
To build your own instead, run docker build -t switchyard:local . from this
checkout and use that tag below.
export SWITCHYARD_ADMIN_SECRET="$(openssl rand -hex 32)"
docker run -d --name switchyard -p 127.0.0.1:8317:8317 \
-v switchyard-data:/data \
-e SWITCHYARD_ADMIN_SECRET -e SWITCHYARD_ADMIN_ALLOW_REMOTE=true \
ghcr.io/ichikuruma22-star/switchyard:0.1.2This bash example generates a fresh admin secret in SWITCHYARD_ADMIN_SECRET;
use that value to sign in and keep it in a password manager. The config is
created at /data/switchyard.toml on first start. Admin access across the
container boundary is explicitly enabled, while the published port is bound
to the host's loopback interface. For access from other machines, use TLS and
restrict who can reach the gateway. Images leave remote admin access disabled
unless you enable it.
Each protocol has a codec that maps it to and from one canonical request and stream model, so supporting four protocols takes four codecs rather than twelve pairwise translators. When the client and the provider speak the same protocol its fields are preserved, with JSON normalization, model routing and any configured reasoning or payload changes. Restricted client keys cannot use upstream selectors that could bypass their model allow-list. Details that do not survive a protocol boundary — provider-specific blocks, signed reasoning from another vendor — are dropped rather than sent somewhere they would be rejected. See docs/DESIGN.md.
cargo build --release -p switchyard # Rust 1.88+
cargo test --workspaceThe dashboard in ui/ has no build step and is embedded at compile time. A
debug build (cargo run -p switchyard) serves it straight from ui/ on disk, so
edits show up on reload; node ui/tests/check.mjs runs its self-checks.
Switchyard is an independent implementation inspired by CLIProxyAPI; see NOTICE.
MIT
