Token efficiency guide cover image

  • Apr 6

How to Reduce Claude Code Token Usage and Get More From Every Session

Eight practical changes to your Claude Code settings that reduce token usage per session. Covers MAX_THINKING_TOKENS, .claudeignore, subagent routing, compaction, and MCP management.

This is an update to an article published here on 6 April 2026. Claude Code has changed a good deal since then, and on reviewing the original I found that three of the settings it recommended either no longer work or never worked in the first place. If you applied the original changes to your configuration, read the section below on what to undo, then work through the rest. Everything here has been checked against the current Claude Code documentation. See token optimisation document at the bottom of this guide that you can give to your Claude Code and ask it to make the changes to your workspace.

Contents

Three things to undo, then thirteen ways to cut token consumption, in rough order of how much they return for the effort.

  1. What to Undo From the Original Article, three settings that either stopped working or never worked

  2. Start By Looking At Where the Tokens Go, /context and /usage before you change anything

  3. Clear Between Unrelated Tasks, the largest avoidable cost, and it needs no settings

  4. Set the Effort Level to Match the Work, /effort and what replaced thinking budgets

  5. Route Subagents to Cheaper Models, per-agent frontmatter, and why the environment variable is the wrong tool

  6. Keep Verbose Work Out of the Main Conversation, delegation, and returning paths rather than content

  7. Filter Data Before Claude Sees It, hooks, with the current schema

  8. Cap Bash Output Before It Reaches Context, one variable covering the general case

  9. Set the Compaction Window Deliberately, the real control the original article got wrong

  10. Trim MCP Server Overhead, mostly handled for you now, with what still helps

  11. Move Detail Out of CLAUDE.md and Into Skills, the 200-line target

  12. Keep Skill Descriptions Short, invisible overhead on every message

  13. Use an Output Style for Non-Coding Work, dropping the built-in coding instructions

  14. Scope Rules to the Files They Apply To, paths: frontmatter

  15. Write Prompts That Do Not Trigger Broad Scanning, specificity, plan mode, /rewind

  16. What to Do First, the order to work through it

What Is Modified From The Original Article

Three recommendations need reversing. None of them will have broken anything, because a setting Claude Code does not recognise is simply ignored, but they take up space in your configuration and give a false sense that something is being managed.

Remove contextCompactionThreshold from your settings.json. This key is not part of the Claude Code settings schema, so whatever value you gave it has had no effect. The real control is autoCompactEnabled, which defaults to true and summarises your conversation history when you approach the context limit. If you want to influence what survives compaction, you do that with a /compact instruction or a compact instructions section in your CLAUDE.md, not with a threshold number.

Delete your .claudeignore file. Claude Code does not read it. The reasoning behind that recommendation was wrong at a deeper level too, because it assumed Claude Code scans your whole workspace at session start. It does not. Files are read on demand when Claude decides it needs them, so a large SQLite database or a node_modules folder costs you nothing until something reads it. There is no indexing pass to exclude anything from.

Reconsider MAX_THINKING_TOKENS. This one still exists, but it only does what the original article claimed on models with a fixed thinking budget. Sonnet 5, Opus 4.7 and later, and Fable 5 all use adaptive reasoning, where the model decides per step whether thinking is warranted. On those models a value like 10000 is ignored. The only value that still bites is 0, which turns thinking off entirely except on Fable 5, where it cannot be turned off at all. If you are running any current model, the control you want is the effort level, covered below.

The remaining changes from the original article were sound, and they carry forward into what follows.

Start By Looking At Where the Tokens Go

Guessing at token consumption is how you end up with configuration that does nothing. Two commands give you the actual picture.

/context breaks down what is occupying your context window right now, separated into the system prompt, MCP tool definitions, memory files, conversation history, and remaining free space. Run it in a session that feels sluggish and you will usually find one item accounting for far more than you expected, commonly an oversized CLAUDE.md or a chatty MCP server.

/usage shows token counts and, on a Pro, Max, Team or Enterprise plan, how your recent activity maps against your plan limits. Anthropic documents the full breakdown in its guide to managing costs. It attributes usage to skills, subagents, plugins, and individual MCP servers, each as a percentage of the total. It also identifies behaviours responsible for 10% or more of recent usage, such as long context or cache misses, which is the fastest route to finding out what is draining a session. Press d or w to switch between the last 24 hours and the last seven days.

Do this before changing any settings. The point of the exercise is to fix what is costing you rather than what seems plausible.

Clear Between Unrelated Tasks

Claude Code sends your entire conversation with every message. A one-line question asked in a session that has been open since morning costs tokens for the whole day's conversation, not for the one line. This is the largest single source of avoidable spend, and it has nothing to do with settings.

Use /clear when you switch to unrelated work. If you might want the session back, run /rename first to give it a findable name, then /resume to return to it later. Where you want continuity rather than a fresh start, /compact summarises instead of discarding, though compaction reads the whole conversation it summarises, so compacting a very large context is itself an expensive request. Clearing costs nothing.

