Skip to main content

ccr: the cheapest sufficient model for Claude Code

CI License: MIT Python 3.10+ Built for Claude Code Rule-based Last commit

ccr routes each Claude Code task to the cheapest model and effort level that should be enough for it, so your subscription goes further without you picking models by hand. You keep typing plain claude.

ccr: T2 (sonnet/medium) — touches app/payments/ledger.py, 2 dependents, no tests found,
critical path: payments. Delegate implementation to ccr-implement; use Explore (haiku) for search.

Screenshots

ccr explain shows the tier and exactly why, without running anything:

ccr explain output

ccr dashboard writes a self-contained HTML report of tiers, success rate, estimated savings and every routing decision:

ccr dashboard

How it works

For every prompt, a hook decides a tier using local, rule-based checks (no tokens spent, under half a second):

  1. Classify the task: question, bugfix, feature, refactor, migration, security, and so on.
  2. Locate the code it touches, using a local tree-sitter code graph (.ccr/graph.db).
  3. Score risk: dependents, complexity, test coverage, churn, critical paths (auth, payments, migrations, infra, secrets) and notes in CLAUDE.md or memory.
  4. Adjust with your team's past outcomes and your weekly usage.
  5. Hint Claude with one line, which delegates the work to a tiered ccr-* subagent.
Tier Model / effort Agent Typical work
T0 haiku / low ccr-quick questions, lookups, typos, renames
T1 sonnet / low ccr-small tests, clear bug fixes, small edits
T2 sonnet / medium ccr-implement features, refactors, perf work
T2H sonnet / high ccr-senior risky or complex multi-file changes
T3 opus / high ccr-architect migrations, security, unclear bugs, design
T4 opus / xhigh ccr-critical critical-path changes only

Install

Requires Python 3.10+, git, and Claude Code (claude) on PATH.

uv tool install claude-code-router
# or
pipx install claude-code-router
# or
pip install claude-code-router

ccr --help

The package is claude-code-router; the command it installs is ccr. To install the latest unreleased code instead, use uv tool install git+https://github.com/ai-solution-architect-roadmap/claude-code-router.git.

Name clash: the npm package claude-code-router also installs a ccr command. Install this tool so ccr on your PATH is this one. ccr doctor checks.

The .claude/ folder in this repo is a working example of what ccr init generates (agents and settings), because ccr routes its own development.

Quick start

cd your-project
ccr init --dry-run     # show the exact diff of every file it would touch; writes nothing
ccr init               # apply it (modified files are backed up to .ccr/backups/)
ccr doctor             # check the setup
ccr explain "Fix the off-by-one in paginate() in app/api/pagination.py"   # preview a decision
claude                 # work as usual

Re-running ccr init is safe. To skip routing for one prompt, put !noroute at the end of it.

Commands

Every command accepts --path DIR (project root, default .) and --help. Run ccr --help for the list.

Setup

ccr init installs settings (model, hooks, status line), the ccr-* agents and .ccr/config.yaml. Safe to re-run; modified files are backed up to .ccr/backups/.

Option Effect
--dry-run Print the exact diff; write nothing
--force Override your model/effortLevel and regenerate edited ccr agent files (with backups)
--local Write settings to .claude/settings.local.json (personal, uncommitted)
--no-statusline Do not install the status line relay
--no-graph Skip building the code graph
--command CMD Command prefix the hooks use to run ccr (default: auto-detect)
ccr init --dry-run
ccr init --local --no-statusline

ccr profile [PATH] prints the detected languages, frameworks, file count and LOC, and the suggested session default model/effort.

Option Effect
--apply Write the suggestion into .claude/settings.json (overrides existing values)
--dry-run With --apply: print the diff only
--local With --apply: write .claude/settings.local.json instead

ccr doctor checks the environment and project setup. --verbose logs details to .ccr/local/ccr.log.

ccr graph builds or refreshes the code graph incrementally, or inspects it.

Option Effect
--rebuild Drop and rebuild the graph
--stats Show graph statistics
--query SYMBOL Look up a symbol
--offline Never download tree-sitter grammars

Routing

ccr explain "<task>" shows the tier, scores, touched files and reasoning. Runs nothing. --json gives machine-readable output; --llm asks haiku (your claude CLI) when rule confidence is low.

ccr explain "Fix the off-by-one in paginate() in app/api/pagination.py"

ccr run "<task>" runs the task headlessly with claude -p at the routed tier and climbs one tier if the attempt fails. Omit the task or pass - to read it from stdin.

Option Effect
--tier T0..T4 Start at this tier instead of the routed one
--max-turns N Turn cap per attempt (default run.max_turns)
--max-budget-usd X Spend cap for the whole run, all attempts
--max-escalations N Tiers to climb after a failure, 0 to 4 (default 1)
--test-command CMD Shell command that must exit 0 for success (default run.test_command)
--no-test Skip the test command
--permission-mode MODE Passed to claude, e.g. acceptEdits
--no-llm Rules only; never ask haiku to help classify
--dry-run Show the routing and the command; run nothing
--json Print a JSON summary instead of the result text
ccr run "add a --dry-run flag to app/main.py" --test-command "pytest -q" --max-budget-usd 2

