Skip to content

Choose a preset

A preset is a named, ordered pipeline. Set it once (--preset / PRESET, or preset: in YAML) and every explicit field you add overrides it. This guide maps workloads to presets and names the caveats before you commit.

Presets are just defaults

A preset expands to a default pipeline: list. Explicit pipeline: / components: blocks always win, so start from the closest preset and tune from there. See Architecture.

Which preset?

Your workload Preset
Nothing — A/B baseline / passthrough control off
Any traffic, want a guaranteed-safe win only safe
General agent traffic, good default balanced
Squeeze harder, tolerate LLM/structural offload aggressive
Coding agent reading big source files coding
MCP / list-endpoint JSON arrays mcp
Long agentic sessions (SWE-bench-style, re-sent transcripts) agent
One long transcript to compress, run standalone summarize

The presets

Every preset below is exactly the list in config/config.go; per-component behavior is in Components.

off[]

No components. Passthrough. Use it as the A/B control when you measure savings — the baseline in Benchmarks is this preset.

safe[format, cacheinject]

Two lossless Reformat components only: compact JSON (format) and an Anthropic cache breakpoint (cacheinject). Nothing is ever dropped, so there is nothing to expand.

  • Fits: any traffic where you want a zero-risk win and no reversibility surface.
  • Caveat: cacheinject's savings are provider-side cache hits, invisible to /stats token counts — it will show up under top_passthrough. That's expected, not dead weight.

balanced[format, dedup, failed_run, cmdfilter, cacheinject]

The default. Adds three cheap, high-precision offloaders: exact-dup removal (dedup), superseded test/build runs (failed_run), and DSL command-log filtering (cmdfilter).

  • Fits: general agent traffic; the safe everyday choice.
  • Caveat: cmdfilter only fires when ≥1 filter is loaded and the output's first line matches one. Its builtins cover pytest / npm-install / make; author more with a custom DSL filter.

aggressive[format, dedup, failed_run, cmdfilter, smartcrush, extract, cacheinject]

balanced plus JSON-array crushing (smartcrush) and query-relevance projection (extract).

  • Fits: you want more savings and accept structural/LLM offload with expand recovery.
  • Caveat: extract with strategy: code/rlm spends a model call (gated by its trigger); the default deterministic strategy is free. Keep the store on so the extra offloads stay recoverable.

coding[format, skeleton, cmdfilter, cacheinject]

Swaps in skeleton, which tree-sitter-parses fenced code blocks and replaces function bodies with { … }, keeping signatures/imports/types.

  • Fits: a coding agent that reads large source files but mostly needs the shape.
  • Caveat: skeleton is inert on unfenced file reads, unknown languages, or when the skeleton isn't smaller than the body.

mcp[format, smartcrush, cacheinject]

Targets homogeneous JSON arrays (list endpoints, search hits): keep keep_first + keep_last items plus any item carrying an error signal, drop the middle.

  • Fits: MCP tools and REST list endpoints returning long uniform arrays.
  • Caveat: inert on non-array output or arrays below min_items.

agent[format, dedup, failed_run, mask, extract, cacheinject]

Tuned for long agentic sessions (e.g. Claude Code on SWE-bench) where the dominant cost is the transcript of old tool outputs re-sent every turn.

  • Fits: long-running agents with a growing transcript.
  • Caveat: mask is the biggest lever here — age-based GC of tool outputs older than keep_recent. In the SWE-bench sweep it delivered ~27% mean content-token savings (up to 93.5% on a long session) with no reward loss (Benchmarks). Order matters: lossless first, then offload old-then-large, cache last.

summarize[summarize]

One LLM component that collapses the middle of the transcript into a single === History Summary === message, keeping the head + last few turns.

  • Fits: long agentic sessions where the stale middle is the token cost.
  • Caveat: run it alone. It changes the message count and restructures the whole transcript, so apply.Body rebuilds the body — no other component's in-place edits can race that rebuild. It needs a model; with none it no-ops.

LLM presets cost model calls

aggressive (via extract code/rlm) and summarize call a model. Both are gated by a trigger and reuse prior compactions per session, so they don't fire every turn. Pick the model with model.source (incoming reuses the request's own model+key; config uses a dedicated cheap model). See LLM components.