cerveau docs site github
How it works

Context window

The window is the scarce resource, so it is planned rather than filled. Every turn is packed by a manager that counts what a request will really cost, demotes what can be recovered from disk, and never lets history vanish without saying so.

The budget

model_ctx is the ceiling. The packer does not aim at it — it aims at 75% of the budget minus a reserve, leaving room for the response and for a turn that arrives larger than expected.

Why 75% The factor was 0.6, tuned when the window was 32K. At 96K that shed context with 40K still unused: the packer was throwing away history the model could have had. The number is a tuning constant, and the comment in internal/window/window.go records why it moved.

What counts as cost

Tool-call arguments are part of the request. For a whole-file write they dwarf the assistant's own text, which is often empty. Counting only message content let a 33K request look like 1K and sail past the budget into a hard exceeds the available context size from the engine. The packer counts content, tool names and arguments together.

Three zones

How the packer escalates Green fits and nothing is touched. Yellow demotes tool output to pointers on disk. Red drops the oldest turns and replaces them with a briefing assembled from the log. OVER STILL < 60% green everything fits nothing is touched 80% yellow tool output → pointer big arguments elided 95% red oldest turns dropped a briefing takes their place EACH STEP RUNS ONLY WHEN THE ONE BEFORE IT WAS NOT ENOUGH Report{ tokens, budget, zone, demoted, trimmed, compacted } SURFACED TO THE PANEL EVERY TURN
Nothing is destroyed. Demoted text is still on disk; the window is only ever a projection of it.

Green

The turn fits inside the usable budget. Nothing is modified.

Yellow — demotion

Over budget. Two moves, oldest first, until it fits:

Demotion, not summarisation A summary is lossy the moment it is written and the original is gone. A pointer keeps the original on disk, so if the agent needs that output again it re-reads it. This is the distinction the whole memory design turns on — see Memory.

Red — compaction

Still over budget after demotion. The oldest turns are dropped, keeping the system prompt and the last n turns. What replaces them is the important part.

The compaction briefing

A silent delete is the worst outcome: the model loses what it decided and why, with nothing in its place, so it re-opens settled questions and redoes finished work — and reads as disobedient rather than forgetful.

Dropped turns are replaced by a briefing assembled from the log, never written by the model. Asking a model to summarise what it just lost is circular. The brief carries what cannot be recovered by reading the workspace:

Goal
The original request, verbatim.
Plan
The committed plan title, if there is one.
Done
Completed steps and checkpoints.
Files
What is on disk right now.
Workspace
The absolute path.
Compacted
How many turns were folded away.

If nothing is known, the brief degrades honestly rather than inventing structure — an empty section beats a confident lie. When no brief is available at all, a plain marker is used instead:

[N earlier turns were compacted out of this window to stay under the
context limit. They are NOT lost — the full episodic log is on disk, and
files you already wrote are still in the workspace. If you need something
from before this point, re-read the files rather than assuming it never
happened.]

The report

Every build returns a Report, and the panel renders it live:

tokens / budget
What this turn cost against the ceiling.
zone
green, yellow or red.
demoted
How many items became pointers or had arguments elided.
trimmed
How many turns were dropped.
compacted
How many turns were folded into a marker. Surfaced deliberately: a user who cannot see that the session lost history cannot tell it apart from the model ignoring what it was told.

Ingress caps

Demotion is the second line of defence. The first is that every tool has an IngressCap — a maximum number of characters its output may contribute to the window at all. A grep that matches four thousand lines is truncated at the boundary rather than admitted and then demoted. The caps are listed on Tools.

One more thing the window buys

Cerveau sends enable_thinking: false on every request. A reasoning model left to its own devices will spend the entire budget inside <think> and return nothing — which is not a context-management problem so much as a context-annihilation one.