Context is a budget
Between the point where quality starts to slip and the point where you notice, hours of work go by. Nothing warns you in between: there is a number almost nobody keeps in view.
There is a moment, in long sessions with a coding agent, when the answers change without the tone changing. It proposes a path you ruled out an hour ago. It loses a constraint that was decided out loud and never written to a file. It starts declaring finished a piece of work that is not finished.
None of that gets flagged. The model does not tell you «from here on I reason worse»: it keeps answering with the same confidence it had two hours ago, and at some point you notice you are correcting more than you are building.

The decay does not wait for the million
A context window is a capacity, not a guarantee. Two different things, and the marketing keeps them deliberately close together.
The two best measurements I know are more than a year old, and that is worth saying before the numbers: the models in them are largely superseded, some deprecated. They are not a snapshot of today. They establish that the phenomenon exists and how it behaves, and on that nothing published since has contradicted them.
**NoLiMa** (Adobe Research, February 2025, then ICML 2025) tested twelve models claiming at least 128k tokens, with questions that share no words with the answer — so not solvable by literal matching. At 32k tokens, ten of those twelve fell below half the score they got at short context. GPT-4o, old and on its way out today but among the best of that group at the time, went from 99.3% to 69.7%. Thirty-two thousand tokens: in a real working session you pass them before lunch.
**Chroma** (July 2025) repeated the measurement across eighteen models — Claude, GPT, Gemini, Qwen, also in their versions of the time — in the work that made the term context rot popular. The result is not «past a certain threshold it collapses»: it is that performance does not stay constant at any increment of length, not even on trivial tasks, and that the drop is not uniform. A single distractor in the context is enough to fall below baseline. On the conversational LongMemEval benchmark, the gap between giving the model the roughly 300 tokens it needs and giving it the 113k of the whole conversation is clear across all of them.
The counterargument is fair, and it is double: these are synthetic benchmarks, and they run on yesterday's models. It holds for the precise numbers, not for the direction — which is the same across thirty models and four different families, and which Anthropic explains in architectural rather than empirical terms: the model has a finite attention budget, every token you add depletes it, and the transformer builds pairwise relationships between all tokens — which at a hundred thousand tokens is ten billion. It is a property of the mechanism, not a flaw in one generation. A new model moves the threshold; it does not remove it.
Compaction is not the fix, it is the symptom
The obvious answer, when the context fills up, is to compact: summarise the conversation and carry on from there. It is also what auto-compact does on its own, and almost always at the worst moment.
The problem is what the summary carries forward. If you spent two hours on a bug that turned out to be an inverted condition, the session holds every wrong hypothesis you went through to get there. Compaction does not tell them apart from the rest: it summarises those too, and the model finds them again as good state — summarised, and therefore without the context that made it possible to discard them.
On this, Anthropic wrote the most useful thing I have read this year. In the piece on harness design for long-running applications, from March 2026, they separate compaction from context reset: the first summarises in place and leaves standing what they call context anxiety — the agent starts wrapping up early because it believes it is near its limit. With Sonnet 4.5 the effect was strong enough that compaction alone was not enough to sustain long tasks. What they adopted instead is clearing the window and starting a fresh agent, with a handoff artifact carrying the state and the next steps.
A compaction gives you back room, not quality. The noise you had accumulated comes back summarised, and the model treats it as good context.
The handoff is the step you decide
The difference between a compaction and a handoff is not technical, it is a matter of authority. A compaction is a compression you undergo: the machine decides what survives, and it decides on the basis of how much room is needed. A handoff is a document you write, to disk, before clearing — and what goes into it is a choice.
The handoff skill by Matt Pocock is the leanest version I know. It writes the document to the system temp directory rather than the workspace, so it does not clutter the repo. It includes a «suggested skills» section, telling the next agent what to reach for. And above all it forbids duplication: whatever already lives in a plan, an ADR, a commit or a diff is not summarised, it is referenced by path. That is the rule that keeps the document small, and it is the same reason it works — a long handoff is a compaction written by hand.
Then /clear, and you start again with an empty window and three hundred lines of chosen state. It is the same principle I have written about in when not to automate: the part you can automate is the transport, not the judgement about what is worth carrying over.
But to decide, you have to see the number
Here is the practical gap. The handoff has to happen before you need it, and to do it early you have to know where you are. Claude Code has the number, but shows it late and in passing: by the time the warning appears, the decay NoLiMa describes started a long while back.
That is why I wrote imperStatusLine, a status line for Claude Code. The starting idea is trivial: the status line is the only surface that stays visible while you work, and it is wasted showing the current directory.

