Context Budget Audit: /skill-doctor, Output Caps and the Six Numbers That Fill Your Window
A Claude Code project accumulates context debt the way a laptop accumulates browser tabs. Every skill you installed adds a line to a listing Claude re-reads on every turn. Every subagent adds a description. Every CLAUDE.md paragraph you wrote in March loads in September whether the task needs it or not. And every npm test dumps up to 30,000 characters into the conversation. None of it is visible until the session starts forgetting instructions or the bill stops matching the work.
Context management covers the two commands you use in the moment, /clear and /compact. This page is the audit you run once per project: six places where Claude Code spends context before you type anything or between your turns, the setting that governs each, and the number it defaults to. Everything here is in the official docs as of September 2026, and most of the knobs are newer than the folklore about them.
- Measure before you cut: read /context, /usage attribution, and /doctor's listing estimate so you fix the biggest line item first
- Prune the skill listing with /skill-doctor (v2.1.252+) and the four skillOverrides states, and know the 1%-of-window budget the listing is capped at
- Cap what a shell command or background task returns inline (30,000 and 32,000 characters by default) with bashOutputMaxChars and taskOutputMaxChars
- Stop paying for CLAUDE.md in every subagent with omitClaudeMd (v2.1.271+) and keep subagent descriptions under the 15,000-token warning line
- Set the auto-compact window on purpose (/autocompact, autoCompactWindow) and understand the 25,000-token budget that decides which invoked skills survive compaction
- Cap effort fleet-wide with maxEffortLevel when thinking tokens, not context, are the real bill
What is in the window before you type
Two facts make this diagram actionable. Everything in the left box is paid on every request, because Claude Code sends the full conversation each turn and only the cache-read discount softens it. And the right box is where a single verbose command can add more than the whole left box in one step. The audit below works left to right.
The audit
- Run /context for a live breakdown by category with optimization suggestions, including which CLAUDE.md and auto-memory files loaded. On a Pro, Max, Team, or Enterprise plan, /usage attributes recent usage to skills, subagents, plugins, and individual MCP servers as percentages, and flags behaviors (long context, cache misses) that account for 10% or more. /doctor estimates the skill listing's context cost and its biggest contributors. Write the three biggest line items down before changing anything.
- Every skill in the listing costs context on every turn whether or not Claude uses it. /skill-doctor (v2.1.252+) shows each skill's context cost and invocation frequency, flags skills never invoked, and tells you where to turn them off; it also lists plugins you have not used recently. Start with the highest-cost unused ones. Interactive sessions open the report in the /plugin manager's Stats tab; with -p it prints as text. It does not cover bundled or enterprise skills, needs feature-flag fetching, and refuses over Remote Control.
- Four states per skill: on (name and description listed), name-only (listed without description, still invocable), user-invocable-only (hidden from Claude, still in the / menu), off. The /skills menu writes this for you: highlight a skill, press Space to cycle, Esc to save to .claude/settings.local.json. Plugin skills are managed through /plugin instead. Setting disableBundledSkills: true removes Claude Code's own bundled skills and workflows in one line.
- The listing is capped at 1% of the model's context window (skillListingBudgetFraction, default 0.01). When it overflows, Claude Code keeps every name but drops descriptions starting with the least-used skills, which strips the keywords Claude needs to auto-select them. Each skill's description plus when_to_use is also cut at 1,536 characters (skillListingMaxDescChars). Put the key use case in the first sentence.
- Keep CLAUDE.md under 200 lines and move workflow-specific instructions (PR review, migrations) into skills, which load only when invoked. Auto memory loads only its first 200 lines or 25 KB, so a bloated MEMORY.md silently truncates. Subagent descriptions are read every turn: when the combined descriptions of your custom subagents pass 15,000 tokens, Claude Code warns at startup. Move detail into each subagent's system prompt, which loads only when it runs.
- A successful Bash or PowerShell command returns up to roughly 30,000 characters inline by default; past that Claude gets a short preview plus a file path and reads the file on demand. A failing command returns up to 10,000 characters as a head-and-tail excerpt. bashOutputMaxChars (v2.1.261+, clamped to 4,000–128,000) sets the inline ceiling and read-back window together and makes Claude Code ignore BASH_MAX_OUTPUT_LENGTH. taskOutputMaxChars does the same for background tasks read with TaskOutput (default 32,000, same range). Lower them on projects with chatty build tools; raise them only when Claude keeps opening the saved file anyway.
- A non-fork subagent loads every level of your CLAUDE.md hierarchy plus a git-status snapshot, on top of its own prompt. The built-in Explore and Plan agents skip both. For custom subagents that get everything from the delegation prompt, set omitClaudeMd: true in the frontmatter (v2.1.271+): user, project, and local CLAUDE.md files are skipped; managed policy files still load. Ignored when the agent runs as the main session agent. For large shared instructions in headless runs, pass --append-subagent-system-prompt-file (v2.1.261+) instead of stuffing them into every description.
- autoCompactWindow is a token count from 100,000 to 1,000,000, capped at your model's window; unset means Claude Code picks a window tuned for the model. /autocompact 500k writes it to user settings; --autocompact overrides for one session; CLAUDE_CODE_AUTO_COMPACT_WINDOW overrides both. CLAUDE_AUTOCOMPACT_PCT_OVERRIDE (1–100) can only lower the trigger point. After compaction, invoked skills are re-attached at up to 5,000 tokens each within a 25,000-token total, most recent first, so older skills can be dropped entirely. If a skill must survive, re-invoke it after /compact.
- Thinking tokens are billed as output. maxEffortLevel (v2.1.267+) caps the effort any session can use: one of low, medium, high, xhigh, or max (max = no cap). It applies before every request on every provider, the lowest cap across scopes wins, and a cap below xhigh disables ultracode. Per-model caps go in modelSettings. Deploy through managed settings to enforce for an organization.
A settings block you can paste
Project-local context caps (.claude/settings.local.json)
{
"bashOutputMaxChars": 12000,
"taskOutputMaxChars": 12000,
"skillOverrides": {
"legacy-migration-notes": "name-only",
"deploy-prod": "user-invocable-only",
"old-design-system": "off"
},
"autoCompactWindow": 500000,
"maxEffortLevel": "high"
}Read it top to bottom as decisions, not defaults. The two output caps assume a chatty test runner; drop them back toward the 30,000 / 32,000 defaults if Claude starts opening the saved output file on every run. The three overrides keep the skills reachable without paying for their descriptions. The compaction window is an explicit choice for a 1M-context model where you would rather compact at half than at the model-tuned point. The effort cap is the one line here that changes output quality, so set it last and only after /usage shows thinking tokens dominating.
Subagent that does not load CLAUDE.md (.claude/agents/repo-auditor.md)
--- name: repo-auditor description: Audits a repository for dead code and unused exports. Use for read-only sweeps. tools: Read, Grep, Glob, Bash model: sonnet omitClaudeMd: true --- You are a read-only auditor. Everything you need is in the delegation prompt. Report findings as a table of path, symbol, and evidence. Do not edit files.
Run the skill report in a headless session
claude -p "/skill-doctor"
Common mistakes
- Deleting skills instead of collapsing them. name-only keeps a skill invocable at near-zero listing cost; off removes it from the / menu too. Most 'unused' skills should become name-only, not disappear.
- Raising bashOutputMaxChars to the 128,000 ceiling because one build log overflowed. That makes every future command up to 4× more expensive inline. Filter the log with a PreToolUse hook (grep for FAIL, head -100) instead; the costs docs show the exact hook.
- Setting autoCompactWindow above the model's context. Claude Code caps it at the window silently, so the setting looks applied and does nothing.
- Assuming a subagent is cheap because its context is separate. Its startup still includes every CLAUDE.md level and a git snapshot unless it is Explore, Plan, or sets omitClaudeMd.
- Reading /skill-doctor over Remote Control from a phone. It returns 'Skill usage reports are not available on this connection.' Run it in the terminal where the session lives.
- Expecting an invoked skill to survive /compact. Only the most recent invocations fit in the 25,000-token re-attach budget, at 5,000 tokens each. Re-invoke the ones you still need.
Quick check
Check yourself
0/6- Measure first: /context for the live breakdown, /usage for attribution by skill, subagent, plugin, and MCP server, /doctor for the listing estimate.
- The skill listing is a per-turn tax capped at 1% of the window. /skill-doctor tells you what to collapse; name-only keeps a skill usable at near-zero cost.
- Tool output is the fastest way to blow a window: ~30,000 characters inline per successful command, 32,000 per background task. Cap with bashOutputMaxChars / taskOutputMaxChars, or filter with a hook.
- Subagents are not free at startup: every CLAUDE.md level plus git status, unless Explore, Plan, or omitClaudeMd. Keep custom descriptions under 15,000 tokens combined.
- Compaction keeps only the most recent invoked skills (5,000 each, 25,000 total). Set autoCompactWindow deliberately, and re-invoke what must survive.
- When thinking tokens dominate the bill, maxEffortLevel caps effort fleet-wide; lowest scope wins and it holds on every provider.
Sources & further reading
- Claude Code docs — Settings reference —
autoCompactWindow,bashOutputMaxChars,taskOutputMaxChars,maxEffortLevel,skillListingBudgetFraction,skillOverrides,disableBundledSkills - Claude Code docs — Extend Claude with skills —
/skill-doctor, the listing budget, description cap, compaction re-attach budget - Claude Code docs — Tools reference: output limits — inline ceilings for valid and failing commands
- Claude Code docs — Subagents — what loads at startup,
omitClaudeMd, the 15,000-token description warning - Claude Code docs — Manage costs —
/usageattribution, the 200-line CLAUDE.md guidance, the test-output filter hook - Claude Code docs — Explore the context window — the interactive simulation this page's diagram summarizes
- Related on AILmanac: MCP token cost — the MCP-specific half of the same audit
- Related on AILmanac: Subagent fleet limits — the concurrency and budget side of subagents
Next
- Context management —
/clearvs/compactin the moment, once the audit is done - Skills — writing skills that earn their listing line
- Subagents — designing the delegation prompt so
omitClaudeMdis safe