BetaApache-2.0, Go

Your best model shouldn't do every job.

Downshift gives your coding agent the right model for each subagent, shorter output from clean commands, and, if you turn it on, only the code a change touches. No extra AI call to decide.

Replay of the 56 spawns in the 2026-10-15 trial. Totals measured, order interleaved.

Right model, shorter output, less to read.

  • RoutingCompleted on Claude Code

    Right model per subagent

    Mechanical subagent work goes to a smaller model; risky or unclear work keeps yours. A local hook decides, with no extra AI call.

    downshift try
    $ downshift try "rename userId to accountId…"
    assumed current: claude-opus-5-5…
    → small: opus → haiku
    why: trivial task, no risk, confident
    Real CLI output, 2026-10-21. Long lines trimmed.
  • CompactorOn by default

    Shorter clean output

    Passing test runs and clean builds reach the context in a line or two. Errors, stack traces and failing exits stay untouched.

    downshift compact
    $ go test ./internal/...
    Go test: PASS (3 packages ok) under …
    ok execwrap
    ok telemetry
    ok classify
    [downshift compact: compacted 205 to 119 bytes]
    Real CLI output, 2026-10-21. Long lines trimmed.
  • DCIOpt-in

    Less to read

    When you ask for a change, the agent gets only the code it touches. Opt-in; measured for size and speed, not for answer quality.

    downshift dci
    $ downshift dci impact HashSessionID
    Target:        HashSessionID
    Target Type:   Symbol
    Callers/Deps:  31
    - cmd/downshift/cmd_test.go:TestHook…
    Real CLI output, 2026-10-21. Long lines trimmed.

Who it is for

Downshift acts when your agent delegates a task. What you gain depends on how you pay.

  • Your agent delegates

    With Claude Code, each subagent can get a model sized for the job; Codex and Cursor are functional; OpenCode is beta. No subagents, nothing to switch.

  • You pay per token

    Mechanical work on a smaller model costs less per token. downshift report shows tokens per completed task, routed against control.

  • You are on a plan (Pro, Max, Team)

    There is no per-token bill. Downshift shows how many tokens ran on a smaller model. What that does to your plan limit is still being measured.

Not for: picking your main model, or deciding whether to delegate.

Where a coding agent spends more than it needs to.

Three leaks. Downshift is one Go binary, no daemon, and acts on each.

  1. Subagents inherit your most expensive model

    Renaming a variable gets the same model as an architecture review.

    Fix

    A local hook scores the task and rewrites the model only when it is confident. In doubt, your model stays.

    Status

    Completed on Claude Code

  2. Routine output fills the context

    A passing test run or a clean git status drops dozens of repeated lines into the context.

    Fix

    downshift compact shortens the clean run. Errors, stack traces and failing output stay byte for byte.

    Status

    Implemented, on by default

  3. The agent reads more code than the change needs

    To change one symbol it opens whole files and hunts for callers.

    Fix

    DCI packs only the affected symbols, under a byte cap.

    Status

    Opt-in. Measured for latency and bytes.

Completed: seen working end to end. Implemented: code, tests and at least one real observation. Opt-in: off until you turn it on. Reports show tokens and coverage, not dollars.

  1. 1

    Right model per subagent

    Completed on Claude Code

    Rewrites only the subagent's model, never your main session.

    QualifierAbout 53% fewer tokens per completed task in real use, routing and compactor combined (KiroCrew, 2026-10-21, 6 control tasks — directional).

  2. 2

    Compactor

    On by default

    Wraps git, go test and the other test and build tools listed in the docs; keeps the exit code.

    QualifierOnly a plain allowlisted command is rewritten; of the git commands, only git status shrinks, the rest pass through unchanged; automatic rewrite is Claude Code only.

  3. 3

    Code intelligence, DCI

    Opt-in

    Gives the agent only the code a change touches.

    QualifierBytes and latency measured; answer quality not measured.

  1. Several harnesses, honest levels

    One install sets up Claude Code, Codex and Cursor hooks; OpenCode is beta.

    QualifierCodex and Cursor are functional, OpenCode is beta.

  2. Guardrails Implemented

    Auth, payments, crypto and private data are never downshifted.

    QualifierDetection is pattern based, English and Portuguese; false-positive rate on real traffic is not measured.

  3. See and compare Implemented

    Switched, held or only observed, with the reason, plus routed against control.

    QualifierChild token usage is observed on Claude Code only; the report needs 20 completed tasks per group.

See Downshift in action

Pick a task to see the decision, or type your own to build the command and run it in your terminal.

