I was reading the v2.1.299 changelog one morning when a single line stopped me: a conversation over 200K tokens that sits idle for about 54 minutes gets compacted before its one-hour prompt cache expires. As an indie developer, I step away from a long session and come back to it almost every day.
The first thing I want to say is that this is a feature, not a bug. But if Claude seems to have forgotten something you settled an hour ago, the cause may not be the model's mood. It may be this compaction.
What is actually happening
The changelog says that in the terminal, a conversation of 200K+ tokens left idle for roughly 54 minutes is compacted just before the one-hour prompt cache runs out, so your next message doesn't have to reprocess everything.
The goal is a shorter wait and a smaller bill when you return. The price is that the fine detail of the conversation is replaced by a summary. It only happens when all three of these hold:
| Condition | Detail |
|---|---|
| Where | A terminal conversation |
| Size | 200K tokens or more (the default minimum) |
| Idle time | About 54 minutes, before the 1-hour cache expires |
Short conversations and sessions you poke every few minutes are untouched. The longer you have nurtured a session, the more likely it is to qualify, which is the awkward part.
Checking whether it happened
A notice appears when compaction runs, and since v2.1.302 that notice also tells you how to turn it off. If you missed it, look for these signs:
- The first reply after you return drops a file name, a rejected option, or a decision you had shared
- A summary-like passage you didn't write appears in the middle of the conversation
- Your Claude Code is older than v2.1.290, where the setting doesn't exist
This script checks the version and every settings layer at once, so you don't have to open each file by hand.
#!/bin/bash
# Report idle-compaction settings from user and project layers
echo "version: $(claude --version 2>/dev/null)"
for f in "$HOME/.claude/settings.json" ".claude/settings.json" ".claude/settings.local.json"; do
[ -f "$f" ] || continue
# "unset" means the default (enabled)
v=$(jq -r 'if has("idleCompaction") then .idleCompaction else "unset" end' "$f")
m=$(jq -r '.env.CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS // "unset"' "$f")
echo "$f -> idleCompaction=$v, min_tokens=$m"
doneIf everything says unset, compaction is on by default. Knowing which layer wins saves you from guessing when you add a setting later.
Narrowing the cause in three steps
When something feels forgotten, I check in this order, so I don't change settings in a hurry. First, how long was I away? Under about 54 minutes, it isn't idle compaction. Second, how big was the conversation? Under 200K tokens, it's out of scope. Third, run the script above: if idleCompaction is false, compaction didn't run and the cause is elsewhere. Only when all three fit do I treat idle compaction as the prime suspect. Blaming it without these checks can hide the real cause.
Turn it off, or just raise the bar
There are two ways to switch it off:
- Add
"idleCompaction": falsetosettings.json(v2.1.290 or later) - Use the "Idle compaction" row in
/config(v2.1.302 or later)
Or keep it and raise the threshold with CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS:
{
"idleCompaction": true,
"env": {
"CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS": "400000"
}
}I'd start with the threshold. Turning it off entirely means the first message after a long break pays the full cost of reprocessing an expired cache, and the longer the conversation, the heavier that message is. I'd rather reserve "off" for work where losing detail to a summary costs more than that.
The real fix: keep what you can't lose outside the conversation
Before touching settings, ask whether the information that hurt to lose lived only in the chat. I move three kinds of facts into a file every time:
- Options I rejected, and why (so they aren't proposed again)
- Files and directories that must not be touched
- Where the work stands, and what comes next
I put them in a dated section at the end of CLAUDE.md, kept apart from permanent rules so cleanup is easy.
## Working notes (2026-10-20 — delete when done)
- Rejected: regenerating all files on every build (reason: a diff is enough)
- Do not touch: everything under scripts/legacy/
- Status: log formatting done. Next: retry limit on failureBefore I leave, I ask Claude to write the current working notes to the end of CLAUDE.md. For how I think about the file itself, see CLAUDE.md design.
How it ties to the cache
Idle compaction is built around the one-hour cache lifetime. If you want to design cache behavior more deliberately, prompt cache TTL and directory scope goes further. v2.1.300 also added cache_creation_5m_tokens and cache_creation_1h_tokens to the OpenTelemetry api_request event, so you can split cache writes by lifetime.
I don't yet have the records to say "switching it off paid for itself" in my own work. If you change the setting, I'd keep the same task running for a few days either side and write down the wait after you return and how many assumptions went missing.
One rule to take with you
What can't be lost goes in a file, not in the conversation. I keep to that whether compaction is on or off.
Today, before you step away, try writing one working note to the end of CLAUDE.md.