Zyquo Router icon # Zyquo Router ### One local endpoint. Every AI provider. Spec-exact. *Turn your Mac into a private LLM gateway — 170 models from 12 providers behind a single OpenAI-compatible API.*
[![Release](https://img.shields.io/github/v/release/spboucher-ai/zyquo-router?style=for-the-badge&color=0891B2&label=Release)](https://github.com/spboucher-ai/zyquo-router/releases/latest) [![Platform](https://img.shields.io/badge/Platform-macOS%2013%2B-374151?style=for-the-badge&logo=apple&logoColor=white)](#-requirements) [![Swift](https://img.shields.io/badge/Swift-5.9%2B-F05138?style=for-the-badge&logo=swift&logoColor=white)](#%EF%B8%8F-building-from-source) [![License](https://img.shields.io/badge/License-MIT-2FA36B?style=for-the-badge)](LICENSE) [![Downloads](https://img.shields.io/github/downloads/spboucher-ai/zyquo-router/total?style=for-the-badge&color=4C2BE0&label=Downloads)](https://github.com/spboucher-ai/zyquo-router/releases) [![Notarized](https://img.shields.io/badge/Signed%20%26%20Notarized-Developer%20ID-0891B2?style=flat-square&logo=apple&logoColor=white)](#-installation) [![Universal](https://img.shields.io/badge/Universal-Apple%20Silicon%20%2B%20Intel-9BA3AA?style=flat-square)](#-installation) [![SwiftNIO](https://img.shields.io/badge/Server-SwiftNIO%202-E4E8EB?style=flat-square)](#%EF%B8%8F-architecture) [![No Electron](https://img.shields.io/badge/100%25%20Native-SwiftUI-0891B2?style=flat-square)](#%EF%B8%8F-architecture)
`Anthropic` · `OpenAI` · `xAI` · `Mistral` · `Google Gemini` · `Alibaba Qwen` · `DeepSeek` · `Kimi` · `Perplexity` · `Together AI` · `DeepInfra` · `Cerebras`
--- ## 📖 Table of Contents - [Why Zyquo Router](#-why-zyquo-router) - [Features](#-features) - [Screenshots](#-screenshots) - [Installation](#-installation) - [Requirements](#-requirements) - [Usage](#-usage) - [Architecture](#%EF%B8%8F-architecture) - [Building from Source](#%EF%B8%8F-building-from-source) - [Verification](#-verification) - [Roadmap](#-roadmap) - [Contributing](#-contributing) - [License](#-license) - [Author](#-author) --- ## 💡 Why Zyquo Router Every AI provider speaks a slightly different dialect. Anthropic wants `x-api-key` and content blocks; Gemini wants `contents/parts` and camelCase; Mistral renames `seed`; Perplexity ends its streams with a non-spec event. Your tools — SDKs, CLIs, IDE plugins, agents — mostly speak **one** dialect: the OpenAI API. **Zyquo Router** runs a tiny, native gateway on your Mac. You store your provider keys once in an encrypted vault, pick a port, press **Start** — and everything that can talk to OpenAI can now talk to *twelve providers* through `http://localhost:8787/v1`, with per-request model routing, live traffic inspection, and cost tracking. Think **OpenRouter / LiteLLM — but native, local, private, and gorgeous.** - 🔒 **Private by design** — keys never leave your Mac; requests go straight from your machine to the provider. No middleman, no telemetry, no accounts. - 🎯 **Spec-exact** — byte-exact `chat.completion.chunk` SSE streams that the official OpenAI Python and JS SDKs parse **unmodified** (verified across all 170 models). - 🖥 **A real Mac app** — SwiftUI control room with a menu bar extra, not a Docker container with a YAML file. --- ## ✨ Features ### 🌐 The Gateway | Capability | Details | |---|---| | **OpenAI-compatible API** | `POST /v1/chat/completions` (streaming + non-streaming), `GET /v1/models`, `GET /v1/models/{id}`, `GET /health` | | **170 models, 12 providers** | Full catalog with context windows, capabilities, and per-Mtok pricing under the `x_zyquo` extension key | | **Namespaced routing** | `provider/model-id` (e.g. `anthropic/claude-sonnet-4-5`, `deepinfra/meta-llama/Llama-4-Maverick`); bare IDs accepted when unambiguous | | **Aliases** | Friendly names — `fast` → `cerebras/…`, `best` → `anthropic/…` | | **Fallback chains** | Ordered model lists tried on upstream failure; the response honestly reports the model that answered | | **Full translation** | Anthropic Messages API and Gemini `generateContent` translated bidirectionally: system extraction, turn merging, tools ⇄ `tool_use`/`functionCall`, images, finish-reason and usage normalization | | **Tool calling** | Streamed `tool_calls` argument deltas in exact OpenAI shape, from all three wire formats | | **Vision** | `image_url` content parts (data-URI base64 and remote URLs where supported) | | **Reasoning models** | Thinking output normalized to `reasoning_content` (DeepSeek convention) — works with Claude thinking, Gemini thoughts, DeepSeek-R1, Qwen, Magistral, Perplexity ``, and more | | **Quirk normalization** | Together `finish_reason:"eos"`, Mistral thinking arrays, Perplexity citations + `.done` events, missing `object` fields, argument-repeat streams — all ironed into the spec | | **Resilience** | Exponential-backoff retries with jitter (never after the first streamed byte), honest OpenAI-format error mapping (401/429/502/504), client-disconnect cancels the upstream call in <1s | ### 🔐 Control & Security - **Encrypted key vault** — AES-256-GCM with an HKDF-derived, machine-bound master key (hardware UUID + salted pepper). No Keychain, no plaintext, ever. - **Localhost by default** — LAN exposure (`0.0.0.0`) is an explicit opt-in that *requires* at least one local API key. - **Local API keys** — `zyquo-sk-…` bearer tokens, SHA-256-hashed at rest, shown once at creation, per-key enable/revoke and model allow-lists. - **Redacted logging** — request/response bodies hidden by default; revealing is an explicit per-session switch. Provider keys never appear in any response, log, or error. ### 📊 Observability - **Live dashboard** — requests/min sparkline, tokens, estimated cost (from real per-model pricing), error rate, active streams, uptime, per-provider breakdown bar. - **Request inspector** — every routed call with provider, status, latency, tokens, cost, SSE badge, and a detail pane with an upstream-TTFB timing waterfall. - **Filters & export** — by provider/status/model (⌘F), pause/clear, JSON export. ### 🛠 Developer Experience - **Playground** — built-in tester that calls the router's *own* endpoint, with side-by-side request JSON / raw SSE panes and copy-as-code. - **In-app API docs** — the full reference rendered beautifully inside the app, from the same source of truth the server implements. - **Copy-as snippets** — endpoint URL, `curl`, OpenAI-Python, OpenAI-JS, pre-filled with your port. - **Menu bar extra** — status dot, Start/Stop, req/min, today's cost, copy endpoint. - **⌘K command palette** — server control, section jumps, fuzzy model-ID copy. - **Headless modes** — `ZyquoRouter --serve [port]` (no UI) and `--load-vault` (seed keys from environment variables) for scripting and CI. - **Shortcuts** — ⌘R start/stop · ⌘1–6 sections · ⌘F filter · ⌘⇧C copy endpoint · ⌘K palette. --- ## 📸 Screenshots
**Dashboard — the control room** Dashboard: server card with endpoint and copy-as snippets, live tiles, sparkline

**In-app API reference** Docs: hero card, code blocks with copy, styled sections
--- ## 📦 Installation ### Download (recommended) 1. **[⬇️ Download ZyquoRouter.dmg](https://github.com/spboucher-ai/zyquo-router/releases/latest/download/ZyquoRouter.dmg)** from the latest release 2. Open the DMG and drag **Zyquo Router** into **Applications** 3. Launch it — the app is **Developer ID signed, notarized, and stapled**, so Gatekeeper opens it without warnings ### First run — three steps to one endpoint 1. **Keys** → paste the API keys for the providers you use (each row has a **Test** button that verifies the key and shows latency) 2. **Dashboard** → pick a port (default `8787`) → press **Start** 3. Point anything OpenAI-compatible at `http://localhost:8787/v1` 🎉 --- ## 🖥 Requirements | | Minimum | |---|---| | **macOS** | 13.0 Ventura or later | | **Architecture** | Universal binary — Apple Silicon & Intel | | **Disk** | ~15 MB | | **Accounts** | None. Bring your own provider API keys | --- ## 🚀 Usage ### Python (official OpenAI SDK — works unmodified) ```python from openai import OpenAI client = OpenAI(base_url="http://localhost:8787/v1", api_key="zyquo") stream = client.chat.completions.create( model="anthropic/claude-sonnet-4-5", # any of the 170 models messages=[{"role": "user", "content": "Hello!"}], stream=True, ) for chunk in stream: print(chunk.choices[0].delta.content or "", end="") ``` ### JavaScript / TypeScript ```javascript import OpenAI from "openai"; const client = new OpenAI({ baseURL: "http://localhost:8787/v1", apiKey: "zyquo" }); const r = await client.chat.completions.create({ model: "gemini/gemini-2.5-flash", messages: [{ role: "user", content: "Hello!" }], }); ``` ### curl ```bash curl http://localhost:8787/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model": "deepseek/deepseek-chat", "messages": [{"role": "user", "content": "Hi"}], "stream": true}' ``` ### Good to know - **Model discovery:** `GET /v1/models` lists everything with context windows, pricing, and capability flags. Disabled models 404; favorites float to the top in-app. - **Reasoning:** pass the standard `reasoning_effort` — the router translates it per provider (Anthropic thinking budgets, Gemini `thinkingConfig`, Mistral `prompt_mode`, …) and normalizes the output into `reasoning_content`. - **Provider extras** pass straight through: Perplexity `search_domain_filter`, Qwen `enable_thinking`, Together `top_k`, Anthropic `thinking`, … - **Auth:** with no local keys the router is open on localhost. Create `zyquo-sk-…` keys in **Keys → Local API Keys** to require `Authorization: Bearer …` (mandatory for LAN mode). - The full contract lives in [`docs/API.md`](docs/API.md) — also rendered in-app under **Docs**. --- ## 🏗️ Architecture 100 % native Swift — no Electron, no Python sidecar, no Docker. ``` SwiftUI control room ─┐ ├─► SwiftNIO HTTP/1.1 server (structured concurrency, Menu bar extra ───────┘ NIOAsyncChannel, spec-exact SSE writer) │ RequestRouter (namespaces, aliases, fallback chains, capability gates) │ ┌───────────────────┼────────────────────┐ ▼ ▼ ▼ AnthropicTranslator GeminiTranslator CompatAdjuster (Messages API ⇄ (generateContent ⇄ (per-provider param OpenAI, SSE event OpenAI, SSE tables + quirk state machine) chunks) normalization ×10) └───────────────────┼────────────────────┘ ▼ UpstreamCall → provider APIs (your keys, straight from your Mac — AES-256-GCM vault) ``` - **Server:** SwiftNIO 2 with one task per connection; client disconnects propagate as cancellation all the way into the upstream `URLSession` transfer. - **Translation:** fixture-tested state machines convert Anthropic events and Gemini chunks into byte-exact OpenAI `chat.completion.chunk`s. - **Persistence:** JSON documents in `~/Library/Application Support/ZyquoRouter/`; keys in `vault.zq` (AES-256-GCM, machine-bound HKDF key, no Keychain). - **Zero heavyweight deps:** SwiftNIO, swift-nio-extras, swift-markdown. That's it. --- ## ⚙️ Building from Source Requirements: macOS 13+, Swift 5.9+ toolchain (Xcode or CLT), `librsvg` for the icon pipeline (`brew install librsvg`). Built entirely with SPM — **no Xcode IDE required**. ```bash git clone https://github.com/spboucher-ai/zyquo-router.git cd zyquo-router make dev # release build + ad-hoc signed dist/Zyquo Router.app make test # unit, fixture, and gateway-behavior test suites make icon # regenerate AppIcon.icns from assets/icon/zyquo-router.svg make release # universal binary + Developer ID signing + notarization + DMG ``` Headless gateway for scripts/CI: ```bash .build/release/ZyquoRouter --load-vault # seed the vault from env vars .build/release/ZyquoRouter --serve 8787 # run the gateway without the UI ``` --- ## ✅ Verification Every release is verified by [`scripts/verify.py`](scripts/verify.py), which drives **all 170 catalog models** through the local endpoint with the official OpenAI Python SDK — non-streaming, streaming chunk discipline, tool calling, vision, and reasoning. The current matrix is **170/170 green**: see [`docs/VERIFICATION.md`](docs/VERIFICATION.md). Gateway behavior is integration-tested against mock upstreams: client-disconnect cancellation, fallback-chain honesty, 429 retries, and graceful shutdown with active streams. --- ## 🗺 Roadmap - [ ] `POST /v1/embeddings` routed to embedding-capable providers - [ ] `POST /v1/responses` compatibility surface - [ ] Prompt-level request/response caching - [ ] Per-key rate limiting (token bucket) and budgets - [ ] Usage history persistence with daily/weekly summaries - [ ] Custom OpenAI-compatible endpoints (self-hosted vLLM/Ollama upstreams) --- ## 🤝 Contributing Issues and pull requests are welcome! 1. Fork → branch → make your change 2. `make test` must stay green (unit + fixture + gateway-behavior suites) 3. `swift build` must produce **zero warnings** 4. Every code file carries the project header (see any source file) --- ## 📄 License Released under the [MIT License](LICENSE). --- ## 👤 Author
**Simon-Pierre Boucher** 📫 Contact: [contact@spboucher.ai](mailto:contact@spboucher.ai) Part of the **Zyquo** family — Cloud · Local · Agent · Atlas · MLX · **Router** © 2026 Simon-Pierre Boucher. All rights reserved.