Real decisions from the CLI on 2026-10-19, assuming claude-opus-5-5 as the current model. ~75% and ~50% are the price gap of one model swap at list price, not a saving on a session. This page builds the command; it does not run the classifier.

Rewritten

Stays on frontier

Original model kept

Task
rename the userId variable to accountId
Tier
  1. small
  2. mid
  3. frontier
Model move
opus → haiku
Price gap
~75%, price gap of one model swap (est., list price), not a session saving
Outcome
Rewritten
Why
trivial task, no risk, confident

Your command

downshift try '<your task>'

Type a task to fill in the command.

This page does not run the classifier. It only builds the command. The real decision runs locally in the CLI, on your machine. Up to 200 characters.

Clean output, smaller context.

Passing test runs and clean builds reach your agent in a line or two. Errors, stack traces, diffs and any failing exit stay exactly as they were.

Compactor is on by default. It runs routine commands through downshift compact, which keeps the exit code and shortens only output it can tell is clean. It wraps every git subcommand and the listed test and build tools (go, pytest, vitest, jest, tsc, cargo, playwright, cypress, phpunit, gradle, maven, flutter, dart, next build). Of the git commands, only git status shrinks; the rest pass through byte for byte.

Automatic rewrite works on Claude Code. In other harnesses your agent runs downshift compact -- <command> directly. This is not the /compact command: it never summarises your conversation.

On the synthetic test corpus (248 files), the 26 that compact shrink by 82.3% in bytes, the best clean ones by 91 to 97%. Across all 248, including failures built to stay raw, the cut is 23.7%. Bytes, not tokens, and not your command mix.

Turn it off with "exec": false in the config or DOWNSHIFT_EXEC=0.

Before and after, real runs

downshift compactor -- go test
RunBeforeAfterCut
Full suite4,4662,331−47.8%
Package 1752317−57.8%
Package 2619238−61.5%
Package 3471174−63.1%
Package 4278142−48.9%

Single runs, 2026-10-21, bytes.

How it works

Send the code a change touches, not the whole repo.

Ask for a change and the agent starts with the callers and symbols it can reach, packed under a byte cap, instead of opening whole files.

Run 1: downshift dci impact Route

Routepicks the tierrunTryReporttry commandcmd/downshift/try.goHandleClaude Code adapterinternal/adapters/claudecode/claudecode.goHandleCodex adapterinternal/adapters/codex/codex.goTestClassifierStabilitytestinternal/core/classifier_stability_test.go3500 B
Impact radius of Route in this repository, from downshift dci impact --json Route. Four callers. The dashed box stands for the packing budget (3500 bytes by default); the blocks are illustrative, not measured.

Opt-in (downshift dci enable). It finds the impact radius of a symbol and packs only the affected code. Go by AST; TypeScript, JavaScript, Python, Rust, PHP, Java and C# by pattern.

Benchmark: cold index 295 ms, warm p95 5.64 ms, packs 568 to 2,801 bytes.

Measured so far: size and latency. Not measured: whether answers get better. Read it as a way to send less, not proof of better answers.

Read the DCI docs

How a spawn gets its model.

Eight steps, all code in the repository. Your agent spawns a subagent; a local hook scores the task; guardrails check it; the hook rewrites the model or leaves it alone; telemetry records counts and timings.

  1. Harness

    The agent spawns a subagent

    Agent / Task

    The main agent delegates through its spawn tool: Agent or Task, spawn_agent, invoke_subagent. Downshift sees nothing until the harness fires its pre-tool hook.

  2. Downshift

    The hook starts

    runHookAdapter

    runHookAdapter reads the payload from stdin, capped at 1 MiB with a 2 s read timeout, sets a 1.5 s budget, and turns any panic into an unchanged spawn.

  3. Downshift

    The adapter reads the payload

    internal/adapters

    The harness adapter reads the task text, the model the child would run on and the session. It declares what the harness can do and holds no policy.

  4. Downshift

    The task is classified

    internal/classify

    Weighted signals in English and Portuguese give TRIVIAL, SIMPLE, MEDIUM or COMPLEX, which maps to a tier: small, mid or frontier. A prompt with no signal defaults to mid and abstains.

  5. Downshift

    The semantic step can only raise

    internal/fuse

    An in-process word-hash step may lift a hesitant class. It never lowers a tier, never boosts a prompt with no signal and never creates COMPLEX on its own.

  6. Downshift

    Floors and guardrails check

    selfcheck.go R1-R9

    The risk floor, guardrails R1 to R9 and the project floor in .downshift/policy.json run next. The session model list and the quota gate decide what can be written. Any hit means: keep the model.

  7. Downshift

    Rewrite or hold

    updatedInput

    If it is confident and safe, the hook returns updatedInput with only the model changed, plus reasoning_effort where the harness takes it. Otherwise the spawn goes through as asked. About 1 in 10 spawns is left unrouted on purpose, as the control group.

  8. Harness, then Downshift

    The subagent runs and is recorded

    events.jsonl

    The harness runs the child on the written model, or ignores the rewrite, which Downshift cannot control. Downshift then appends counts, hashes, timings and, on Claude Code, priced tokens to events.jsonl. No prompt text.

