CCLearn

Cap auto-compact well below the model's real window

On a 1M-context model, deliberately set the auto-compact window to a fraction of the real window — one practitioner runs 400K on 1M and reports the full window degraded quality. The knob is documented; the value is a judgement call nobody has published a measurement for.

docs corroborate

The official documentation describes the mechanism this relies on. The technique itself is community practice.

What this costs you if it is wrong

400K is one engineer's number for his own work, not a measured optimum, and no published benchmark separates it from the default. Compacting earlier means compacting more often, and every compaction is lossy — the skill index does not survive it, and only skills you actually invoked are re-injected. Set it too low on a codebase that needs a lot of loaded context and you trade "degraded late in the session" for "amnesiac throughout it." Setting the env var also silently breaks the status line's used_percentage as a compaction predictor.

You are six hours into a session on a 1M-context model. The status line says 61% and nothing has compacted, but Claude has started re-reading files it already read, forgetting a constraint you set two hours ago, and re-proposing an approach you rejected. Nothing is broken. You are just deep inside a context window that the model can technically accept.

The docs are explicit that this is a real effect and vague about what to do with it. best-practices says performance degrades as context fills. model-config says that if you set no auto-compact window, Claude Code compacts when the conversation reaches the model's context limit — Sonnet 5 lands around 967K by default. So on a 1M model the shipped behavior is: run the window all the way to the wall, then compact. That is a correctness default, not a quality default.

The practice, which is not in the docs: pick a number where the model stays sharp and compact there instead.

bash
# in your shell profile, or a project .env your launcher sources
export CLAUDE_CODE_AUTO_COMPACT_WINDOW=400000

Marco Lancini's published setup pins exactly this — 400K on a 1M model — on the stated grounds that running full-1M sessions showed significant degradation. That is one person's observation on one person's workload. It is the whole of the evidence.

Where to set it, and what beats what

Three places, and they do not behave the same way. From model-config:

HowScopeNotes
/autocompact 400kThis session and later onesSaved to user settings as autoCompactWindow. A higher-priority scope such as managed settings wins, and the command tells you so. Requires v2.1.221
claude --autocompact 400kOne launchOverrides your saved setting without changing it. Not preempted by managed settings. Requires v2.1.221
CLAUDE_CODE_AUTO_COMPACT_WINDOW=400000Whatever inherits the envBeats the command, the flag, and the setting. /autocompact then reports the override instead of changing anything

The command and the flag take 400k, 1M, or a bare 400. The environment variable takes a plain integer only — 400k reads as 400 and clamps to the 100K minimum, which is a silent, wrong-direction failure. Range is 100000 to 1000000, capped at the model's actual window.

Check your version before you plan around the first two rows. commands.md and cli-reference.md both say the command and the flag require "Claude Code v2.1.221 or later". Neither the environment variable nor the autoCompactWindow settings key carries a version note, so on an older client those two are the whole toolkit — and writing the key by hand costs you the reversible one-command adjustment the rest of this tip assumes.

The half of the claim the docs contradict

The same setup pairs this with CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1 to stop the model downshifting effort on hard problems. On current models that does nothing. From env-vars: it applies to Opus 4.6 and Sonnet 4.6 only, and "has no effect on Fable models, Sonnet 5, or Opus 4.7 and later, which always use adaptive reasoning." model-config repeats it.

If you want effort pinned high on a current model, the knob is a different one:

bash
export CLAUDE_CODE_EFFORT_LEVEL=xhigh

That one takes precedence over --effort, /effort, and the effortLevel setting — and, from v2.1.251, the per-model modelSettings key that /effort writes instead. Note it also suppresses ultracode's workflow orchestration unless the value is exactly xhigh.

Carrying a dead env var costs nothing but a false sense of control, which is the expensive kind.

What is actually unverified here

Be clear-eyed about which parts of this rest on what.

  • Documented mechanism. The variable, its range, its precedence, the default thresholds, and the status-line side effect are all in env-vars and model-config. None of that is in dispute.
  • Documented direction. "Performance degrades as context fills" is a direct quote from best-practices. The direction of the effect is official.
  • Not documented, not measured. That 400K is better than 967K. No Anthropic page suggests a value, says the default is too high, or names a point where degradation becomes material. The published claim is one engineer's subjective read on his own sessions, with no A/B, no task set, no numbers.

A sane way to adopt it

Do not jump straight to 400K on faith. The cheap version:

  1. Run a long session at the default and note where it starts drifting — the point where you find yourself re-stating things.
  2. Set the window somewhat below that with /autocompact (v2.1.221 or later), which is reversible in one command. On an older client, write autoCompactWindow into your user settings instead.
  3. Verify it took: launch with the variable set and run /autocompact. It reports the override rather than changing the window, which confirms the value the session is actually using — a much better check than assuming the export landed.
  4. /autocompact auto returns to the window tuned for your model.

The counter-pressure is real: a lower window means more compactions, and each is a lossy rewrite. context-window notes the skill index does not survive compaction — only skills you actually invoked are re-injected, capped at 5,000 tokens each. Compacting three times instead of once is three chances to lose the thread. Somewhere between "one lossy event at 967K" and "six lossy events at 150K" there is a floor, and where it sits depends on how much loaded context your work needs.

If you want the boundary visible rather than surprising, pair the cap with a status line that computes the percentage against your chosen window instead of used_percentage. Then compaction stops being a thing that happens to you mid-refactor.

Checkpoint

  • On a 1M-context model with no auto-compact window set, roughly where does the session compact — and is that a quality choice or a correctness one?
    Show answer

    At the wall. With no window set, model-config says Claude Code compacts when the conversation reaches the model's context limit — around 967K for Sonnet 5 — so the session runs almost the entire window first. That is a correctness default: it exists to keep you from overflowing, and it says nothing about where the answers are still sharp, which best-practices addresses separately by stating that performance degrades as context fills. Capping lower is the practice; no published measurement says where to cap.

  • You export CLAUDE_CODE_AUTO_COMPACT_WINDOW=400k. What window does the session actually run at, and why?
    Show answer

    100,000 — the minimum, not 400,000. The environment variable takes a plain integer only, so 400k reads as 400 and clamps to the bottom of the 100000-1000000 range: a silent failure in the wrong direction, leaving you compacting far more often than you meant to. The command and the flag do accept 400k, 1M or a bare 400; the variable does not. Confirm what the session is really using by running /autocompact, which reports the override rather than changing anything.

  • Your status line reads 38% on a 1M model with the window capped at 400K. How close is compaction?
    Show answer

    Imminent — about 380K of your 400K is gone. env-vars states that the status line's used_percentage always measures against the model's full context window, so a 400K cap on a 1M model fires compaction at what the gauge calls 40%. Steering by that number is exactly how compaction turns up unannounced mid-task: compute your own percentage against the window you chose, or put that figure in the status line instead.

Where this came from

Official pages that back this