Progressive disclosure: what stays in the window
By the end you can
- State how long an invoked skill's content stays in the conversation and what that costs per turn
- Split a skill into SKILL.md plus supporting files that load only when referenced
- Predict what survives auto-compaction from a session that invoked several skills
- Read the Skills row in /context as the listing cost you pay every turn, whether or not a skill fires
- Audit the skills that cost context and never get invoked, and say what each tool for it requires
You wrote a review-api skill and put the whole API reference in it — four
hundred lines of endpoint tables — reasoning that it costs nothing until the
skill runs. That reasoning is correct exactly once. You invoked it at ten in the
morning. It is four in the afternoon, you are three tasks downstream, and those
four hundred lines have been re-sent with every message you have typed since.
The docs name the fix once, in passing, pointing at the skills page for "complete Skill authoring guidance including progressive disclosure and tool restrictions" (Plugins). It means: put a small navigational core in front, and let the detail load only when something needs it.
Once loaded, it stays loaded
This is the sentence the whole lesson hangs on:
When you or Claude invoke a skill, the rendered
SKILL.mdcontent enters the conversation as a single message and stays there across later turns. […] write guidance that should apply throughout a task as standing instructions rather than one-time steps. — Skills
Two consequences, and people usually take only the first. It persists, so write
it as standing guidance: "First, do X" is a bad line in a skill body, because
it is still there on turn forty telling Claude to do X first. It persists, so
it is charged again on every turn — the docs draw that conclusion themselves,
calling every line of a loaded skill a recurring token cost and sending you to
the same conciseness test you would apply to CLAUDE.md content
(Skills). That test is Lesson 6.6's,
applied to a different file. Only the trigger differs: a CLAUDE.md line is
charged from startup, a skill body from the turn you invoke it — and for as much
of it as compaction later keeps, which the next section puts a number on.
The permissions half does not persist. An allowed-tools grant clears when you
send your next message even though the content stays — Lesson 7.2 made that
point from the other side. Instructions are durable; grants are not.
The 500-line line, and the directory around SKILL.md
The documented size guidance is one sentence:
Keep
SKILL.mdunder 500 lines. Move detailed reference material to separate files. — Skills
Be clear about what that is. It is a tip, not a limit: no documented behaviour changes at 500 lines and nothing rejects a longer file. The caps Claude Code actually enforces are on the listing, further down this lesson. Treat 500 as the point where you should be able to say why the file is that big.
The second half of the sentence is the mechanism. A skill is a directory, and only one file in it loads on invocation:
my-skill/
├── SKILL.md (required - overview and navigation)
├── reference.md (detailed API docs - loaded when needed)
├── examples.md (usage examples - loaded when needed)
└── scripts/
└── helper.py (utility script - executed, not loaded)In the docs' words, large reference docs, API specifications and example collections "don't need to load into context every time the skill runs" (Skills).
Note the third annotation in that tree: helper.py is "executed, not loaded". Its
source is not pulled into the window when the skill runs — so a fiddly
deterministic step, parsing a changelog or checking a version, is cheaper as a
script the skill calls than as prose telling Claude to do it by hand. Lesson 7.3
covers making one resolve from anywhere with ${CLAUDE_SKILL_DIR}.
A sibling file only helps if Claude knows it exists and what is in it, which is
SKILL.md's actual job. The documented form is a markdown link with a
description of what is behind it — For complete API details, see [reference.md](reference.md) under an Additional resources heading. The
description does the work: it is what Claude decides on before reading anything.
What compaction keeps
Lesson 3.2 gave you a row in a table: invoked skill bodies come back after compaction, "capped per skill and in total; oldest dropped first". Here are the numbers behind it.
Claude Code re-attaches the most recent invocation of each skill after the summary, keeping the first 5,000 tokens of each. Re-attached skills share a combined budget of 25,000 tokens. Claude Code fills this budget starting from the most recently invoked skill, so older skills can be dropped entirely after compaction if you have invoked many in one session. — Skills
Do the arithmetic once and it changes how you write the file. Invoke seven skills of about 6,000 tokens each across a long session, then compact: each is truncated to its first 5,000 tokens, and the 25,000-token pool holds five of them, filled from the most recent backwards. The two you invoked earliest are not truncated — they are gone.
Which half survives is documented, and the docs turn it into an authoring rule:
Truncation keeps the start of the file, so put the most important instructions near the top of
SKILL.md. — Context window
The listing you pay for on every turn
Everything above is the cost of a skill you used. There is a second cost, and it is charged whether you use the skill or not:
Every skill in the skill listing adds to your context on every turn, whether or not Claude ever uses it. — Skills
The listing is names plus descriptions, and it is budgeted:
The listing always contains every skill name, but if you have many skills, Claude Code shortens descriptions to fit the listing's character budget […] The budget scales at 1% of the model's context window. When the listing overflows, Claude Code drops descriptions starting with the skills you invoke least, so the skills you use most keep their full text. — Skills
That 1% is skillListingBudgetFraction, whose default is 0.01
(Settings reference). The
overflow is indirect rather than silent: nothing errors in the session, a
rarely-used skill loses its description, and the symptom weeks later is that
Claude stopped picking it — a Lesson 7.2 problem caused by a Lesson 7.5 budget.
There is one signal, and you have to go looking for it: when the listing exceeds
its budget, Claude Code writes a warning to the debug log, visible with
--debug.
So a skill directory has four costs with four different clocks:
| What | When you pay for it | Size set by |
|---|---|---|
| Its listing entry | Every turn, from startup | description plus when_to_use, capped at 1,536 characters by default (skillListingMaxDescChars) |
Its SKILL.md body | Every turn after it is invoked | The rendered length of the file |
| A supporting file | Only on the turns Claude reads it | That file |
| A bundled script | Not loaded — it is executed | — |
The first row has one documented exception, from Lesson 7.2: a skill with
disable-model-invocation: true keeps its description out of context entirely,
and the full body still loads when you invoke it. That is the one way to own a
skill and pay nothing for it until you type its name.
Read /context with that table in hand: its Skills row is the first row, not the
second.
The Skills row in
/contextreports the size of the listing after the budget is applied, so it matches what the model receives. — Skills
That has been true since v2.1.196. Before then the row counted the full text of every description and could show a value several times larger than the budget — the size of what you wrote rather than of what the model was sent. The number in front of you now is the one the model actually receives, so it is a figure to act on rather than an upper bound.
Finding the skills you never use
The listing cost scales with the number of skills you have installed, not the number you use, so the cheapest optimisation available is deletion.
Run
/skill-doctorto see what each of your skills costs and how often it gets used, so you can decide which ones to turn off. — Skills
It flags skills in the listing that have never been invoked and says where to turn them off, and of those, the docs say to start with the ones that have the highest context cost. It covers your session's skills other than bundled and enterprise ones, and it runs in the terminal on the machine hosting the session — over Remote Control it declines.
There is a second report, and it is the broader of the two. The capability list
that Commands gives /doctor covers
unused skills, MCP servers and plugins against their context cost, alongside
install health and slow hooks, and it reports its findings before it changes
anything. Read /doctor as the estimate and /skill-doctor as the per-skill
detail. Before v2.1.205, /doctor was a built-in command rather than a bundled
skill, and it "opened a read-only diagnostics screen and pressing f sent the
report to Claude". A reader, not a writer, which is Lesson 6.5's subject.
A capability list and the dated sentence under it are Lesson 3.4's habit arriving in your own toolchain. The list is written against the current build and is the part you can act on today; the version note tells you what changed, not what survived, and is the only part of the entry speaking about any other build at all. Check which of the two you are reading before you plan around it.
When /skill-doctor is out of reach, the docs answer the phone case directly:
run it in the terminal on the machine the session is running on. Where that is
not available to you, /doctor still reports the skill listing's context cost
and its biggest contributors, and the rest is manual — you already have the
number for it. Take the /context Skills row from the end of the last section
and set it against a listing you can read yourself. Delete what you no longer
recognise. Turning a skill off without editing its file is skillOverrides,
which is Lesson 7.6.
The two questions before a line goes in
Progressive disclosure is not a feature you switch on. It is two questions, asked per paragraph while you write the file:
- Does this need to be true for the rest of the task? If yes, it belongs in
SKILL.md, near the top, phrased as a standing rule. - Is this reference material needed on some invocations? If yes, it belongs
in a sibling file that
SKILL.mdnames and describes.
A paragraph that answers no to both is the line Lesson 6.6 told you to delete
from CLAUDE.md. The only difference is that you pay for it later, which makes
it harder to notice and no cheaper.
Checkpoint
-
You invoke a 900-line skill at the start of a session and never invoke it again. Twenty turns later, how many times has its body been sent, and what would have made that number smaller without losing any of the content?
Show answerAnswer
On every turn since you invoked it — roughly twenty times, not once. The rendered
SKILL.mdenters the conversation as a single message and stays there across later turns, so every line of it is a recurring cost. Invoking once does not mean paying once.Progressive disclosure keeps all 900 lines and charges you for far fewer of them: leave a small navigational core in
SKILL.md— the guidance that has to be true for the rest of the task, near the top — and move the reference material into sibling files thatSKILL.mdnames and describes with a markdown link under an Additional resources heading, so each loads only on the turns Claude reads it. A deterministic step is cheaper still as a bundled script, which is executed rather than loaded. Do not link the sibling with an@: that is attachment, not navigation, and it puts the lines straight back in. -
A long session compacts after you invoked six skills. Which invocation of each skill comes back, how much of it, and which skills are at risk of not coming back at all?
Show answerAnswer
The most recent invocation of each skill is re-attached after the summary, and only its first 5,000 tokens. Truncation keeps the start of the file, which is exactly why the important instructions belong near the top of
SKILL.md.The re-attached skills then share a combined 25,000-token budget, filled starting from the most recently invoked. At 5,000 tokens each that pool holds five, so with six sizeable skills the one you invoked earliest is at risk — and it is dropped entirely rather than truncated. Small skills leave room for more of them; the ordering rule is the same either way. Re-invoking after compaction is what restores a large skill's full content.
-
A teammate says their skill "isn't costing anything because Claude never triggers it". Under what documented mechanism are they wrong, which row of
/contextshows it, and what one frontmatter field would have made them right?Show answerAnswer
The skill listing is the mechanism: "Every skill in the skill listing adds to your context on every turn, whether or not Claude ever uses it." Their skill's name and description are being sent from startup onwards; never triggering only means they never pay the second cost, the body.
The Skills row of
/contextshows it — the listing's size, not the body's, and since v2.1.196 it reports that size after the budget is applied, so it is what the model actually receives rather than what they wrote. The field that would have made them right isdisable-model-invocation: true, which keeps the description out of context entirely while the full body still loads when they type the command themselves. That is the one way to own a skill and pay nothing for it until you invoke it.