Anatomy of a Claude Code Skill — and Why Progressive Disclosure Is the Whole Trick

Date:

A skill looks like a folder with a Markdown file in it. What makes it work is not the content — it is when each part of that content loads.

The short answer: A Claude Code skill is a folder — a SKILL.md plus optional scripts/, references/, and assets/ — that packages a repeatable capability the agent can reach for on its own. Its power comes from progressive disclosure: only the name and a one-line description sit in the model’s context all the time; the SKILL.md body loads only when the skill triggers; and bundled files load only when they are actually read or run. So a skill can carry an unlimited amount of know-how while costing almost nothing until it is needed. Get that layering right and a skill stays small, triggers reliably, and expands forever; get it wrong and you have just pasted a wall of text into every conversation.

A skill is how you teach an agent a procedure once and let it apply that procedure across many future tasks without you re-explaining it. It is not a plugin, an API, or a chat macro. It is a small, self-contained directory the agent discovers, decides whether a task matches, and then follows — the packaged form of “here’s how we do this, every time.” (The official Agent Skills overview frames the same idea across products; this piece is about the Claude Code shape of it.)

The three tiers, and why they exist

The context window is finite and shared. Every token a skill occupies is a token unavailable for the actual work. If a skill’s full playbook lived in context whenever it might be relevant, ten useful skills would crowd out the task itself. Progressive disclosure solves this by loading a skill in three stages, each paid for only when justified.

Tier 1 — metadata (always loaded). The skill’s name and description — roughly a hundred words — are the only part always present. The agent reads them to decide whether a task matches. This tier is tiny on purpose: it is the index, not the book.

Tier 2 — the SKILL.md body (loaded on trigger). When the agent judges the task a match, it reads the body: the actual instructions. This is where the method lives — the steps, the guardrails, the “why.” It persists for the rest of the turn once loaded, but it never loads for tasks that don’t match.

Tier 3 — bundled resources (loaded on demand). Anything in references/ is read only when the body points the agent to it. Anything in scripts/ is executed — it never enters context as text at all. This is the tier that lets a skill be arbitrarily large without cost: a 2,000-line reference document or a 500-line script sits inert on disk until the one moment it is needed.

Metadata is the index, the body is the chapter, and the references are the appendix you only turn to when the chapter sends you there.

How a skill loads: three tiersOnly the index is always in context; the rest is paid for when justified.
Tier 1 – Metadata (always loaded)

Name + one-line description, ~100 words. The only part always in context – the INDEX the agent reads to match a task.

Tier 2 – SKILL.md body (on trigger)

The actual method: steps, guardrails, the why. Loads only when the task matches; never for tasks that don't. The CHAPTER.

Tier 3 – Bundled files (on demand)

references/ read when the body points to them; scripts/ execute without entering context at all. The APPENDIX – effectively unbounded.

A skill's capacity is not how much it contains, but how well it decides what to load.

The description is the trigger — treat it as such

Because Tier 1 is all the agent sees when deciding, the description is not blurb — it is the entire triggering mechanism. A vague description under-triggers: the skill exists but never fires, because the agent didn’t recognize the task as a match. So the description should state both what the skill does and the concrete situations that should invoke it, including the plain-language ways a user might ask without naming the skill. It is the one place worth being slightly pushy: name the trigger phrases, the near-synonyms, the “even when they don’t say X” cases. Because that failure is silent, it’s worth measuring and tuning triggering directly rather than guessing whether the description fires.

This is also the only part with a hard size limit, which brings us to the question everyone eventually asks.

How big can a skill be? (The size limits, honestly)

  • Description: the one hard cap — around 1,024 characters as enforced by the packaging tool (the platform documents a higher 1,536-character ceiling; the stricter of the two is what bites, so aim under ~1,000). Keep it tight; offload everything else.
  • SKILL.md body: guidance, not a hard limit — keep it under ~500 lines so the on-trigger cost stays modest. If you’re approaching that, it’s a signal to move detail into references/.
  • Bundled files, file count, total package: effectively unbounded for context purposes, because they don’t sit in context — they load on demand (references) or execute without loading (scripts).

So “how do I make my skill bigger?” is the wrong question. The limit that actually matters is context budget, and you don’t raise it — you route around it with the three tiers. A skill’s real capacity is not its size; it is how well its SKILL.md decides what to load and when.