Feedback, stats and learning

ccr feedback [good|bad] marks the last routed task good or bad (a correction record is appended; history is never rewritten). With no verdict it shows the last task. Use --id PREFIX to target a task by id instead of the most recent one.

ccr stats shows usage, estimated savings, misroutes, tier distribution, and success and escalation rates per tier, area and task class.

Option Effect
--days N Only the last N days
--misroutes List each over- and under-routed task
--json Machine-readable output

ccr dashboard writes a self-contained HTML dashboard (charts, savings, misroutes, recent tasks). Options: --days N, --out FILE (default .ccr/local/dashboard.html), --open to open it in the browser.

ccr calibrate fits failure odds on the routing signals and compares them with the rules. Report only; it never changes routing. Needs about 30 decided tasks. --json for machine output.

ccr tune proposes config edits from misroute evidence as a diff. Nothing changes unless you pass --apply, which backs up the config first.

ccr shadow re-runs sampled deep-tier tasks at a lower tier in a throwaway git worktree to measure over-routing. Opt-in and costs real usage; without --yes it only prints the plan. Needs hooks.store_prompts.

Option Effect
--from-tier T Sample tasks routed to this tier or above (default T3)
--shadow-tier T Tier to try instead (default: one below the task's tier)
--sample N How many tasks to re-run, 1 to 50 (default 3)
--max-budget-usd X Total spend cap across the sample
--test-command CMD Must exit 0 for a shadow run to count as success
--yes Actually run

ccr export-benchmark writes a replay set from decided tasks with stored prompts to --out FILE (default ccr-benchmark.json). Replay it with uv run python scripts/bench_routing.py --prompts FILE.

Privacy

ccr purge deletes or scrubs locally stored prompts and shadow results. It shows what it would do first and deletes only with --yes.

Option Effect
--prompts Stored prompts and decisions
--shadow Shadow-run results
--older-than N Only prompts older than N days
--redact Re-scrub existing stored prompts
--yes Actually delete

Internal (called by Claude Code, not by you)

  • ccr hook session-start|prompt|stop is the hook entry. It reads hook JSON on stdin and always exits 0.
  • ccr statusline is the status line relay. It records model, effort and rate limits, and prints a short line. --wrap "<cmd>" runs your own status line command and prints its output.

Configuration

ccr init creates .ccr/config.yaml; commit it. Any key you leave out uses the default. You can change the tiers, class base tiers, critical paths and terms, risk weights, budget limits and learning thresholds. See the full reference.

Accuracy

scripts/bench_routing.py replays a labelled prompt set against a fixture project with no API calls. It reports under-routed and over-routed prompts and the estimated cost against all-Opus and all-Sonnet baselines. The labels are judgment calls, so edit them to match your own work. It measures routing quality, not answer quality.

Routing is strongest for clearly worded prompts in a supported language with a fresh graph. It is weaker for prompts that name no code and for projects with unusual folder names until you add your own critical_paths, critical_terms and hard_terms.

Privacy

All routing decisions run locally. The only model call ccr makes on its own is an optional, opt-in classification by haiku through your own claude CLI. Local state lives in .ccr/.

Documentation

The reference covers the full configuration, team workflow, status line and budget pressure, hooks and fail-open behavior, headless runs, feedback and learning, privacy, limitations and troubleshooting.

Development

See CONTRIBUTING.md and the changelog.

uv sync
uv run pytest
uv run python scripts/bench_routing.py

License

MIT

Metadata

Release files for claude-code-router 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for claude-code-router 0.1.1
File Size Uploaded
claude_code_router-0.1.1.tar.gz 991.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for claude-code-router 0.1.1
File Interpreter ABI Platform
claude_code_router-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 1.2 MB

Release files / claude_code_router-0.1.1.tar.gz

Download URL claude_code_router-0.1.1.tar.gz
Size 991.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7865393e8ba30397f6cd3f9890d2fc5759ec96febca97d521e3af5dd1ee30dd2
BLAKE2b-256 checksum
How to use checksums
646421588b1f5f4d769be75c4fce2792369c98531111645f7d364275cd2e3651
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / claude_code_router-0.1.1-py3-none-any.whl

Download URL claude_code_router-0.1.1-py3-none-any.whl
Size 180.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5757a0f9ebcae219f8b79c5c8eefb056dba1b4dab53f7542a809f6f016b90dfd
BLAKE2b-256 checksum
How to use checksums
e3b739e97a5d05332dd0003522c9870deb845d5f8f8605c57b1dcca14fcaae5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page