Open source · Apache-2.0

Get far more done
with far fewer tokens.

Distill is a lightweight coding agent harness and terminal UI. It runs on the Grok and Codex subscriptions you already pay for, on OpenRouter, or on any model that speaks the OpenAI-compatible protocol. It reduces what your tools hand back before that text reaches the model.

curl -fsSL https://raw.githubusercontent.com/samuelfaj/distill/main/install.sh | sh

macOS, Linux, and Windows. Upgrade later with distill update.

The Distill terminal interface, showing the home menu, the Model tiers entry, and the status line with the active reasoning and worker models
Works with
  • Grok subscription
  • Codex subscription
  • OpenRouter
  • Local models

Model tiers

Reasoning, Worker, and Utility models

Each tier has its own picker. Every tier defaults to auto.

Reasoning model

Handles the main conversation, the difficult reasoning, and the code changes.

/model or /tiers reasoning

Worker model

Takes suitable calls in the same conversation when a lighter model can handle them. Optional.

/worker-model or /tiers worker

Utility model

Handles bounded tasks such as extraction, summaries, and compression.

/utility-model or /tiers utility

Leave a tier unset to run without it. A Worker left unset means no Worker routing.

Routing

Jev picks the model for each call

Jev is the decision layer inside Distill. It answers structured questions about a small state that the harness assembles: which model should take a call, how much effort that call needs, and which parts of a tool result are worth keeping.

What Jev decides

  • Which model and which effort level a call uses, when effort is on auto.
  • Which files, lines, logs, search results, and instructions deserve another look.
  • Which errors to address first when a check fails.
  • What to preserve during compression and compaction.

Token saver

Where the savings come from

Most of the reduction happens in deterministic code, on a tool result, before it enters the conversation. A tool result meets these stages in order, and each stage has a guard that can stop it.

Stage What it removes Runs when Default
Read reuse A second copy of bytes already in the conversation 2000 bytes or more, and hash-identical to a payload already sent On
Exact-output guard Nothing. This stage stops the rest. The call is line-addressed, or the text belongs to a skill Always
Preclean Terminal noise, and content the payload itself repeats 2000 bytes or more, and not a document On
Importance extraction The unreadable middle of a long payload 4000 bytes or more, and not a document On
Utility task A payload a small model can digest more cheaply than the session model should 2000 bytes or more, and a task is registered for that shape On
Utility compression The same, for a payload too large to want whole 24 KiB or more On

The first four stages save tokens. The last two save money by handing work to a cheaper model, which is a different thing.

Guards

The original is always kept

Every stage that would drop bytes writes the original to a file first and sends its path along with the reduced text. A store that refuses means the stage does not run.

The literal gate

A reduction is compared against the original before anyone uses it. If a path, a file:line, a number, or an error word would disappear, the reduction is thrown away and the original bytes are kept.

Read the original back

retrieve_range returns a line range of a stored payload. grep_handle runs an exact match inside one and returns verbatim lines with their line numbers.

Checked answers from small models

Distill uses a utility answer only when a guard can check it. An extraction must quote spans that really appear in the payload, a classification must land on a closed label, and a pick must name ids that were offered. When a check fails, the bytes stay as they were.

Rules

What never happens

These are rules in the code, not settings.

  • A tool result from an exact-output call is never rewritten.
  • A document is never rewritten.
  • A message you wrote is never compressed or rewritten. The pipeline only ever receives a tool result.
  • Skill bodies and permission text are never rewritten.
  • A secret's value is never returned by a transform. A presence flag masks it.
  • A payload is never changed unless the literal gate agrees, and a lossy stage never runs without the original stored.
  • No savings figure is reported, because nothing in Distill measures one.

A cap is not a saving, an estimate is not a measurement, and a skipped payload is not a win.

The harness

What else is in the box

Distill is a full coding agent. The token saver is one part of it.

Separate provider logins

Sign in to Grok, ChatGPT, and OpenRouter independently. Signing out of one leaves the others alone.

Local models

Start an OpenAI-compatible server, add an entry to config.toml, and use it as any tier.

Tier pickers

Open Model tiers from the home screen to change a tier, or type /tiers with the tier name.

Context commands

/context shows where the window is going, including what tool definitions and skill listings cost. /compact reclaims space on demand.

A decision log

GROK_LOG_JEV=1 records the lever, the verdict, the reason, and the confidence for every decision.

Off in one switch

Set [jev] enabled = false, or start with GROK_JEV=0, to turn the whole layer off. Each lever also has its own key.

Profiles

New profiles live in ~/.distill. Point DISTILL_HOME elsewhere, and an existing ~/.grok profile keeps working.

In-place upgrade

distill update upgrades an installation made with the release installer.

The home menu

New worktree, resume session, model tiers, and a separate logout per provider, all on one screen.

Quick start

Four steps

The installer detects your platform and architecture, then writes the binary under your home directory.

  1. Install

    Run the command for your platform.

  2. Sign in

    Log in to the subscription you already pay for, or to OpenRouter. You can use more than one.

  3. Set your tiers

    Pick a Reasoning, a Worker, and a Utility model, or leave them on auto.

  4. Run it

    Start distill in any project directory.

macOS and Linux

curl -fsSL https://raw.githubusercontent.com/samuelfaj/distill/main/install.sh | sh

Windows

irm https://raw.githubusercontent.com/samuelfaj/distill/main/install.ps1 | iex

Upgrade an existing install

distill update

Questions

Questions and answers

Which accounts do I need?

Any one of them. Distill keeps separate login and logout actions for Grok, ChatGPT, and OpenRouter, and signing out of one does not sign out of the others. ChatGPT uses OAuth, and OpenRouter accepts a browser login or an OPENROUTER_API_KEY.

Can I use a local model?

Yes. Start an OpenAI-compatible server, add an entry to config.toml with the model id and the base URL, then select it as a tier. New profiles use ~/.distill, and you can move that location with DISTILL_HOME.

Does Jev decide what my agent is allowed to do?

No. Jev picks among candidate models and routes that code supplies. Plan mode, auto approval, YOLO, and permission policies belong to Distill, and Jev cannot approve a call, veto one, or hold one for confirmation.

What happens when a decision is wrong?

The harness falls back. A routing decision that fails, times out, or lacks confidence leaves the session model in place, and a utility answer that fails its guard is discarded so the original bytes stay as they were.

How do I see what it did?

Start Distill with GROK_LOG_JEV=1. It writes logs/jev.jsonl inside your profile, one entry per decision, using labels such as reuse, crush, extract, keep, used, defer, local, and cloud.

How much does it actually save?

Distill does not publish a savings figure, and the code does not measure one. The stages and their thresholds are documented, so you can read what runs and check the decision log from your own sessions.

Install with one command

Distill supports macOS, Linux, and Windows, and upgrades in place.

curl -fsSL https://raw.githubusercontent.com/samuelfaj/distill/main/install.sh | sh

Open source under the Apache-2.0 license.