ds-router
Keeps your Hermes agent on whichever LLM provider still has quota.
You have several subscriptions that all serve the same open models. Each one has its own rolling usage windows that throttle you at different times. ds-router reads every provider's live quota, works out which ones are about to run out, and points Hermes at a healthy one.
Works with any providers that expose a usage API. Shipped with support for four:
| provider | plan | price | quota windows | |---|---|---|---| | CommandCode | GOAT | $10/mo | $14 / 5h, $35 / week, $70 / month | | OpenCode Go | Go | $10/mo | session, weekly, monthly | | Ollama Cloud | Pro | $20/mo | $60 / month credits | | ClinePass | Agent/Pass | $9.99/mo | 5-hour, weekly, monthly |
Total: about $40-50/month, and the plans' own allowances add up to roughly $190 a month at their list rates. That gap is the reason to run the router: it is what lets you actually use all of it instead of hammering one subscription until it throttles you.
What it is
Four moving parts, none of them a proxy:
- router.py polls each provider's usage API and scores the readings by burn
rate; how fast a window is draining against how much of it remains; rather than by raw percent, which is what makes a 5-hour window and a monthly window comparable.
- ds-switch applies that decision by rewriting three keys in Hermes' own
config (model.provider, model.default, model.baseurl). The first time it writes, it saves a one-time backup of your original config for undo.
- A timer (a systemd user unit on Linux, a launchd agent on macOS) re-runs
ds-switch every 15 minutes, so the choice tracks quota as it drains. Every tick logs what it decided and why.
- placement.py is for many sessions at once: it gives each open session its
own provider, so a fleet does not pile onto one provider's concurrency cap.
What it is not: there is no HTTP server, no proxy, and no per-request routing anywhere in this tool. Nothing sits in the request path; Hermes keeps sending requests to the provider it was pointed at, and mid-turn failover is Hermes' own fallback chain, not this. The choice is made when a session starts (or on the timer's rewrite), never inside a request.
Runs on Linux (systemd user units, exercised end to end) or macOS (launchd; see Limits; supported by construction, never loaded on a Mac). Needs Python 3.10+ with PyYAML and the hermes CLI. Providers without a usage API work as plain Hermes fallback entries but are never routed to.