Cache behaviour makes the timing matter as well. On a subscription, the prompt cache lives for an hour, dropping to five minutes once you are drawing on usage credits, and five minutes by default on an API key. Your first message after a longer break misses the cache and reprocesses the full context at full price. Coming back to a stale session for one small question is more expensive than starting a new one.

Set the Effort Level to Match the Work

Extended thinking is on by default because it improves performance on planning and reasoning work, and thinking tokens are billed as output tokens. The default budget can run to tens of thousands of tokens per request. For routine work, that is spend you do not need.

Effort levels are the control on current models. Opus 5, Sonnet 5, Opus 4.8 and Opus 4.7 all accept low, medium, high, xhigh and max, as does Fable 5. Run /effort on its own for a slider, /effort low to set it directly, or /effort auto to return to the model default. The active level appears in the session header beside the model name, so you can confirm what is running without opening anything.

Dropping to low effort for mechanical work, then raising it when you hit something genuinely difficult, tracks cost to the value of the reasoning far better than a fixed cap ever did. Changing effort mid-session does invalidate the cache, so set it at the start where you can.

There is also a managed effortLevel setting, which acts as a starting default for new sessions rather than a restriction. Users can still override it for any given session.

Route Subagents to Cheaper Models

When Claude Code spawns a subagent, that agent defaults to inheriting the main conversation's model. Run Opus as your default and five parallel subagents will each cost Opus rates, whether or not the work needs it.

The current mechanism is the model field in the subagent's frontmatter, in .claude/agents/, written like this.

---
name: file-sorter
description: Sorts and relocates files according to workspace conventions
model: haiku
---

Valid values are the aliases sonnet, opus, haiku and fable, a full model ID such as claude-sonnet-5, or inherit. The subagents documentation covers the full resolution order. Omitting the field is the same as inherit.

The CLAUDE_CODE_SUBAGENT_MODEL environment variable from the original article still works, and it sits at the top of the resolution order, which is the reason to be careful with it. Claude Code resolves a subagent's model by checking the environment variable first, then any per-invocation parameter, then the frontmatter, then the main conversation's model. Setting the variable therefore overrides every per-agent decision you have made in frontmatter. Per-agent frontmatter is the better instrument, because it lets a file-sorting agent run on Haiku while a research agent stays on Sonnet.

Since v2.1.198, subagents inherit the main conversation's extended thinking configuration, so thinking on in your session means thinking on in the subagent. There is no per-subagent thinking setting.

Keep Verbose Work Out of the Main Conversation

Running tests, fetching documentation, and processing log files all generate output far larger than the conclusion you need from it. Delegating that work to a subagent keeps the raw volume in the subagent's own context window and returns only a summary to your conversation.

The discipline that makes this pay is instructing agents to write their output to disk and return a file path with a one-line summary rather than the full content. Five agents each returning 100 lines adds 500 lines to your context in one step. Five agents each writing to disk and returning a path adds five. You then read back from disk only the section the next step needs. On parallel work the difference compounds through the session.

Filter Data Before Claude Sees It

A hook can preprocess tool output so the expensive content never reaches your context at all. Instead of Claude reading a 10,000-line log to find the errors, a hook greps for them and returns the matching lines, turning tens of thousands of tokens into hundreds.

The schema has changed since April, and the original article's version no longer applies. Hook configuration puts matcher as a sibling of hooks rather than nested inside it, so the shape is now this.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/filter-test-output.sh"
          }
        ]
      }
    ]
  }
}

The response your script writes to stdout has also changed. The old one-key decision object is superseded by a structured response carrying the hook event name alongside the permission decision.