What never happens

  • No AI call to pick a model.
  • No prompt, task text or file path stored.
  • No rewrite when unsure.
  • No downshift of complex tasks or of auth, payments or secrets.
  • No blocked spawn because of an error: a bad payload, panic or timeout leaves the spawn unchanged.
  • About 1 in 10 spawns is left unrouted on purpose, as the control group.

Nine layers, each with its status.

Status is what the repository shows today, not what is planned. Implemented does not mean validated on every harness.

Right model, less noise

ClassificationScores the task text into TRIVIAL, SIMPLE, MEDIUM or COMPLEX, with no LLM call.Implemented
  • internal/classify: weighted signals in English and Portuguese
  • language guard
  • internal/fuse: hash semantic boost, raise-only

On blind test sets, tier accuracy is 40 to 53%, and most misses are abstentions that keep your model.

Model catalog and sessionKnows which models exist in your session, their tier, list price and whether one is explicit-only.Implemented
  • internal/catalog: tiers, list prices, aliases, explicit_only
  • session models from hook lists, session-models.json, discovery, or inferred from the current model on Claude Code

Prices are a dated snapshot, so savings are list-price estimates.

Routing hook per harnessRuns the same decision in every harness and writes the rewrite in that harness's own format.Implemented
  • one shared runner, runHookAdapter
  • adapters: claudecode, cursor, codex, opencode, antigravity, kirocrew

Claude Code is completed, Codex and Cursor are functional, OpenCode is beta, Antigravity is experimental, KiroCrew is functional.

Shell output compaction (downshift compact)git and the listed test and build tools. Keeps the exit code and compacts only what is unambiguously clean.On by default
  • shell exec wrapper; automatic rewrite on Claude Code only
  • "exec": false or DOWNSHIFT_EXEC=0 turns it off
  • downshift context compress, for pipes

Understand code

Code intelligence (DCI)Finds the impact radius of a symbol and packs only the affected code under a byte cap.Opt-in
  • downshift dci impact and dci inspect
  • Go AST, plus TypeScript/JavaScript, Python, Rust, PHP, Java and C# by pattern
  • BM25 ranking, 3500-byte default budget

Stay in control

GuardrailsHolds any change the evidence does not support and keeps the model you asked for.Implemented
  • R1 to R9 (R3 retired) in selfcheck.go
  • risk floors: secret, authz, crypto, payment, vuln, pii, destructive, concurrency, prompt injection
  • project tier floor in .downshift/policy.json, which only raises
  • quota and credit gate

The quota gate is implemented but not validated on every harness.

Rules it always follows

  • Local classification. Each task is scored on your machine with signals and a model catalog. No LLM call. Prompts are evaluated in memory and never stored.
  • Fail-open. Any error or missing capability leaves the spawn untouched. Downshift only changes the model and effort fields.
  • Doubt keeps your model. Unsure? The spawn keeps the model it asked for. Doubt never spends money, and a cheaper pick without confidence is held.
  • Risk floors. Payments, auth and secrets are protected. Migrating a payment webhook stayed on opus. Rotating production secrets kept its original model.
Telemetry, control group and reportsRecords what happened and compares routed spawns with an unrouted control.Implemented
  • events.jsonl: counts, hashes, timings
  • downshift stats, session and watch: switched, held or observed per spawn
  • downshift report: tokens per completed task, routed against control
  • 10% control group (DOWNSHIFT_CONTROL_SHARE)

Two controlled runs so far, both on mechanical tasks (2026-10-15 and 2026-10-21). report needs 20 completed tasks per group and compares tokens per completed task; child token usage is currently recorded on Claude Code only. stats and report print no dollar amounts.

Mods in Claude CodeMake the work visible: a progress bar with each subagent's Downshift state, a panel of subagents, a file tree and a dock to reopen them.Implemented
  • savvy-progress
  • filetree
  • downshift-dock
  • downshift-theme, optional

savvy-progress and filetree are vendored third-party mods; downshift-dock is original and tested only against a mock engine. None holds routing logic. setup installs them, but not the theme.

