An Opus-run dev got no verification and no message, so silence meant both "still verifying" and "will never verify" (SAFETY-135 waited overnight, SAFETY-126 8 h). Verdicts were also labelled with the routing choice, not the model the run used. - Every dev hand-back posts one line at once: "[model-router] Tn verifying on Opus..." (a verdict follows), or "[model-router] Tn no verification: dev ran on Opus. Go straight to review." A run that ends with an error or names no clone says so. - Each round is decided and labelled by the model the run reported (its end usage), the routing choice only as fallback. A difference is shown as "(routed to X, ran on Y)", also on later rounds. - 8 new tests; each new rule was also broken on purpose and caught, apart from one equivalent change. Version 0.4.6. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MdqPWvuDpbpRvDEdURoAwo
3.4 KiB
3.4 KiB
model-router
A Claude Code plugin that picks a model for every subagent, checks dev work on a second model before it reaches a PR, and estimates what that saved compared with running everything on Opus.
What it does
| Step | Behaviour |
|---|---|
| Route | Dev agents run on Sonnet when the brief decides the approach (Expected / acceptance criteria), on Opus when the design is still open. Review and test agents keep the model they are given (Opus when none). |
| Verify | When a dev agent below Opus finishes a round, the router diffs its clone against the merge base, runs the test command in that clone, and has Opus judge the change. |
| Hand-back line | Every dev hand-back gets one line at once: [model-router] Tn verifying on Opus... (a verdict follows), or [model-router] Tn no verification: dev ran on Opus. Go straight to review. Decided by the model the run actually used, not only the routing choice; a difference is shown as (routed to X, ran on Y). |
| On FAIL | 1st: resume the same agent with the issues. 2nd: a new agent one model up, in the same clone. After that: handed back to the manager. |
| Not verified | A test timeout, a test command that cannot run, a missing clone or merge base, or a verdict that cannot be read even after asking once more: reported as NOT VERIFIED, never as a FAIL. |
| Savings | /router savings prices every run on the model it ran on and compares it with the same tokens on Opus 5.5. |
Briefs
Every dev, review and test brief carries one line:
Clone: /home/homelab/projects/goodwe/clones/<TICKET>-dev/
Add (Role: dev|review|test) when the path does not end in the role. Tickets with extra parts (OPT-11-P4) are fine. Name the base branch (Base branch: release/1.0).
Install
/plugin marketplace add <this repo's git URL>
/plugin install model-router@model-router
Or for development: claude --plugin-dir /path/to/model-router.
Settings (/config)
| Setting | Default | Notes |
|---|---|---|
testCommand |
empty | Run in the agent's clone; output goes to the verifier |
testTimeoutSec |
1800 | Wrapped in GNU timeout --verbose; a timeout is NOT VERIFIED |
defaultBaseBranch |
release/1.0 |
After the PR lookup and the brief's own base branch |
prBaseCommand |
empty | Optional command that prints the PR's base branch |
maxRewrites |
2 | Failed verdicts before handing back |
safetyPatterns |
control loop, rs485, ... | Marks tasks as critical in the log |
respectExplicitModel |
false | Keep a named model on agents without a role |
allowFable |
false | Rewrite on Fable after Opus fails |
prices |
empty | JSON price overrides, USD per MTok |
Commands
/router: recent decisions, verdicts and savings/router savings [Tn]: the full savings table, or one task/router clear: reset log, records and costs
Tests
claude plugin validate .
claude plugin test .
62 tests. Every routing, verification, cost and timeout rule was also checked by breaking it on purpose (66 mutations in v0.4.4, plus 13 for the verdict reader in v0.4.5 and 12 for the hand-back line in v0.4.6; all caught by a test).
Known limits
- Savings are an upper bound: Opus may need fewer tokens than the cheaper model did.
timeoutstops thedockerclient, not the container: name the container and remove it in atrapin the test command.- An Opus rewrite is not verified; the PR review covers it.