Claude Code auto-compact: the threshold setting that actually exists.
If you searched for a way to make Claude Code compact earlier, you probably found the same tip we did: add "autoCompactThreshold": 80 to your settings.json. We tried it. It does nothing. The knob that works today is /autocompact. Here is what it really does, with the honest caveats.
Updated 2026-11-02. We warned that this could change without notice. It did, and in your favor. /autocompact is now the official way to move the trigger, the environment variables we called undocumented are documented, and several traps we warned about are gone. We also had the formula wrong. This post is rewritten for v2.1.316.
Everything below was re-checked on Claude Code v2.1.316 on 2026-11-02, against the shipped binary and the official docs, not other blog posts. Version matters; re-check after big updates.
Every number says where it comes from. Documented: the official docs say so. Derived: we worked it out from the shipped code and did not run it. Measured: we saw it in a real session. In our judgment: our opinion, nothing measures it.
Auto-compact in one minute
Claude Code works inside a fixed context window. As a session grows, the window fills. When it gets close to full, auto-compact kicks in: the conversation is summarized, the summary replaces the history, and the session continues with room to breathe.
The catch is timing. By default, compaction fires near the ceiling: at about 967K tokens on a model with a native 1M window (documented). At that point the summarizer is working under pressure, with a nearly full window, and the summary loses more nuance than an earlier, deliberate one would. If you have ever watched Claude Code come back from a compact slightly dumber about your task, that is why.
So the question is legitimate: how do you move the trigger earlier?
The tip that doesn't work
A widely shared tip says to put this in settings.json:
{ "autoCompactThreshold": 80 }
That key does not exist as a setting. In the 2.1.316 binary, the string autoCompactThreshold appears only as an internal reporting field: a name the app uses when reporting metrics, not a setting it reads. Nothing in the settings loader looks for it.
The trap is that it fails silently. settings.json accepts unknown keys without complaint, so you add the line, nothing breaks, and you assume it worked. It didn't. Your threshold never moved.
The knob that actually exists: /autocompact
Since v2.1.221, Claude Code has a real command for this (documented):
/autocompact 433k # compact at about 400K on this model
/autocompact auto # back to the window tuned for your model
It saves the value to your user settings under the current model, and it applies it to the session you are in (documented). The value runs from 100K to 1M tokens (documented).
Why 433k for 400K? Because the value is a window, not the trigger. Auto-compact fires 33,000 tokens below the window: 20,000 reserved for the model's output, then a 13,000 buffer (derived). So /autocompact 433k compacts at 400K, and /autocompact 400k compacts at 367K (both derived).
The same window can be set in other places (documented):
- Every model:
"autoCompactWindow": 433000in a settings file. - One model:
modelSettings.<model>.autoCompactWindow. This is what/autocompactwrites since v2.1.288. - One launch:
claude --autocompact 433k. - One subagent:
autoCompactWindowin its definition. - Scripts and cloud: the
CLAUDE_CODE_AUTO_COMPACT_WINDOWenvironment variable. It beats/autocompact, the flag and both settings, and/autocompactthen reports the override without saving.
Whichever way you set it, Claude Code caps the window at the model's context window (documented). A value that is too high no longer disables anything, and you no longer have to keep it in step with your model. Two things we said did not exist now do: an auto value and a per-model form.
Native 1M today: the Fable models, Sonnet 5 and later, Haiku 5.5, Opus 4.7 and later. Sonnet 4.6 and Opus 4.6 without extended context stay at the 200K boundary (documented).
The on/off switches are still there: autoCompactEnabled in settings.json and DISABLE_AUTO_COMPACT=1. The variable wins over the setting (documented).
The environment pair still works, with a different formula
The pair this post used to lead with is still there, and both variables now sit on the official env-vars page (documented):
CLAUDE_CODE_AUTO_COMPACT_WINDOW=1000000 # the window
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=40 # a percentage of the effective window
We used to write the rule as window × percentage / 100. That was too simple. The shipped rule is (derived):
effective = min(window, model window) - min(max output, 20000)
threshold = min(effective × percentage / 100, effective - 13000)
So 40 on a 1M window gives 392,000, not 400,000 (derived). With no percentage the threshold is 967,000 (derived), which matches the "about 967K" in the docs (documented). The docs add that raising CLAUDE_CODE_MAX_OUTPUT_TOKENS shrinks the effective window (documented); in the shipped code that reserve stops at 20,000 (derived).
We run this pair. Without the pair, in one long session, auto-compact fired 19 times between 967K and 973K on v2.1.306 to v2.1.312, and once at 1,047K on v2.1.316, which we cannot explain. With the pair set, it fired at 406,218 and then 394,480 tokens (all measured, and only two compactions with the pair so far). A compaction lands past the threshold because the check runs before each model request, so the last turn can carry it over (derived).
Does the percentage still need a window? Not always, as far as we can read, but we have not measured this one. In the code, it is ignored only while the window source is auto. A model with a native 1M window gets a default source instead, so the percentage alone should apply there (derived). The docs agree in general terms: it applies "only in sessions that compact before the model's context limit" (documented). On a model that compacts at its limit, it is read, then ignored. Set a window with it and the question goes away.
To make the pair permanent, put both in the env block of ~/.claude/settings.json:
{
"env": {
"CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1000000",
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "40"
}
}
We used to say this only reached new sessions. On v2.1.316 it does not wait: we added the pair to a project's .claude/settings.local.json during a session, and the next shell command in that session saw both variables, with no restart (measured). The 406,218 and 394,480 above are that same session. We tested that one file, not ~/.claude/settings.json itself. A shell export still needs a new session.
Moving from the pair to /autocompact? Remove both variables first, then start a new session: removing a variable from a settings file does not unset it in a running session (documented). The window variable stops /autocompact from saving (documented), and a leftover percentage applies on top of any window (derived): 40 on top of /autocompact 433k compacts near 165K, not 400K.
How the engine decides: warn, compact, blocked
Under the hood, Claude Code computes a level from the current token count. Three levels matter:
- warn: you are within 20,000 tokens of the threshold (derived). The status line starts nudging you.
- compact: the threshold is reached. Auto-compact fires (if enabled).
- blocked: you are near the hard ceiling of the window. No more room.
A smaller window moves warn and compact down with it, far away from the blocked zone where summaries are at their worst. Blocked itself stays at the model's real ceiling (derived).
One trap: the status line's used_percentage measures against the model's full context window. While the variable is set, that percentage does not tell you when compaction will run (documented). We used to say the two were consistent. With the variable set, they are not.
The honest caveats
- The percentage is still a test knob inside. It is documented now, but the binary still names its value a test override, and it already changed once, between 2.1.211 and 2.1.220. Prefer the window. Re-verify after you update.
- Lower is not better. Every compact costs a summarization pass and loses some nuance. Set it too low and you compact constantly, paying that price over and over. In our judgment, 40% to 70% of the window is a sane range. We run 40. And you can only pull the trigger earlier, never later (documented): the threshold stops at the window minus 33,000, which is 83.5% of a 200K window and 96.7% of a 1M window (derived). The "roughly 83" we quoted before only held for 200K.
- It only moves the automatic trigger. Despite its name, the auto-compact window does not grow your context window: it tells the compaction engine when to act. It does not make summaries better either. It just buys them room.
The better habit: /compact on your terms
The window is a safety net, not a strategy. The best compaction is the one you run yourself: type /compact at a natural breakpoint: a task finished, findings written to a file, state saved. A deliberate compact with everything persisted beats any automatic one that lands mid-task, whatever the threshold.
The pattern that works: finish a chunk of work, persist what matters to disk, then compact. The window exists for the sessions where you forget.
We hit all of this while building Klyr, which gives your AI a memory that lives outside the context window, so what your assistant knows about you survives every compact, every session, every machine. Compaction is exactly the moment a stock assistant forgets; it is the moment Klyr is built for. The two ways into Klyr are laid out on the homepage.
New to Claude Code entirely? Start with our non-developer guide first.
FAQ
Does autoCompactThreshold in settings.json work?
No. In Claude Code 2.1.316 that string exists only as an internal reporting field name. The settings loader never reads it. It fails silently, which is why the tip keeps spreading.
How do I make Claude Code auto-compact earlier?
Run /autocompact with a window size, for example /autocompact 433k. Claude Code saves it for the current model and applies it to the session you are in. It compacts 33,000 tokens below the window, so 433k means about 400K (derived from the shipped code, not run). /autocompact auto goes back to the default.
Does a change apply to the session I am already in?
/autocompact does, by design (documented). The env block of a settings file did too on v2.1.316: we measured it on a project's .claude/settings.local.json, not on ~/.claude/settings.json. Removing a variable from that block (documented) and a shell export both need a new session.
Does CLAUDE_AUTOCOMPACT_PCT_OVERRIDE work on its own?
Not everywhere. It applies only in sessions that compact before the model's context limit (documented). On a model that compacts at its limit with no window set, it is read and silently ignored. On a model with a native 1M window it should apply alone, but that is derived from the code and we have not measured it. Set a window with it and the question goes away.
What should CLAUDE_CODE_AUTO_COMPACT_WINDOW be?
The window you want, from 100,000 to 1,000,000 tokens (documented). It no longer has to match your model: Claude Code caps it at the model's context window. It beats /autocompact, the --autocompact flag and the autoCompactWindow setting, so prefer /autocompact if you mix models.
Is CLAUDE_AUTOCOMPACT_PCT_OVERRIDE official?
It is documented now, on the official env-vars page. Inside the binary its value is still named a test override, and its behavior changed once between 2.1.211 and 2.1.220. Last verified on 2.1.316 on 2026-11-02. Re-check after you update.
What value should I use?
In our judgment, 40% to 70% of the window. Lower means earlier, better-quality compaction but more frequent summarization, and every summary loses some nuance. We run 40. You can only pull the trigger earlier than the default, never later (documented).
How do I disable auto-compact completely?
Set autoCompactEnabled to false in settings.json, or set the environment variable DISABLE_AUTO_COMPACT=1. Both are official, and the variable wins over the setting. You will then hit the context ceiling with no safety net, so compact manually.
What do the warn, compact and blocked levels mean?
Internal levels Claude Code computes from your token count: warn means you are within 20,000 tokens of the auto-compact threshold (derived from the shipped code), compact means the threshold is reached and auto-compact fires, blocked means you are near the hard ceiling of the window.