{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow"}}

Run /hooks afterwards to confirm the hook is registered, or start with claude --debug and watch for the log line reporting modified tool input. The hooks reference documents every event and response field.

Cap Bash Output Before It Reaches Context

A hook is the precise instrument, but there is a blunt one that needs no script at all. The BASH_MAX_OUTPUT_LENGTH environment variable sets the maximum number of characters a bash command can return before Claude Code saves the full output to a file and hands Claude the file path with a short preview instead.

That single variable covers the general case the hook approach handles individually. A test suite that dumps thousands of lines, a verbose build, a log tail that runs longer than expected, all of them stop flooding your context, and the full output stays on disk where Claude can read the part it needs. Set it in the env block of your settings.json, alongside any other environment variables you use.

"env": {
  "BASH_MAX_OUTPUT_LENGTH": "20000"
}

Pick the value against your own work. Too low and Claude reads a file path on every routine command, which costs a round trip. Too high and it never triggers. Somewhere in the low tens of thousands of characters catches the genuine floods while leaving ordinary command output alone.

Set the Compaction Window Deliberately

The original article recommended a compaction threshold that does not exist. There is a real control, though it works differently. CLAUDE_CODE_AUTO_COMPACT_WINDOW sets the context capacity in tokens that Claude Code uses when calculating whether to auto-compact, and it defaults to the model's own context window, 200K on standard models or 1M on extended context models.

Setting it lower than the model's actual window makes compaction trigger earlier, which keeps your working context smaller through a long session at the cost of summarising sooner. On a model with a 1M window, leaving it at the default means a session can grow enormous before anything compacts, and every message in the meantime carries that full context. If you work in long sessions on an extended context model, this is the variable to reach for.

"env": {
  "CLAUDE_CODE_AUTO_COMPACT_WINDOW": "200000"
}

Treat this as a considered choice rather than a default to copy. Compaction costs a large request when it fires, so triggering it more often is not automatically cheaper. The gain comes from every message between compactions carrying less context.

Trim MCP Server Overhead

The advice here has largely been overtaken by a change in Claude Code itself. MCP tool definitions are now deferred by default, so only tool names enter your context at session start and full schemas load on demand when a tool gets used. The overhead the original article warned about is mostly handled for you.

What still helps is disabling servers you are not using, since even names and connection setup carry a cost, and every connect or disconnect invalidates your prompt cache. Run /mcp to see what is configured and turn off what you do not need. Where a command-line tool exists for the same job, such as gh, aws, or gcloud, it stays more context-efficient than an MCP server because it adds no per-tool listing at all. Claude can run those directly.

Move Detail Out of CLAUDE.md and Into Skills

Your CLAUDE.md loads into context at session start and stays there for the whole session. Detailed instructions for specific workflows, database migrations or pull request reviews or report formats, are consuming tokens on every message even when you are doing something unrelated.

Skills load on demand when invoked. Moving specialised instruction into a skill and keeping CLAUDE.md to essentials cuts your base context on every session. The documented target is under 200 lines.

Keep Skill Descriptions Short

Skill bodies load on demand, which is the whole point of them, but the name and description in each skill's frontmatter load at session start so Claude knows what is available. Every word of every description is present on every message, whether or not you invoke that skill.

A description only has to do one job, which is to trigger reliably when the work matches. Descriptions that run to 100 words or more, listing every phrase that might invoke the skill, cost you on every session for a job that 25 words does. Where a workspace carries fifty or sixty skills, this adds up to thousands of tokens of permanent overhead, and it is invisible because nothing about a long description looks wasteful when you are writing it.

Go through your skills and count the words in each description. Trim the longest ones to the trigger conditions and cut the padding, then check that invocation still works for the phrases you care about.

Use an Output Style for Non-Coding Work

Claude Code's default system prompt includes built-in software engineering instructions, covering how to scope changes, write comments, and verify work. If your work is writing, analysis, research, or anything else that is not software engineering, those instructions are consuming context on every session for no benefit.

A custom output style removes them. Create a markdown file in .claude/output-styles/ with frontmatter and your own instructions, and the built-in coding instructions are left out unless you explicitly set keep-coding-instructions: true. Leaving that field out is what strips them, since it defaults to false.

---
name: Writing assistant
description: Long-form writing and editing work
---

Add whatever standing instructions your own work needs below the frontmatter. Select the style through /config, and note that it takes effect after /clear or on the next session, because the system prompt is read once at session start.

The saving is modest per message and permanent across every session, which is the profile of a change worth making once. Bear in mind that your own added instructions increase the system prompt too, so a very long custom style can cost more than the coding instructions it replaced. Output styles also apply to the main conversation only, since subagents run their own system prompt.

Scope Rules to the Files They Apply To

Where your setup uses a rules directory, rule files can carry a paths: field in their frontmatter so the rule loads only when Claude is working on matching files.

---
paths:
  - "Clients/**"
---

A rule governing client documents has no reason to load while you are debugging a script. Scoping it to the relevant paths takes it out of your baseline and brings it in when it applies. Where a workspace has accumulated a dozen always-on rules, going through them and asking which are genuinely universal usually finds that several are not.

Write Prompts That Do Not Trigger Broad Scanning

Vague instructions cost more because they make Claude search. "Improve this codebase" sets off wide exploration across files. "Add input validation to the login function in auth.ts" does the work with two or three file reads.

For longer pieces of work, plan mode earns its keep. Shift+Tab cycles into it, and Claude explores and proposes an approach for approval before writing anything, which is considerably cheaper than discovering the direction was wrong after implementation. When you can see it heading the wrong way, Escape stops it immediately, and /rewind or a double-tap of Escape restores both conversation and code to an earlier checkpoint. Giving Claude a way to check its own work, a test case or an expected output, prevents the round trips that follow work you have to send back.

What to Do First

Run /context and /usage before touching anything, then remove the three dead settings from the original article. After that, the two habits worth building are clearing between unrelated tasks and matching the effort level to the work, because between them they address long context and thinking spend, which are the two largest line items for most people.

The structural changes are worth doing once and then forgetting about. Set BASH_MAX_OUTPUT_LENGTH first, since it takes one line and covers the largest uncontrolled input in most workflows. Then work through per-agent models, skill descriptions, an output style if your work is not primarily coding, path-scoped rules, and moving detail out of CLAUDE.md.

What /context tells you should decide the order. A workspace carrying sixty skills and twenty MCP servers has a different problem from one running long sessions on a 1M context model, and the numbers will say which you have.

Anthropic's own documentation puts average enterprise cost at roughly 13 dollars per developer per active day, with 90% of users staying under 30 dollars. If you are running well above that on a comparable workload, the cause is usually a session left open for hours or an expensive model left as the default rather than anything exotic in your configuration.

0 comments

Joinor login to leave a comment