|
| 1 | +<div align="center"> |
| 2 | + <img src="./resources/brandMark@2x.png" width="64" height="64" alt="ReRouted logo" /> |
| 3 | + <h1>ReRouted</h1> |
| 4 | + <p><strong>Stop rewiring your AI tools every time an account hits quota.</strong></p> |
| 5 | + <p> |
| 6 | + A macOS menu-bar router that puts your connected accounts, models, |
| 7 | + API keys, and fallback routes behind one local chat-completions endpoint. |
| 8 | + </p> |
| 9 | + <p> |
| 10 | + <a href="https://rerouted.dev">Website</a> | |
| 11 | + <a href="https://github.com/gitcommit90/rerouted/releases/latest">Download</a> | |
| 12 | + <a href="#quick-start">Quick start</a> | |
| 13 | + <a href="./docs/architecture.md">Architecture</a> |
| 14 | + </p> |
| 15 | + <p> |
| 16 | + <a href="https://github.com/gitcommit90/rerouted/releases/latest"><img alt="GitHub release" src="https://img.shields.io/github/v/release/gitcommit90/rerouted?color=ef5b2a&label=release" /></a> |
| 17 | + <img alt="macOS Apple Silicon" src="https://img.shields.io/badge/macOS-Apple%20Silicon-1b1d18?logo=apple&logoColor=white" /> |
| 18 | + <img alt="Local first" src="https://img.shields.io/badge/gateway-local--first-247454" /> |
| 19 | + </p> |
| 20 | +</div> |
| 21 | + |
| 22 | +<p align="center"> |
| 23 | + <img src="./docs/images/status.png" width="400" alt="ReRouted status panel" /> |
| 24 | + <img src="./docs/images/route-editor.png" width="400" alt="ReRouted route editor" /> |
| 25 | +</p> |
| 26 | + |
| 27 | +## One URL. The routing decision lives somewhere sane. |
| 28 | + |
| 29 | +Your editor should not need to know which account still has quota, which provider is having a bad morning, or which model you want to try next. |
| 30 | + |
| 31 | +ReRouted gives compatible chat-completions clients the same local contract: |
| 32 | + |
| 33 | +```text |
| 34 | +Base URL http://127.0.0.1:4949/v1 |
| 35 | +API key rr-your-generated-key |
| 36 | +Model coding |
| 37 | +``` |
| 38 | + |
| 39 | +`coding` is a route you own. Put your preferred model first, another account second, and a backup provider third. When an upstream rate-limits, times out, or returns a retryable failure before output begins, ReRouted advances through the route without changing the URL or model name your client uses. |
| 40 | + |
| 41 | +The promise is deliberately focused: ReRouted exposes model discovery and OpenAI-style chat completions. It is a routing layer, not a clone of every OpenAI API. |
| 42 | + |
| 43 | +## Why ReRouted exists |
| 44 | + |
| 45 | +| Without ReRouted | With ReRouted | |
| 46 | +| --- | --- | |
| 47 | +| Provider URLs and credentials are repeated across tools | One localhost URL and one generated gateway key | |
| 48 | +| A model name hard-codes a provider or account | A named route describes intent: `coding`, `fast`, `review` | |
| 49 | +| Quota means stopping to edit settings | The next route member is attempted automatically | |
| 50 | +| Multiple OAuth accounts are managed by hand | OAuth accounts share a provider pool and fall through in order | |
| 51 | +| Requests and failures are scattered | Activity, quota, token counts, and logs live in the menu bar | |
| 52 | + |
| 53 | +No hosted control plane. No account with ReRouted. No Dock icon. The gateway and panel run together on your Mac. |
| 54 | + |
| 55 | +## How it works |
| 56 | + |
| 57 | +```text |
| 58 | + editor / agent / script |
| 59 | + | |
| 60 | + | POST /v1/chat/completions |
| 61 | + | model: "coding" |
| 62 | + v |
| 63 | + 127.0.0.1:4949/v1 |
| 64 | + | |
| 65 | + v |
| 66 | + ReRouted route |
| 67 | + 1. primary model |
| 68 | + 2. second account |
| 69 | + 3. backup provider |
| 70 | + | |
| 71 | + v |
| 72 | + normalized OpenAI-style response |
| 73 | +``` |
| 74 | + |
| 75 | +Routes support two strategies: |
| 76 | + |
| 77 | +- **Fallback:** try members in the order you chose. |
| 78 | +- **Round robin:** rotate the starting member on each request, then retain fallback through the rest. |
| 79 | + |
| 80 | +Timeouts and retryable `408`, `429`, and `5xx` responses can advance the route. Streaming failures are inspected before output begins; once client-visible output has started, ReRouted does not replay the request behind the client's back. |
| 81 | + |
| 82 | +## What connects |
| 83 | + |
| 84 | +- **OAuth accounts:** ChatGPT, Claude, Antigravity, and xAI. |
| 85 | +- **API-key presets:** OpenRouter, NVIDIA NIM, Cloudflare, and GLM Coding. |
| 86 | +- **Custom upstreams:** any service that exposes the OpenAI chat-completions shape ReRouted expects. |
| 87 | +- **Local credential discovery:** supported credentials already stored in known files or the macOS Keychain can be imported instead of re-entered. |
| 88 | +- **Multiple accounts:** connect more than one account for the same provider and use shared or account-specific model routes. |
| 89 | + |
| 90 | +OAuth accounts and keyed providers can live in the same route. ReRouted handles request translation and normalizes supported upstream responses back into the shape your client expects. |
| 91 | + |
| 92 | +ReRouted is an independent project and is not affiliated with or endorsed by any upstream provider. |
| 93 | + |
| 94 | +## Quick start |
| 95 | + |
| 96 | +### 1. Install |
| 97 | + |
| 98 | +[Download ReRouted 0.3.1 for Apple Silicon](https://github.com/gitcommit90/rerouted/releases/download/v0.3.1/ReRouted-0.3.1-arm64.dmg), open the DMG, and drag ReRouted to Applications. |
| 99 | + |
| 100 | +The macOS release is Developer ID signed, notarized by Apple, and stapled for a normal Gatekeeper launch. |
| 101 | + |
| 102 | +After the first install, ReRouted checks stable releases in the background. You can also use **Settings → Software updates** at any time; new versions download inside the app and install on restart. |
| 103 | + |
| 104 | +### 2. Connect what you already use |
| 105 | + |
| 106 | +Import a detected credential, complete an OAuth flow, or add an API key. ReRouted keeps OAuth accounts and keyed providers side by side. |
| 107 | + |
| 108 | +### 3. Create a route |
| 109 | + |
| 110 | +Name it for the job rather than the vendor: |
| 111 | + |
| 112 | +```text |
| 113 | +coding |
| 114 | + 1. preferred account and model |
| 115 | + 2. second account |
| 116 | + 3. backup provider |
| 117 | +``` |
| 118 | + |
| 119 | +### 4. Test the route, then point your client at localhost |
| 120 | + |
| 121 | +Use a direct request to verify the gateway and route: |
| 122 | + |
| 123 | +```bash |
| 124 | +curl http://127.0.0.1:4949/v1/chat/completions \ |
| 125 | + -H "Authorization: Bearer rr-your-generated-key" \ |
| 126 | + -H "Content-Type: application/json" \ |
| 127 | + -d '{"model":"coding","messages":[{"role":"user","content":"Say hello in three words."}]}' |
| 128 | +``` |
| 129 | + |
| 130 | +Then enter the same base URL, gateway key, and route name in a configurable client that supports OpenAI-style chat completions. Setting names vary by client. Switch providers, accounts, models, and route order inside ReRouted; leave the client configuration alone. |
| 131 | + |
| 132 | +## The menu-bar control plane |
| 133 | + |
| 134 | +- **Status:** gateway health, endpoint, latest route, and recent traffic. |
| 135 | +- **Accounts:** OAuth sessions, imported credentials, API keys, and model availability. |
| 136 | +- **Routes:** named fallback or round-robin model groups with explicit ordering controls. |
| 137 | +- **Activity:** requests, failures, token counts, route choices, and account usage. |
| 138 | +- **Quota:** provider-specific subscription windows where supported. |
| 139 | +- **Settings:** gateway keys, localhost or network binding, login launch, security controls, and signed software updates. |
| 140 | + |
| 141 | +The gateway continues running when the panel is hidden. Quitting ReRouted stops both. |
| 142 | + |
| 143 | +## API surface |
| 144 | + |
| 145 | +| Endpoint | Purpose | |
| 146 | +| --- | --- | |
| 147 | +| `GET /` | Same unauthenticated local health response as `/health` | |
| 148 | +| `GET /health` | Local gateway health and listening port | |
| 149 | +| `GET /v1/models` | Enabled direct models and named routes | |
| 150 | +| `POST /v1/chat/completions` | Streaming or non-streaming routed completions | |
| 151 | + |
| 152 | +Requests require a generated bearer key except for `/` and `/health`. ReRouted currently targets clients that use OpenAI-style chat completions; embeddings, images, audio, and the rest of the OpenAI platform API are outside its scope. |
| 153 | + |
| 154 | +## Local-first, with the boundaries stated plainly |
| 155 | + |
| 156 | +- The gateway binds to `127.0.0.1` by default. |
| 157 | +- Configuration, credentials, request metadata, usage, and logs are stored locally. |
| 158 | +- Prompt bodies are not intentionally persisted. |
| 159 | +- Local config and usage files are written with restrictive permissions where supported. |
| 160 | +- Provider credentials are not encrypted at rest. |
| 161 | +- Requests and the credentials needed to authorize them are sent to the upstream services you choose. |
| 162 | +- Enabling network access binds the gateway to `0.0.0.0`; only do that on a network you trust. |
| 163 | + |
| 164 | +## Build from source |
| 165 | + |
| 166 | +Requires Node.js 22.12 or newer. Packaging requires macOS and produces an Apple Silicon DMG. |
| 167 | + |
| 168 | +```bash |
| 169 | +git clone https://github.com/gitcommit90/rerouted.git |
| 170 | +cd rerouted |
| 171 | +npm ci |
| 172 | +npm test |
| 173 | +npm start |
| 174 | +``` |
| 175 | + |
| 176 | +Package the macOS app and DMG: |
| 177 | + |
| 178 | +```bash |
| 179 | +npm run package:dmg |
| 180 | +``` |
| 181 | + |
| 182 | +The implementation is intentionally small: Electron, Node's built-in HTTP server, and a vanilla HTML/CSS/JavaScript renderer. See [the architecture document](./docs/architecture.md) for the runtime, routing, persistence, and packaging details. |
| 183 | + |
| 184 | +Questions and bug reports are welcome in [GitHub Issues](https://github.com/gitcommit90/rerouted/issues). |
| 185 | + |
| 186 | +## Current release |
| 187 | + |
| 188 | +ReRouted `0.3.1` ships for Apple Silicon macOS with a Developer ID signature, stapled Apple notarization tickets, and in-app updates backed by stable GitHub Releases. The public API is intentionally limited to health, model discovery, and chat completions; a published third-party client compatibility matrix is still forthcoming. |
| 189 | + |
| 190 | +ReRouted is released by [Public Bytes](https://publicbytes.org), a nonprofit building practical technology for public good. |
| 191 | + |
| 192 | +## Thanks |
| 193 | + |
| 194 | +- Thanks to [9Router](https://github.com/decolua/9router) and its contributors for pushing local multi-provider routing forward. |
| 195 | +- Thanks to [CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) and its contributors for advancing local provider connectivity and the ecosystem around it. |
0 commit comments