cc-swap
Every LLM you can drop into Claude Code (or any Anthropic Messages SDK) with one env-var swap. Live pricing, context window, cache discount, and ready-to-copy ANTHROPIC_BASE_URL setup.
What
Anthropic, z.ai, Moonshot, and Alibaba's DashScope all expose Anthropic-Messages-protocol endpoints — meaning you can point Claude Code or any Anthropic SDK at them by changing two env vars (ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN) and nothing else. Other providers (OpenAI, Google, DeepSeek, MiniMax, ...) need a translation gateway like LiteLLM in front. cc-swap is a live, public, no-auth board that lists every model under both buckets — with current pricing, cache discount, context window, and a copy-pasteable setup snippet.
Why
- Claude Opus 4.7 is
$5/$25per MTok. Sonnet 4.6 is$3/$15. Teams burn hundreds of dollars per developer per month on Claude Code. - Several providers now ship drop-in Anthropic-compatible endpoints at a fraction of the price. Knowing which models are eligible — and what their cache-read discount is — is the difference between a $500/mo and $50/mo coding stack.
- Provider docs, blog posts and GitHub gists are scattered. Pricing changes weekly (Qwen dropped ~30% in late May; OpenAI raised long-context pricing). cc-swap is a single, live source.
How (data)
| Source | URL | Used for | Refresh |
| --- | --- | --- | --- |
| OpenRouter Models API | https://openrouter.ai/api/v1/models | Every model's id, name, context, prompt/completion/cache-read pricing | every 30 minutes (cron /30 *) |
| Static compat map | data/compat_tiers.json | Anthropic-protocol compatibility tier + base URL + provider docs link | hot-reloadable on POST /api/refresh |
The compat map's base URLs and docs URLs are publicly documented facts (e.g. https://api.z.ai/api/anthropic, https://docs.z.ai/guides/develop/claude/introduction) sourced from each provider's docs. They are not synthesized data — they're configuration constants, like saying "Postgres listens on 5432". All changing data points (pricing, context window, cache-read price, model presence/removal) come from the OpenRouter live fetch.
No mock data. No seed data. No Math.random. If OpenRouter is unreachable on boot, the table is empty until the first successful refresh.
Endpoints
All public — no authentication. Reads and the manual refresh trigger are equally open.
| Method | Path | Notes |
| --- | --- | --- |
| GET | /cc-swap/ | Single-page board (vanilla JS, no framework) |
| GET | /cc-swap/health | Orchestrator smoke-check; returns 200 with model count + last refresh |
| GET | /cc-swap/api/models | All models, with computed session_cost_usd and cache_discount_pct. Query: ?compat=native,gateway&provider=Anthropic,z.ai (Zhipu)&min_context=200000&sort=session_cost&limit=200 |
| GET | /cc-swap/api/model/:id | One model + last 30 days of price points |
| GET | /cc-swap/api/stats | Counts by tier and provider, cheapest native, cheapest gateway, last refresh |
| GET | /cc-swap/api/compat | The loaded compat-tier map (for transparency / debugging) |
| GET | /cc-swap/api/refresh-log | Last 50 refresh attempts |
| POST | /cc-swap/api/refresh | Manual refresh. Mutex-guarded; rate-limited server-side to 1 / 60 seconds |
Compat tiers
| Tier | Meaning |
| --- | --- |
| native | Provider ships a public Anthropic Messages protocol endpoint. Drop-in via ANTHROPIC_BASE_URL only. |
| gateway | No native Anthropic endpoint — bridge via LiteLLM, Vercel AI Gateway, or OpenRouter's anthropic-compat shim. |
| unknown | Provider not yet in data/compat_tiers.json. Falls through here. |
Synthetic session cost
For ranking purposes, every model gets a "session cost" = the cost of one typical Claude Code session:
session_cost_usd = (cache_read_per_mtok ?? prompt_per_mtok) * 0.18 // 180K cached input
+ prompt_per_mtok * 0.02 // 20K fresh input
+ completion_per_mtok * 0.03 // 30K output
This is a sorting lever, not a guarantee for any specific workflow — but it surfaces the bang-for-buck winners that pure input-price sorts miss (cache-heavy agent loops benefit massively from high cache discount, regardless of headline input price).
Run
npm install
cp .env.example .env
npm start
# open http://127.0.0.1:4903/cc-swap/
Requires Node 18+ (for global fetch) and better-sqlite3 build dependencies.
Environment
| Var | Default | Notes |
| --- | --- | --- |
| PORT | 4903 | HTTP port |
| BASE_PATH | /cc-swap | Mount prefix (must match nginx route) |
| DB_PATH | ./cc-swap.db | SQLite file (WAL mode) |
| REFRESH_CRON | /30 * | UTC |
| OPENROUTER_URL | https://openrouter.ai/api/v1/models | Override only for testing |
No API keys required. OpenRouter /models is anonymously fetchable.
File layout
cc-swap/
server.js # express bootstrap, helmet, compression, cron, boot refresh
db.js # better-sqlite3 (WAL) + migrations
fetchers/openrouter.js # the fetch/classify/upsert worker
routes/api.js # all /api/* handlers
data/compat_tiers.json # static prefix -> compat-tier map (provider docs sourced)
public/
index.html
app.js # vanilla JS SPA
style.css # dark theme
package.json
.env.example
README.md # this file
CLAUDE.md # tips for future Claude Code sessions
SPEC.md # original product spec
DEPLOY_MANIFEST.json # RNDLAB orchestrator manifest
License
MIT.