Real numbers. No marketing math.

KiroCrew real use + Claude Code four-arm trial, 2026-10-21. Two harnesses, independent evidence.

  • ~53%fewer tokens per completed task, routing and compactor, real useKiroCrew harness2026-10-216 control tasksOne session. Control group is thin; treat as directional, not definitive.
  • ~24%fewer tokens per accepted run, routing only, four-arm trialClaude Code46 runsone operator2026-10-2116% per run; 95% interval +2.1% to +46.7%. Routing only; Compactor savings are additional. State isolation bugs found in battery — number may change.
  • 12 of 12accepted in both routed arms (C and D)
  • 82.3%fewer bytes on the 26 of 248 corpus files that compactsynthetic fixtures23.7% across all 248your mix will differ
  • about1 in 10spawns left unrouted as a control group

Tokens per accepted run, four arms

2026-10-21, millions of tokens
  • A Opus fixed2.25M10 of 11 accepted
  • B opusplan2.00M10 of 11 accepted, no routing
  • C opusplan + routing1.52M12 of 12 accepted
  • D routing + Compactor1.46M12 of 12 accepted

Tokens = input + output + cache read + cache write, all models. Bar length relative to arm A.

Fewer tokens per accepted run, arm against arm

bootstrap 95% intervals
  • Routing (B−C)24.1%interval +2.1% to +46.7%. Per run, before charging failures: 16.5%, +0.6% to +29.7%. Includes the cost of one failed run in the opusplan arm (named constants, 2 of 3 accepted).
  • Routing + Compactor (B−D)26.8%interval +4.4% to +48.3%
  • Compactor alone (C−D)3.5%interval −14.8% to +19.4%, includes zero: not measurable in this part. The agents chained commands with “;”, which Compactor did not wrap until PR #424 (merged 2026-10-21).
  • Opus fixed against everything on (A−D)34.8%interval +19.1% to +52.5%
  • opusplan alone (A−B)11.0%interval −28.9% to +39.0%, includes zero

solid: interval excludes zero. hatched: interval includes zero.

Earlier trial (2026-10-15, list price)

Up to about 12% cheaper per run on the mechanical batch. One trial, one operator, three runs per cell, list price, Claude Code, 2026-10-15. 12 of 12 checks passed in both arms; checks verify structure, not quality.

Saving per task, routed against control

list-price estimate
  • Rename~33%all five subagents downshifted
  • Named constants~14%
  • Doc comments~10%the interval includes zero
  • Mirrored testsnoisenothing downshifted in 2 of 3 runs

solid: saving. hatched: interval includes zero, or noise.

List-price estimate. Bar length is relative to the largest saving.

What we have not shown

  • A saving on your plan limit. Still being measured.
  • Any saving from everyday use. Two controlled runs on mechanical tasks so far; nothing attributable.
  • Compactor's own effect on tokens in a run. Not measurable in part 1.
  • Routing on natural fixes that run tests. That is part 2.
  • That DCI gives better answers. We measured size and latency only.
  • Compaction on your own commands. The 82.3% is a synthetic corpus, in bytes.
  • That the model is honored in every harness. See the table below.
  • A false-positive rate for risk detection on real traffic.

Part 1 of 2: mechanical tasks. Part 2 (natural fixes that run tests) is next.

Read the four-arm write-upRead the A/B reportSee the corpus results

One router, six harnesses, honest levels.

The levels are what was observed, not what is planned. A rewrite emitted proves the hook answered; only the last column says whether the subagent ran on that model.

What each harness does with the rewrite

HarnessLevelModel rewriteSubagent used the modelCompactor
Claude CodeCompletedEmittedObserved, 2026-10-06Automatic rewrite; or run downshift compact -- <command>
CodexFunctionalEmittedInferred from the next spawn, not observedRun the command directly
CursorFunctionalEmittedUnconfirmed; discarded on Free and legacy ProRun the command directly
OpenCodeBetaAdapter ready; plugin in developmentNot observed yetRun the command directly
AntigravityExperimentalEmitted via an undocumented fieldObserved once, desktop 2.21.1Run the command directly
KiroCrewFunctionalBlock and retry (policy mode); no in-place rewriteNot recorded (block and retry path)Run downshift compact -- <command>

Compactor works in KiroCrew by calling the command directly (steering): 223 calls recorded on 2026-10-21. Compactor is a plain shell command, so it works in any harness. Only Claude Code rewrites it in automatically. Each harness routes its own models. Verified routing is Claude Code only; the others sit at the levels in the table. OpenRouter models are discovery only and are never routed.