At its centre is the context bar: ◉ for the occupied part, ◯ for the free one, sized to the real width of the terminal. Next to it, the percentage and the true size of the window — read from the field Claude Code passes, not guessed from the model name. In the shot it is at 15% of a million: the moment when you do not have to think about it, and exactly the moment a status line should know to stay quiet.
The colour says one thing, and says it everywhere
One function, color_pct, colours the context percentage, the five-hour quota and the seven-day one: green below 60%, yellow up to 79, red from 80 up. Three different quantities, one scale, nothing to remember.
The two exceptions are deliberate, and they are where red changes meaning. Effort is coloured against common sense — low green, medium yellow, high, xhigh and max red — because there red does not say «bad», it says «you are spending». Permission mode follows the same logic: default green, accept yellow, plan purple, bypass red. Not because working in bypass is wrong, but because it is the one state where nothing stops you, and it is worth knowing that without having to think about it.
The marker this article is about
On the context row, when the session passes 200,000 tokens, a red ⚠ 200k appears. It is not a threshold I picked: it is the exceeds_200k_tokens field Claude Code already passes, and that almost no interface shows.
It matters because on a one-million window the bar stays green up to 60%, which is six hundred thousand tokens — three times past it. That marker is the only thing reminding you that the capacity and the range where the model reasons well are two different numbers, and it is this whole article compressed into five characters.
The rows, one by one
| Row | What you read there |
|---|---|
| Header | the active output style, or the agent name in an --agent session. Not the active skill: the status line JSON does not expose it |
| TIME · MODEL · EFFORT · PERM | time, model with the (1M) suffix when that is the variant, reasoning level, permission mode |
| ENV | agents, skills, hooks, plugins and commands available, counted by walking the installed plugins rather than the marketplaces: it is what Claude Code actually loads. With subagents running it becomes 58 (4 active) |
| CONTEXT | the bar, the percentage, the window, the ⚠ 200k |
| TOKENS | In, Out, Cached, Total. If In looks absurdly small it is not an error: it is the prompt cache doing its job |
| SESSION | cost in dollars, lines added and removed, real session uptime |
| QUOTA | usage of the five-hour window and the seven-day one, with the reset time |
| PWD | directory, branch, age of the last commit, modified files, ahead/behind, and the pull request open on the branch with its review state: ✓ approved, ✗ changes requested, ● pending, ◷ draft |
| TASKS | appears only when something is in flight: background tasks and subagents that have not returned yet |
In the shot the PWD row is missing, and that is not a fault: I work in Warp, which already shows directory, branch and diff in its own bottom bar, so the script suppresses it — and for the same reason it drops Lines +/- from the SESSION row. Information duplicated on screen costs as much attention as information hidden.
This is not a dashboard for curiosity. Each of those rows is the input to a decision: the percentage says whether it is time to hand off, the permission mode says how much you can let run, the seven-day quota says whether to burn the big model now or in two hours, the tasks in flight say whether you are actually done. They are the same things you used to go looking for in three different places, each at an attention cost you paid only when you remembered to pay it.
Installing it
git clone https://github.com/imperugo/imperStatusLine.git
cd imperStatusLine
./install.shThe installer copies the script to ~/.claude/imperStatusLine.sh, makes it executable and writes the entry into ~/.claude/settings.json:
"statusLine": {
"type": "command",
"command": "bash $HOME/.claude/imperStatusLine.sh",
"padding": 0
}If it finds a previous version it sets it aside as .bak.<epoch> rather than overwriting it, and it is idempotent: running it again on a machine already set up does no harm. ./install.sh --uninstall removes the entry from settings and the script.
The only required dependency is jq. npx and ccusage are only the fallback for the five-hour quota, when Claude Code does not pass native rate limits. On Windows the script hunts for jq in the winget paths itself, because the bash Claude Code uses there does not inherit the system PATH: without that search every field comes out zero, and not in an obvious way.
What it does not do
It does not save you from hallucinations and it does not manage your context. There is no intelligence inside: it reads what Claude Code passes and lays it out so you can decide on it. The judgement stays yours, as in the systems I wrote about regarding human-in-the-loop — with the difference that here the person in the loop is you, and the loop is your afternoon.
The part that cost more than expected is the part you do not see. Since version 2.1 Claude Code passes context, cost, effort, rate limits and PR state directly in the JSON on stdin; before that they had to be reconstructed by reading the transcript and calling an external tool for the quotas. Keeping both paths alive is most of the script's complexity, and it is the part that breaks when a field gets renamed. It is also the only part worth the care: a status line showing a wrong number is worse than no status line at all, because you look at a wrong number and you believe it.
The rule I follow
I look at the bar before starting something new, not when I am in the middle of it. Above 60% I do not open a new front: I close the one that is open, write the handoff, /clear, and start again. Below 60% I do not think about it.
It is not a measured threshold, it is a convenient one: far enough below the range where the benchmarks see the drop, far enough above to avoid restarting every twenty minutes. The point is not the number. It is that the number is in front of you, because you only make the right decision at the right moment if you can see the moment coming.
Sources
- Adobe Research, NoLiMa: Long-Context Evaluation Beyond Literal Matching (February 2025, ICML 2025) — https://arxiv.org/abs/2502.05167
- Chroma, Context Rot: How Increasing Input Tokens Impacts LLM Performance (July 2025) — https://www.trychroma.com/research/context-rot
- Anthropic, Effective context engineering for AI agents (September 2025) — https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
- Anthropic, Harness design for long-running application development (March 2026) — https://www.anthropic.com/engineering/harness-design-long-running-apps
- Anthropic, Effective harnesses for long-running agents (November 2025) — https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents
- Matt Pocock, the
handoffskill — https://github.com/mattpocock/skills - imperStatusLine — https://github.com/imperugo/imperStatusLine