Structuring for expansion

The pattern that follows from all this: keep SKILL.md a lean router, and grow the skill by adding files it points to.

  1. The body holds the immediate method and the decision of what to consult next — not the exhaustive detail.
  2. Depth goes in references/ with a clear “read this when…” pointer. A large reference gets a table of contents so the agent can jump to the relevant section instead of loading all of it.
  3. Repetitive or deterministic logic goes in scripts/, invoked by the body — written once, executed forever, never re-derived and never in context.

A concrete example from practice: we built a skill that batch-vaults images into a content store with rich metadata. The SKILL.md body is short — it explains the model and the workflow. The exact field reference (every option, every edge case) lives in a references/ file the body tells the agent to open only when building the input. The whole engine — the code that actually does the vaulting, render-checks each image, and stays safe against writing to the wrong target (the discipline a store-mutating skill needs) — lives in a single script the body calls. Adding a new capability later means adding one reference file and a one-line pointer, not swelling the body. The skill can double in capability without costing a single extra token until that capability is used.

A skill’s capacity is not how much it contains, but how well it decides what to load.

Two rules keep the structure honest. Same job, more depth → a reference file. Different job, different trigger → a separate skill (its own description, so it triggers independently). When a set of related skills grows, a plugin can bundle them — but that’s packaging, not a reason to merge distinct triggers into one overloaded skill. And wherever a skill lands while you build it, commit it into the repo whose domain it serves the moment it’s worth keeping — a skill isn’t done until it’s tracked.

The short version

A Claude Code skill is a folder — SKILL.md plus optional scripts/, references/, assets/ — and its design is entirely about when each part loads. Metadata (name + description) is always in context and is the trigger, so write the description to fire reliably and keep it under ~1,000 characters, its one hard limit. The body loads on trigger; keep it a lean router under ~500 lines. References load on demand and scripts execute without ever entering context, so bundled resources are effectively unbounded. Grow a skill by adding files the body points to — depth as a reference, logic as a script — not by inflating the body. Same job deeper is a reference; a different job is a new skill.

Frequently Asked Questions

Is a skill the same as a plugin?

No. A skill is a single packaged capability (one SKILL.md folder). A plugin is a distribution unit that can bundle several skills together, but each skill still has its own description and triggers on its own.

Why isn’t my skill triggering?

Almost always the description. If it doesn’t name the situations and phrasings that should invoke the skill, the agent won’t recognize a matching task. Rewrite the description to be specific about when to use the skill, not just what it does.

Do bundled scripts count against the context limit?

No. Scripts are executed, not read into context. That is exactly why deterministic or repetitive logic belongs in a script rather than as prose in the body.

What’s the actual maximum size of a SKILL.md?

There’s no hard cap on the body — the ~500-line figure is guidance to keep the on-trigger context cost reasonable. The only hard limit is the description (~1,024 characters in the packager). If the body is getting long, that’s the cue to move detail into references/.

When should I split one skill into two?

When the second concern has a different trigger. If you’d want the agent to reach for it in situations the first skill’s description shouldn’t cover, it’s a separate skill. If it’s just more detail on the same job, it’s a reference file.

Share post:

Subscribe

Popular

More like this
Related

How to Merge Spreadsheets by URL (and Why Our Tool Reported 5 Misses That Weren’t)

Matching two spreadsheets on a URL column is the same job as matching a stock list to a price list by product code. It goes wrong in the same two places: how you clean the code, and how you count what didn't match.

Many-to-One: Why a Mapping Backlog Outgrows Its Target Taxonomy

You're mapping a messy source vocabulary onto a clean target taxonomy. The target has about 5,600 slots, so the job must be roughly 5,600 decisions — right? The backlog is already past 8,900, and still climbing.

The Fix That Didn’t Take: When a Content-Hash Gate Skips Your Code Change

You shipped a fix to how one field is computed, re-ran the pipeline across everything, and it reported a clean run. Then the consistency check still flags those records as wrong. The fix is in the code, the rebuild "ran" — and the records never changed. Your own optimisation skipped them.

Your Dedup Scan Is Over-Counting — Because It Forgot What You Already Fixed

The report said 80 duplicate groups still to resolve. You'd been resolving them for days. You run it again after a big batch and it *still* says 80-ish. The backlog isn't stubborn — the scan is counting work you already finished.