switchyard

mcp
Security Audit
Fail
Health Warn
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Fail
  • rm -rf — Recursive force deletion command in .github/workflows/release.yml
  • exec() — Shell command execution in app-ui/diff.js
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Switchya: a local coding workspace (desktop app + CLI) for the model providers you choose, powered by Switchyard Gateway, a self-hosted Rust LLM API gateway for OpenAI, Anthropic and Gemini protocols

README.md

Switchya & Switchyard Gateway

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

Start Switchya from source

From this checkout, in a Windows PowerShell terminal:

cargo build --release --locked -p switchyard-app
.\target\release\switchya.exe serve

Open 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. File edits and commands require an exact, single-use human decision;
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 --locked

The 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.

Switchyard Gateway

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, …
                              └────────────────────┘

Switchyard dashboard showing mock-provider traffic

The dashboard above uses the built-in mock provider; its figures are test traffic.

What it does

  • 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-After awareness 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.

Quick start

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:

switchyard

On 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"}]}]}'

Using it from coding tools

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"

Endpoints

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.

Configuration

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.

Command line

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.

Docker

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.1

This 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.

How translation works

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.

Building

cargo build --release -p switchyard     # Rust 1.88+
cargo test --workspace

The 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.

Acknowledgements

Switchyard is an independent implementation inspired by
CLIProxyAPI; see NOTICE.

Licence

MIT

Reviews (0)

No results found