Group 1(1) **One endpoint. Every model. Always the right one.** A drop-in proxy for Anthropic, OpenAI, and Gemini that picks the best model for *every* request: using a tiny on-box embedder, not a vibes-based prompt. [![Weave Badge](https://img.shields.io/endpoint?url=https%3A%2F%2Fapp.workweave.ai%2Fapi%2Frepository%2Fbadge%2Forg_QWsHDcRQWQEs6RpkdEZrlFK8%2F1222789989%2Fhttps%253A%252F%252Fgithub.com&cacheSeconds=3600)](https://app.workweave.ai/reports/repository/org_QWsHDcRQWQEs6RpkdEZrlFK8/https%3A%2F%2Fgithub.com/1222789989) [![Go](https://img.shields.io/badge/Go-1.26%2B-00ADD8?logo=go)](go.mod) [![Tests](https://github.com/weave-os/router/actions/workflows/test.yml/badge.svg)](https://github.com/weave-os/router/actions/workflows/test.yml) [![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE) [![Managed deployment](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Frouter.workweave.ai%2Fv1%2Fversion&query=%24.display&label=managed%20deployment&color=EC6341&cacheSeconds=1800)](https://github.com/weave-os/router/deployments) [![#1 Product of the Day on Product Hunt](https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=1247729&theme=light&period=daily)](https://www.producthunt.com/posts/weave-router-2-0?embed=true&utm_source=badge-top-post-badge&utm_medium=badge&utm_campaign=badge-weave-router-2-0) *Built by [Weave](https://www.workweave.ai): The #1 engineering intelligence platform, loved by Robinhood, PostHog, Reducto, and hundreds of others.*
--- ## What it does Point Claude Code, Codex, Cursor, or your own app at `localhost:8080`. The router: - 🎯 **Routes per action.** A cluster scorer derived from [Avengers-Pro](https://arxiv.org/abs/2508.12631) [^1] picks the right model from your enabled providers, for every upstream API request. (See [docs/SEMANTICS.md](docs/SEMANTICS.md) for the canonical terminology: the router routes per **action**, not per **turn**.) - 🔌 **Speaks everyone's API.** Anthropic Messages, OpenAI Chat Completions, Gemini native. Streaming, tools, vision, the works. - 🧠 **Knows OSS too.** DeepSeek, Kimi, GLM, Qwen, Llama, Mistral via OpenRouter (or any OpenAI-compatible endpoint). - 🔒 **BYOK by default.** Provider keys stay on your box, encrypted at rest. - 📊 **Observable.** OTLP traces out of the box. See them in the Weave dashboard (http://localhost:8080/ui/dashboard) or drop in Honeycomb, Datadog, Grafana, whatever. ## 30-second quickstart The fastest way: point Claude Code, Codex, opencode, or pi at the **hosted** Weave Router with one command. No clone, no Docker, no Postgres. ```bash npx @weave-os/router ``` That's it. Your browser opens the hosted setup page. To install directly from the terminal, choose a target explicitly. Other flavors: ```bash npx @weave-os/router --claude # skip the picker, Claude Code npx @weave-os/router --codex # skip the picker, OpenAI Codex CLI npx @weave-os/router --opencode # skip the picker, opencode npx @weave-os/router --pi # skip the picker, pi + Loom UI npx @weave-os/router --scope project # per-repo, commits settings.json (or .codex/ / opencode.json) npx @weave-os/router --local # self-hosted localhost:8080 npx @weave-os/router --base-url https://router.acme.internal npx @weave-os/router --email you@example.com # set identity without prompting npx @weave-os/router --claude --return-url https://app.example.com/onboarding # continue after health + key verification npx @weave-os/router@0.1.0 # pin a version ``` Requires Node ≥ 18 (Claude Code, opencode, and pi paths also need `jq`). Full flag reference: [install/npm/README.md](install/npm/README.md). The npm package is published as `@weave-os/router`. The former `@workweave/router` package remains available as a compatibility alias and continues to receive the same releases. ### Or: self-host the whole stack If you want the router (and dashboard) running on your own box: ```bash # 1. Drop a provider key in. OpenRouter is the recommended baseline. echo "OPENROUTER_API_KEY=sk-or-v1-..." >> .env.local # 2. Set a dashboard password. Without one, inference still runs but # dashboard administration is disabled. echo "ROUTER_ADMIN_PASSWORD=replace-with-a-strong-password" >> .env.local # 3. Boot Postgres + router on :8080 and seed an rk_ key. make full-setup ``` The router is up at , the dashboard at , and your `rk_...` key prints in the logs. ```bash # Call it like Anthropic curl -sS http://localhost:8080/v1/messages \ -H "Authorization: Bearer rk_..." \ -d '{"model":"claude-sonnet-4-5","max_tokens":256, "messages":[{"role":"user","content":"hi"}]}' # ...or like OpenAI curl -sS http://localhost:8080/v1/chat/completions \ -H "Authorization: Bearer rk_..." \ -d '{"model":"gpt-4o-mini", "messages":[{"role":"user","content":"hi"}]}' # Peek at the routing decision without proxying curl -sS http://localhost:8080/v1/route -H "Authorization: Bearer rk_..." -d '...' ``` ### What that stack looks like Only the grey boxes are off your machine. The router, the scorer, Postgres, and your provider keys all stay local; prompts go from the router straight to the provider you configured, never to Weave. ```mermaid flowchart LR client["Claude Code, Codex, opencode,
pi, Cursor, your own app"] router["Router :8080
/v1/messages · /v1/chat/completions
/v1beta/models · /v1/route"] scorer["Cluster scorer
in-process ONNX embedder"] hmm["HMM policy sidecar :8093
optional, make up-hmm"] pg[("Postgres
installations, rk_ keys,
encrypted BYOK keys, usage")] ui["Dashboard /ui
selfhosted mode only"] providers["Anthropic · OpenAI · Gemini
OpenRouter and any
OpenAI-compatible endpoint"] otel["Your OTLP collector
Honeycomb, Datadog, Grafana"] client -->|"rk_… bearer token,
streamed response back"| router router -->|"embed and score the action"| scorer router -.->|"ROUTER_DEFAULT_STRATEGY=hmm"| hmm router -->|"auth, config, usage"| pg pg --> ui router -->|"provider key from env or BYOK"| providers router -.->|"spans and usage logs"| otel classDef external fill:#f4f4f5,stroke:#a1a1aa,color:#3f3f46 class providers,otel external ``` Multi-replica deployments also need Pub/Sub (`PUBSUB_*`) for cache invalidation; `docker compose` runs the emulator for you. ### Optional: self-host the frozen HMM policy The default stack uses the in-process cluster scorer. To run the frozen HMM policy as a companion container, add a Google API key and use the opt-in target: ```bash echo 'GOOGLE_API_KEY=...' >> .env.local make up-hmm ``` This does not change the default strategy. See [`sidecars/hmm/README.md`](sidecars/hmm/README.md) for artifact verification, embedding compatibility, and explicit HMM selection. ## Wire it into your tools **Claude Code.** Run `make install-cc` to wire Claude Code at the local self-hosted router (it's also invoked automatically at the end of `make full-setup`). For the hosted router, use `npx @weave-os/router` above. **Codex** (OpenAI CLI). `npx @weave-os/router --codex` patches `~/.codex/config.toml` (or `/.codex/config.toml` with `--scope project`) with a managed `[model_providers.weave]` block and sets `model_provider = "weave"`. The provider preserves Codex's existing ChatGPT OAuth login while the router key rides in an `X-Weave-Router-Key` HTTP header and the installer selects the HMM strategy for the public hosted endpoint. `--codex --local` and custom self-hosted URLs keep their router's configured default because the HMM sidecar is optional. HMM and forced selections in the native Codex family (`gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`) use that OAuth credential; every other selected model uses its WorkWeave deployment or BYOK credential, matching the Claude Code plugin's model-to-credential dispatch. Codex does not load third-party slash-command files, so the installer ships `$force-model ` (alias `$fm `), `$unforce-model` (alias `$ufm`), and `$router-feedback ` (alias `$rf `) as native Codex skills. Their invocations are handled by the router directly. Re-install and `--uninstall --codex` rewrite/remove only the managed block, leaving the rest of your Codex config untouched. Codex also gets `$router-status`, `$router-off`, `$router-on`, and `$router-models` as skills that call this installer's own verbs. Invoke `$disable-routing` (or `$router-off`) to switch the next Codex session back to its normal provider, or run `npx @weave-os/router disable-routing` in a shell; a literal `/disable-routing` is not a third-party extension point in Codex. **opencode.** `npx @weave-os/router --opencode` requires OpenCode major version 2 when the CLI is installed and available on `PATH`. It merges a `provider.weave` entry into `~/.config/opencode/opencode.json` (or `/opencode.json` with `--scope project`) and makes `weave/auto` the active model while saving any prior default for off/uninstall. OpenCode v2 sends Responses requests through its bundled `@ai-sdk/openai` provider; the router selects and translates to the upstream model. The router key, identity, and session headers ride alongside the provider config. No plugin is installed; re-install removes stale v1 plugin registrations/files, and `--uninstall --opencode` removes the provider and restores the prior model. **pi.** `npx @weave-os/router --pi` keeps stock pi as the runtime and installs the router's pi extension. It adds the Loom header, Wooly's animated terminal mascot, a persistent `WEAVE ROUTER` route/savings line, `/fm` + `/ufm` model-pin commands with a `[forced]` status, and context-isolated subagents without shipping or maintaining a forked pi binary. **Cursor** *(early beta, performance may not be the best).* Settings → Models → *Override OpenAI Base URL* → `http://localhost:8080/v1`, paste `rk_...` as the API key. **Switching on/off.** After installing, `npx @weave-os/router off --claude` (or `--codex` / `--opencode`) routes that client straight to its provider again without discarding the router config; `on` flips it back, and `status` reports which way it's pointing. Claude Code also gets `/router-off`, `/router-on`, and `/router-status` slash commands. Cursor toggles via the same Settings → Models override above. See [install/README.md](install/README.md#switching-on-and-off). **Choosing which models the router may pick.** `npx @weave-os/router models --claude` lists every deployed model with its on/off state, and `models enable` / `models disable` change it — the same setting as the dashboard's settings page, edited from the terminal. Claude Code gets this as `/router-models` (alias `/models`). Requires a router that serves the model-selection API; against the Weave-hosted router the list still prints and points you at the dashboard, where selection is an organization-wide setting. See [install/README.md](install/README.md#choosing-which-models-the-router-may-pick). > Two keys, don't mix them up: > - `sk-or-...` / `sk-ant-...` / `sk-...` = your **upstream** provider key. Lives in `.env.local`. > - `rk_...` = your **router** key. Clients send this as a Bearer token. ## Endpoints | Endpoint | Format | | ------------------------------ | ---------------------------------------- | | `POST /v1/messages` | Anthropic Messages, routed | | `POST /v1/chat/completions` | OpenAI Chat Completions, routed | | `POST /v1beta/models/:action` | Gemini `generateContent`, routed | | `POST /v1/route` | Returns the decision, no upstream call | | `GET /v1/models`  ·  `POST /v1/messages/count_tokens` | Anthropic passthrough | | `GET /livez`  ·  `GET /startupz` | process responsive check + completed initialization | | `GET /health`  ·  `GET /readyz`  ·  `GET /validate` | responsive-check alias + dependency diagnostics + key check | | `POST /v1/client-events` | Harness CLI's `off`/`on`/`uninstall` report (`harness` = `claude_code`/`codex`/`opencode`/`pi`); logged + exported as `router.harness_lifecycle`, nothing stored | | `GET /v1/sessions/:session_id/cost` | One session's committed cost + savings, scoped to your key's installation; `rk_` or `ra_` key ([docs](docs/SESSION_COST.md)) | | `GET /v1/analytics/routing-decisions` | Raw routing decisions as cursor-paginated NDJSON ([docs](docs/ANALYTICS_EXPORT.md)) | | `GET /v1/analytics/schema`  ·  `GET /v1/analytics/models` | Export field dictionary + price book | Use `/startupz` for Cloud Run startup and `/livez` for its process responsive check. The listener starts after artifact/client initialization and bounded connection preparation. `/startupz` also pings PostgreSQL with a two-second budget: failure returns 503, so Cloud Run withholds traffic and retries while the process stays running. Provider preparation failures only log warnings. `/livez` does not contact the database. Startup sends no prompts and performs no embedding or HMM inference; it cannot guarantee the latency of first inference. `/readyz` retains dependency diagnostics. Routed non-stream responses include `x-router-cost-usd`, `x-router-cost-input-usd`, `x-router-cost-output-usd`, `x-router-cache-read-tokens`, and `x-router-cache-creation-tokens`. Streaming responses cannot carry the final cost in HTTP headers because headers flush before usage is known; stream clients should read the `weave_cost` object on the final Anthropic `message_delta` usage event. ## Deeper docs - 📐 [**Configuration reference**](docs/CONFIGURATION.md): every env var, BYOK encryption, OTel knobs, cluster routing. - 🧭 [**Semantics and terminology**](docs/SEMANTICS.md): canonical definitions for session, round, turn, action, and step. - 📊 [**Analytics export**](docs/ANALYTICS_EXPORT.md): pulling raw routing decisions into your own warehouse with a read-only key. - [**Policy router harness**](docs/POLICY_ROUTER_HARNESS.md): contract and rollout checklist for adding an out-of-process policy model. - 📏 [**Codex benchmark harness**](bench/README.md): reproduce the published SWE-Atlas QnA and Terminal-Bench 4.0 comparisons of `/beta` routing vs. direct and OpenRouter controls. - 🛠️ [**Contributing**](CONTRIBUTING.md): layering rules, hot-reload dev, migrations, tests, the whole engineering loop. - 🏗️ [**Architecture**](AGENTS.md): package layout, import contracts, recipes for adding endpoints / providers / strategies. ## License Licensed under the [Apache License 2.0](LICENSE). Copyright 2025-2026 Workweave, Inc. See [NOTICE](NOTICE) for attribution. The Apache-2.0 release line begins with `router-v0.2.24` (npm packages `@weave-os/router` and `@workweave/router` version `0.2.24`). Earlier tags and published packages retain the licenses shipped with them; this change does not rewrite historical releases. Apache-2.0 permits commercial use, hosted services, and proprietary derivatives, subject to its terms, and includes a patent grant. It does not grant general rights to Workweave's trademarks. Third-party code, dependencies, model weights, and datasets retain their own licenses; see [THIRD_PARTY.md](THIRD_PARTY.md). --- [^1]: Zhang, Y. et al. *Beyond GPT-5: Making LLMs Cheaper and Better via Performance–Efficiency Optimized Routing* (Avengers-Pro). arXiv:2508.12631, 2025.