Every check passed. The model changed anyway.
Model IDs are not in a lockfile. A hosted model can be retired, re-routed or repriced while your code and CI stay green. Swapcheck scans your repo, tells you what is changing and when, tests what you could move to on your own cases, and opens a PR with the evidence.
or uvx swapcheck. Run it inside a project. Needs no keys and spends nothing to scan.
model = "gemini-2.5-pro"
git diff: 0 files changed
- lint
- types
- unit
- e2e
- deploy
Billed at the replacement's rates. Calls keep succeeding.
gemini-2.5-pro re-routes to gemini-3.8-flash. Nothing fails, so nothing tells you.
Dated changes, none of them in your diff
| Date | Model or API | Change | What happens |
|---|---|---|---|
| in 19 days | claude-sonnet-4-5-20250929 |
Retires | Requests fail. |
| in 20 days | gemini-2.5-proto gemini-3.8-flash |
Re-routes | Calls keep succeeding on a different model, at the replacement's rates. |
| 21 days ago | anthropic-version: 2026-10-21 |
Parameters | temperature, top_p and top_k removed. Requests using them return 400s. |
From an announcement to a pull request
One line, five stops. Only test spends money, and it shows you the maximum first.
-
Registry
A free, signed list of what providers announced, with a source link for each entry.
scanFinds model IDs in TS, JS, Python and config. Writes
models.lock.watchCompares the lock to the registry. Fails CI inside your window.
findShortlists models that do what your calls do and your policy allows.
testRepeated runs on your cases, compared against noise.
bumpEdits the IDs, drops parameters the target rejects.
-
Pull request
swapcheck runs the scan. The GitHub Action can run them on a schedule.
find
Many models in. Five out. One tested.
The registry can tell you what exists. Only your cases can tell you what works for you, so the shortlist is where the listing stops and the testing starts.
- Registryevery model it lists
- Capabilitytools, JSON, vision, context
- Policyproviders, regions, licence, price
- Retirementnot scheduled to go away itself
- Shortlistthe top five, each with a reason
- CHANGED
- REGRESSED
- NO CHANGE DETECTED
- REGRESSED
- NOT ENOUGH EVIDENCE
test
A difference has to survive the maths, then happen again
The same prompt gives different answers from one run to the next, so one run of each model proves nothing.
- Run each case several times on both models.
- Test each case with Fisher's exact test, then correct across the suite with Benjamini-Hochberg.
- Re-run anything flagged on a fresh sample. A drop that does not repeat does not count.
passed failed. Each dot is one run.
refund-policy fell from 5 of 5 to 0 of 5 (p = 0.008, q = 0.063), then passed 1 of 5 on a fresh sample (p = 0.024). The drop happened twice, so it counts. Exit code 1.
Four verdicts. None of them is "safe".
Swapcheck only knows what your cases cover. A clean result means nothing moved on those cases, at that sample size, on that day.
- NO CHANGE DETECTED
- Nothing differed beyond noise on your cases. It is not a guarantee about anything your cases do not test.exit 0
- CHANGED
- Check results, tool calls or token use moved beyond noise, with no confirmed drop in pass rate. Read the report and decide.exit 0
- REGRESSED
- At least one case dropped, and dropped again on a fresh sample. CI fails.exit 1
- NOT ENOUGH EVIDENCE
- Over 20% of calls failed, the budget ran out, or there were fewer than six usable cases. It will not guess.exit 3
What it looks like on your screen
Scanning, watching and finding are free. Testing spends your provider credit, after showing the most it could cost.
npx @allthingsai/swapchecknpx @allthingsai/swapcheck watch --fail-within-days 30npx @allthingsai/swapcheck test --to example-model-a,example-model-bnpx @allthingsai/swapcheck bump claude-sonnet-4-5-20250929 --to example-model-b --open-prexample-model results are made up for this replay.
It runs on your machine, with your keys
There is no Swapcheck server to send anything to. The only network calls are the registry fetch, your model providers, and the GitHub API when you ask for a PR.
- telemetry
- none
- hosted service
- none
- api keys
- read from environment variables, redacted from all output
- tool calls
- recorded and mocked, never executed
- scanned code
- read as text, never run
- registry
- Ed25519 signed, public key pinned in the client
- releases
- published to npm and PyPI from GitHub Actions, with provenance
- spending
- maximum cost shown first; refused without
--yesoff a terminal
Two other open-source tools do this well
ModelBump and Modelpin got here first, and both publish measured accuracy, which Swapcheck has not done yet. Read from their READMEs on 2026-11-09. Swapcheck can import suites from either.
| Swapcheck | ModelBump | Modelpin | |
|---|---|---|---|
| Pick it when | You want every kind of provider change on one board, in TS or Python repos | You want Dependabot-style upgrades and prompts repaired for you | You want your app's real requests replayed and drift caught in CI |
| Runs on | Node 22 via npx; binary wheels via uvx | Python 3.12+ | Python 3.11+ |
| Watches for | Retirements, re-routes, alias moves, prices, parameters, capabilities | Retirements | Retirements |
| Registry updates | Signed snapshot, fetched daily, bundled fallback | Registry of provider retirement dates | Ships inside each release; can point at a newer file |
| Finds replacements | Shortlist by capability, policy and retirement | Uses the replacement the registry suggests | Names the vendor's successor; you choose the candidate |
| Statistics | Fisher exact, Benjamini-Hochberg, must repeat on a fresh sample | Sequential tests or fixed runs, with Benjamini-Hochberg | Exact permutation test, minimum effect size, must repeat on fresh runs |
| Repairs prompts | No | Yes, and verifies the fix | Not in its README |
| Opens the PR | Yes | Yes | No, by design |
| Free local models | Through OpenAI-compatible routes | Ollama by default | Through OpenAI-compatible hosts |
| MCP server | Yes | Not in its README | Not in its README |
| Published accuracy | Not yet | Scanner, judge and repair results | False-alarm and detection rates |
| Licence | Apache-2.0 | Apache-2.0 | Apache-2.0, open-core |
Nothing to sign up for
Run it once in a repo that calls a hosted model. It needs no keys and no config, and it spends nothing.
Node
npx @allthingsai/swapcheck
Python
uvx swapcheck
GitHub Action
- uses: allthingsN/swapcheck@v1
with:
fail-within-days: 30
MCP server
{ "mcpServers": { "swapcheck": {
"command": "npx", "args": ["-y", "@allthingsai/swapcheck", "mcp"]
} } }