workflowLong-Running Sessions10 min read
The Context Budget
Your agent does not get worse at hour three because the model got worse. It gets worse because the instruction you gave it at minute four is no longer in the window, and nothing told you. Context is a budget you either allocate or overspend, and almost every team is overspending by accident.
How the context window actually fills, exactly what survives compaction and what silently does not, the four levers that keep a long session sharp (/context, focused compaction, the auto-compact window, subagent delegation), where durable state belongs instead of the transcript, and the API-side equivalents for agents you build yourself.
The Problem
Every team hits the same three symptoms and blames the model for all of them.
The agent forgets a constraint you stated an hour ago. It re-reads a file it already read. It starts violating a rule that is written down in a file it definitely loaded at startup. The usual response is to write a longer CLAUDE.md, which makes the problem worse, because a longer CLAUDE.md is a larger fixed cost on every single turn.
None of that is a reasoning failure. It is a bookkeeping failure. The window filled, the conversation got summarized to make room, and the summary kept some things and dropped others according to rules nobody on the team has read. Instructions given in chat are gone. A rule scoped to src/api/** is gone until the agent happens to read a file there again. A nested CLAUDE.md two directories down is gone. The root CLAUDE.md came back. The skill you invoked came back, truncated.
The agent does not announce any of this. It just keeps going, slightly dumber, and you find out in review.
What Is Actually in the Window
Before you type a single character, a Claude Code session has already spent tokens on the system prompt, every CLAUDE.md in the directory tree above your working directory, auto memory, environment and git info, the names of your MCP tools, and a one-line description of every skill. That is your fixed cost. Everything else, file reads, tool output, hook output, your prompts and the agent's replies, is variable cost on top of it.
Two defaults are worth knowing because they are doing real work for you. MCP tool schemas stay deferred by default and load on demand, which is why a dozen connected servers no longer cost you a dozen schemas up front. And skills contribute only their one-line description until they are actually invoked.
The command that ends the guessing is /context. It prints a live breakdown by category, names which memory files loaded, and suggests trims. Run it once in your real project before changing anything. Most teams discover their fixed cost is roughly double what they assumed, and that one MCP server or one 600-line CLAUDE.md is most of it.
What Survives Compaction
This table is the part that changes behavior, and it is the part almost nobody knows:
- System prompt and output style. Unchanged. They are not part of message history.
- Project-root `CLAUDE.md` and unscoped rules. Re-injected from disk. Safe.
- Auto memory. Re-injected from disk. Safe.
- Rules with `paths:` frontmatter. Lost, until the agent reads a matching file again.
- Nested `CLAUDE.md` in subdirectories. Lost, until the agent reads a file in that subdirectory again.
- Invoked skill bodies. Re-injected, but capped at 5,000 tokens per skill and 25,000 tokens total, oldest dropped first.
- The skill listing itself. Not re-injected. Only skills you actually invoked are preserved.
- Anything said only in conversation. Gone. Summarized at best.
Three consequences follow directly, and each one is a config change you can make today.
Skill truncation keeps the start of the file, so the most important instructions go at the top of SKILL.md, not in a "Rules" section at the bottom where compaction will eat them first.
A rule that must hold for the whole session cannot live behind paths: frontmatter. Path scoping is a context optimization, and it trades persistence for it. Anything load-bearing belongs in the project-root CLAUDE.md or an unscoped rule.
And an instruction you typed into chat is the least durable thing in the session. If you find yourself repeating a correction, that is the signal to move it to disk, not to repeat it more firmly.
The Four Levers
- Look before you tune.
/contextfor the live breakdown,/memoryto open and edit what loaded. On a checked-inCLAUDE.md,/doctorproposes trims: it cuts what the agent can derive from the codebase anyway, like directory layouts and dependency lists, and keeps the pitfalls and conventions that differ from tool defaults. - Compact with a focus, before the automatic pass.
/compact focus on the auth bug fixkeeps what you chose instead of what the automatic summarizer guessed. Run it deliberately at a task boundary, and run/clearinstead when the next task is genuinely unrelated. Old conversation you no longer need is not free, it is a cost on every remaining message. - Move the auto-compact boundary.
/autocompact 500ksets how full the window gets before the automatic pass runs, saved asautoCompactWindowin your user settings.--autocompactoverrides it for one launch, andCLAUDE_CODE_AUTO_COMPACT_WINDOWtakes precedence over both in scripts and CI. Accepted values run from 100K to 1M, written as200000,500k,1M, or a bare number from 100 to 1000 meaning thousands. Compacting earlier means more compactions and a summary that has less to lose each time; compacting later means fewer, larger losses. - Delegate the expensive reads.A subagent gets its own context window. It loads
CLAUDE.mdand your MCP and skill setup, does its work, and returns only its final text plus a small metadata trailer. Six thousand tokens of file reads become a four hundred token answer in your window. This is the single highest-leverage habit on the list, and the built-in Explore and Plan agents skip loadingCLAUDE.mdfor an even smaller footprint.
Worth knowing before you rely on delegation: the main conversation's auto memory is not loaded into subagents. A fork is the exception, since it inherits the parent conversation and system prompt. A custom subagent with memory: in its frontmatter gets its own separate memory directory, not yours.
Put Durable State Somewhere the Summarizer Cannot Reach
The transcript is the wrong place to keep anything you need in an hour. Three places are better, in ascending order of effort.
Auto memory is the free one. Claude writes it itself, from your corrections and what it discovers, into ~/.claude/projects/<project>/memory/. MEMORY.md is an index loaded at every session start, capped at the first 200 lines or 25KB, whichever comes first. Topic files beside it are read on demand and cost nothing until they are needed. It is per repository and shared across worktrees, but machine-local, so it does not travel to a teammate or a cloud session. Audit it with /memory, because it is plain markdown and it does accumulate things you would not have written.
The repository is the durable one. A progress file the agent updates as it works survives compaction, survives /clear, survives the laptop closing, and is reviewable by a human. For anything that spans more than one session, this is the answer, and it costs one file.
Hooks are the deterministic one. PreCompact fires before compaction with a manual or auto matcher, can inject additionalContext into the summary, and can block compaction entirely by exiting with code 2. PostCompact fires after and is informational. SessionStart has a compact matcher alongside startup, resume, clear and fork, so you can re-inject state on exactly the transitions where it was lost. A hook is the only one of the three that runs whether or not the model decides it should.
The Same Problem, One Layer Down
If you are building on the API rather than driving Claude Code, the mechanisms are explicit and you configure them yourself.
Context editing clears content out of the request server-side while your client keeps the full history. clear_tool_uses_20250919 drops old tool results once input tokens cross a trigger, defaulting to 100,000, keeping the most recent three tool uses, with exclude_tools for the ones that must never be dropped and clear_at_least so a clear is large enough to be worth the cache invalidation it causes. clear_thinking_20251015 does the same for thinking blocks, and when you use both it has to be listed first. Both need the context-management-2025-06-27 beta header.
Server-side compaction is the coarser tool. compact_20260112, behind the compact-2026-01-12 beta header, summarizes the whole conversation when input tokens cross a trigger that defaults to 150,000 and cannot be set below 50,000. It returns a compaction block that you must pass back, after which the API drops everything before it. Two things catch people out: put a cache breakpoint at the end of your system prompt so it stays cached across the event, and read the iterations array in usage, because the top-level token counts exclude the compaction step and under-report what you were billed.
The memory tool is the durable half of the pair. memory_20250818 is generally available on the Messages API with no beta header, and it is client-side: Claude requests file operations under a /memories prefix and your handler executes them against storage you control. Two things are not optional. Every path must be validated to stay inside /memories, because /memories/../../secrets.env is a real request an agent can be talked into making. And the API injects its own memory protocol into the system prompt, ending with "ASSUME INTERRUPTION: Your context window might be reset at any moment", which is the correct design assumption for every long-running agent whether or not you use this tool.
The pattern Anthropic documents for multi-session software work is worth copying wholesale: an initializer session that sets up a progress log and a feature checklist before any real work, each later session opening by reading them, each session updating the log before it ends, one feature at a time, and a feature marked complete only after end to end verification rather than when the code was written.
Why This Matters for Senior Teams
- It explains the failure everyone has already seen."The agent was great this morning and useless by the afternoon" has a mechanism, and the mechanism has settings. That reframes an unfixable vibe as a configuration problem.
- It is the cheapest quality win available.No new tool, no new vendor, no migration.
/context, a trimmedCLAUDE.md, and delegating research to subagents can be done this afternoon and are felt immediately. - It changes what belongs in
CLAUDE.md.Every line is a tax on every turn of every session for everyone on the team. Once the fixed cost is visible, "should this be a rule, a skill, or a path-scoped rule" becomes a real decision instead of a default of appending to the bottom. - It is what makes unattended runs possible at all.A run nobody is watching will compact several times. If the constraints only ever existed in chat, they are gone by the second one, and the run finishes confidently doing the wrong thing.
- It is a cost line, not just a quality line.Input tokens are charged on every turn, so a bloated fixed cost is a bill that compounds across the whole team, every day.
Where It Fits in the Stack
- It is the maintenance layer under context engineering.
CLAUDE.mdandAGENTS.mddecide what loads. This decides what is still loaded when it matters. - It sets the ceiling on Explore, Plan, Implement.The explore step is the biggest consumer of context in the loop, which is exactly why it belongs in a subagent.
- It is why the Browser Verification Loop needs care.Screenshots and DOM snapshots are among the most expensive things you can put in a window. Turn browser tools on for the task, not for the session.
- It multiplies across Agent Teams.Every teammate is a full instance with its own window and its own fixed cost. A 600-line
CLAUDE.mdis not one problem, it is one per teammate. - It belongs in the plugin.The
PreCompactandSessionStarthooks, the trimmed rules and the skill layout ship with the install, so context discipline is inherited rather than explained. - It shows up in Golden-PR Evals.Reliability across repeated runs is where a compaction problem surfaces as a number, because the run that fails is usually the run that compacted at the wrong moment.
When Not to Use It
- Do not optimize a session that never gets long.If your work is short, focused tasks and you already
/clearbetween them, you have solved this. Go do something else. - Do not chase a smaller window when you need a bigger one.Fable 5, Sonnet 5, Opus 4.6 and later, and Sonnet 4.6 support a 1 million token context window. Sometimes the honest answer is that the task is large, not that the context is badly managed.
- Do not treat auto memory as team documentation.It is machine-local and it does not travel. Anything a teammate needs goes in the repository.
- Do not block compaction as a habit.A
PreCompacthook that exits 2 is for a genuinely critical moment. Used routinely, it turns a managed summary into a hard context-limit failure. - Do not skip path validation on a memory handler.A client-side memory tool executes whatever path it is given. That is a file-read primitive pointed at your own infrastructure.
Source
- Explore the context windowcode.claude.com (opens in a new tab)
- How Claude remembers your projectcode.claude.com (opens in a new tab)
- Automate actions with hookscode.claude.com (opens in a new tab)
- Context editingplatform.claude.com (opens in a new tab)
- Compactionplatform.claude.com (opens in a new tab)
- Memory toolplatform.claude.com (opens in a new tab)
