You ask Claude Code for a small fix. It changes five lines, yet the session uses a much larger share of your limit than expected. On another day, it ships something more complex and the session goes much further.

It feels random, but it isn't. Session cost depends less on the size of the diff and more on the path taken to reach it.

Anthropic explains this dynamic in Maximizing the value of your Claude Code sessions. The main idea is excellent: token efficiency is not simply about using fewer tokens. It is about spending context and reasoning on the right problem.

Let's open the hood and see what that means in practice.

Your conversation becomes a backpack

When you start a task, Claude Code receives more than your latest message. A session can carry system instructions, CLAUDE.md, conversation history, files that were read, and command output. The Claude Code documentation calls this collection the context window.

Think of it as a backpack. It starts light. The agent reads two files, runs tests, and finds a log; all of that goes into the backpack. At each new step, it keeps working with what is already there.

Some items are useful: the business rule, the failing test, an architectural decision. Others become dead weight: 400 lines saying tests passed, an abandoned investigation, or files read only while searching for the right code.

Inference has two phases. Prefill processes the input; decode generates the output one token at a time. The Hugging Face LLM course explains the distinction. Tool calls and reasoning tokens also count, even when you only see a short summary in the terminal.

Caching helps, but heavy context does not disappear

Claude Code uses prompt caching. When the beginning of a new request matches an earlier one, some processing can be reused.

A simplified way to think about cost is:

cost = fresh input + cache writes + cache reads + output

These components have different prices, which also vary by model. Reading cached content is usually cheaper than processing it again as fresh input.

Now imagine loading 20,000 tokens of logs before another ten requests. That block may participate in all ten inputs: 200,000 cumulative context tokens. It does not mean all of them are billed as fresh input — caching may serve much of the repeated reading — but the material still occupies the context window and competes for attention with the current problem.

It is like leaving every tool on the workbench after finding the right screwdriver. They are still there, even if you no longer need them.

A good prompt works like a shortcut

Consider a simple checkout bug: products cost $20, the discount is 10%, and shipping is $5. The expected result is $23, but the system returns $22.50. The clue is clear: the discount is probably being applied to shipping as well.

A useful request would be:

In @src/checkout/calculate-total.ts and @tests/checkout/calculate-total.test.ts, investigate this case: products = 20, discount = 10%, shipping = 5; expected = 23, actual = 22.50. The discount must apply only to products. Check the rounding rule, add a regression test, and run the checkout tests. If the cause is outside these files, follow the call and explain what you find.

An @ reference includes the file in the message, as the best-practices documentation recommends. This can avoid a search or a later read call. Just avoid attaching the same file again in every message: it is already part of the conversation.

Model, effort, and commands: choose before accelerating

The discount bug is deterministic. A duplicate charge that appears when two workers process the same event requires examining concurrency, retries, transactions, and idempotency. These problems have very different levels of uncertainty.

The model defines the available capability. Effort controls how much reasoning is applied when supported. The configuration documentation explains the levels and trade-offs.

Check /model and /effort before starting. Changing them mid-conversation can invalidate the cache. Still, if a simple-looking bug turns into a race condition, more capability may be worth rereading the context.

Take care with commands too. A noisy test runner can dump hundreds of lines into the session. For the checkout example, start with the specific test and a concise reporter when supported:

npx vitest run tests/checkout/calculate-total.test.ts --reporter=dot

CLAUDE.md follows the same logic. Keep persistent rules there: commands the agent cannot infer, project-specific conventions, and important architectural decisions. Long tutorials and expired rules enter the backpack in every session. Run /context in a fresh conversation to see what is already loaded.

/clear, /compact, or /rewind?

These commands solve different problems:

SituationBest starting point
You finished one bug and are moving to another task/clear
Investigation continues, but too much material has accumulated/compact with specific instructions
Recent turns followed the wrong hypothesis/rewind to the earlier point

If you discovered a race condition, do not ask only for a conversation summary. Say what must survive:

Preserve the two-worker reproduction, the tests involved, and the evidence that no uniqueness constraint exists. Keep the rejected hypotheses and why they were rejected. The next step is to validate the transaction before changing retry behavior.

Checkpointing also needs care: rewinding conversation or files does not reverse external effects. If the session called an API, changed a database, or published something, confirm the real state before continuing.

A subagent is not a free employee

Subagents are useful for work that produces lots of material. They operate in a separate context window and return a summary to the main agent, as the documentation explains.

Imagine thousands of lines from a duplicate-charge incident. A subagent can build the worker timeline while the main conversation keeps only the evidence needed to decide the fix.

A good delegation would be:

Analyze the logs for the specified event. Do not edit code. Return the attempt timeline, excerpts demonstrating concurrent processing, and gaps that still prevent confirmation of the cause. Include references to the original material.

There is a price: the subagent also uses tokens, starts without some context, and may need to reread files. For the checkout discount, this would be bureaucracy. For filtering thousands of events, it can be a very good division of work.

The test that really matters

In your next session, watch three things:

  1. Did the agent search for something whose location you already knew?
  2. Did a file or command stay in context after it stopped being useful?
  3. Did the solution come with evidence — a test, build, diff, or reproduction — or only the sentence “fixed successfully”?

This quick diagnosis teaches more than memorizing a list of commands. If the search was unnecessary, improve the starting point. If the agent implemented quickly from a bad hypothesis, provide a better reproduction. If the session filled with old material, clear or compact at the right time.

Claude Code works better when context is treated as part of the work's architecture. The goal is not the cheapest possible session. It is a correct, verifiable solution with as little wasted work as possible.