claude-code · PreToolUse
hook    PreToolUse
rewrite updatedInput.model
keeps   every sibling field
doubt   original model kept
codex · PreToolUse
hook    PreToolUse
rewrite model, reasoning effort
keeps   every sibling field
doubt   original model kept
cursor · preToolUse
hook    preToolUse
rewrite updated_input.model
keeps   every sibling field
doubt   original model kept

PreToolUse on Agent and Task rewrites updatedInput.model. Rewrite observed on 2026-10-06.

PreToolUse on spawn_agent rewrites model and reasoning effort. Honor inferred, not observed.

preToolUse on Task rewrites updated_input.model. Honor unconfirmed on the build tested.

See the matrix

Install, preview, then write.

Setup shows the diff for every harness it finds before it writes anything, saves a timestamped backup, and --undo restores it.

  1. curl -fsSL https://raw.githubusercontent.com/tiagovilasboas/downshift/main/install.sh | sh

    Download the binary for your platform.

  2. downshift setup --dry-run

    Print the diff. Writes nothing.

  3. downshift setup --yes

    Write the hooks, with a backup. (Run downshift setup to be asked first.)

  4. downshift doctor

    Check the binary, the hooks, state and scores.

  5. downshift try "rename the userId variable"

    See the tier it would pick, and why.

  6. downshift setup --undo

    Restore the latest backup.

Binaries for macOS and Linux (amd64, arm64) and Windows (amd64). On Claude Code, setup also sets the main session to opusplan and plan mode, unless you pass --no-session-policy. It shows a diff first.

Open source, Apache-2.0.

Built in the open by Tiago Vilas Boas. The most useful contribution is a misrouted prompt: run downshift try with it, compare the tier with what you expected, and open an issue with both.

Frequently asked questions

Is Compactor the same as /compact?

No. /compact summarises your conversation. Compactor shortens the clean output of commands such as go test and git status, keeps the exit code, and leaves errors and failures exactly as they were.

Does it save my plan limit?

We do not know yet. Downshift shows how many tokens ran on a smaller model; the effect on a plan limit is still being measured.

What is sent anywhere?

Downshift stores no prompts or task text, only counts, hashes and timings, locally. Routing makes no network call. Your harness still sends the subagent's work to your model provider, as before. A detached refresh of public model scores sends no prompt and can be turned off with DOWNSHIFT_SCORES=off.

Will it route to the wrong model?

It rewrites only when it is confident and no guardrail objects; in doubt your model stays, and complex tasks or tasks touching auth, payments or secrets never go down. Run downshift session --why to see any decision, and report a misroute as an issue.

How do I undo it?

downshift setup --undo restores the latest backup of your harness config. Pause one session with downshift session --pause, or stop all rewriting with DOWNSHIFT_NO_ROUTE=1.

Which coding agents does it support?

Claude Code is completed. Codex and Cursor are functional, OpenCode is beta, Antigravity is experimental, KiroCrew is functional. The table above shows what was observed for each.

Is DCI safe to turn on?

It is opt-in and off until you enable it. We measured its size and speed, not whether answers improve, so try it on a branch and compare.

Where is the dashboard?

The web dashboard was removed on 2026-10-20. Use downshift report, downshift stats and downshift session, which show tokens and coverage in the terminal.

Does it call an AI to pick a model? Do I need another key?

No to both. Routing is local, from scored signals and a model catalog, with no extra model call and no key.

How much does it save?

In real use with routing and compactor combined, about 53% fewer tokens per completed task (KiroCrew harness, 2026-10-21, 6 control tasks — directional, not definitive). Routing alone: about 24% fewer tokens per accepted run in a four-arm Claude Code trial (46 runs, one operator, 2026-10-21; 16% per run, interval +2.1% to +46.7%). Compactor savings are on top of routing. Estimates are not invoices.

Is Downshift related to the React downshift library?

No. The React downshift library builds accessible autocomplete and dropdown components. This project is an unrelated Go tool that routes AI coding agent subagents to right-sized models.

Is it free?

Yes. Apache-2.0, a single Go binary, no daemon.

What changes on my machine?

Setup merges hooks into your harness config files, such as Claude Code's settings.json, and saves a timestamped backup first. A project can add an optional .downshift/policy.json tier floor. Nothing runs as a daemon.

Does it slow down a subagent spawn?

It adds one local process call, with no network and no LLM. In one traced run the binary exited in 30 ms. The hard limits are 2 s to read the payload and 1.5 s of hook budget, and an overrun or error leaves the spawn unchanged. On Claude Code it may also wait up to 400 ms for the parent transcript, to learn the current model. That is one trace, not a benchmark.