Claude Skills: SKILL.md, Progressive Disclosure, and Bundled Scripts
Learning Objectives
Author a valid SKILL.md with correct YAML frontmatter and a description that triggers reliably.
Apply progressive disclosure to keep skill context cheap until the skill is actually needed.
Bundle helper scripts and reference files so a skill can do deterministic work instead of token-by-token reasoning.
Decide when a Skill is the right abstraction versus a raw tool or an MCP server.
Pre-Reading Check — What a Skill Is
1. On disk, what is a Claude Skill?
2. At startup, what does Claude pre-load from each installed skill?
3. Using Anthropic's framing, which statement best distinguishes Skills from MCP?
1. What a Skill Is
Key Points
A Claude Skill is a folder on a filesystem with exactly one required file, SKILL.md, plus any number of optional scripts and reference files.
Because a skill is just files, it can be version-controlled in Git, code-reviewed, and shared by copying a directory.
Skill discovery is a two-field problem: at startup Claude pre-loads only each skill's name and description, and triggers on those alone.
Anthropic's boundary: a tool grants a capability, an MCP server grants connectivity, and a Skill grants procedural knowledge — and they compose.
Where a skill runs matters: the Claude API sandbox has no network access, claude.ai varies by admin settings, and Claude Code has full local network access.
Skills are a third abstraction that sits at a different layer from tools and MCP servers. Where a tool grants a capability and an MCP server grants connectivity, a Skill grants procedural knowledge — it teaches Claude how to do a task the way your organization wants it done, without permanently taxing the context window.
The most important thing to internalize is that a skill is not an API object or a piece of pasted prompt text. It is a folder. A minimal skill is just pdf-processing/SKILL.md; a richer one adds reference docs (FORMS.md, REFERENCE.md) and a scripts/ directory of executable helpers.
graph TD
ROOT["pdf-processing/ (skill folder)"] --> SKILL["SKILL.md (required: frontmatter + body)"]
ROOT --> FORMS["FORMS.md (reference, read on demand)"]
ROOT --> REF["REFERENCE.md (deeper API notes)"]
ROOT --> SCRIPTS["scripts/"]
SCRIPTS --> FILL["fill_form.py (run via bash)"]
SCRIPTS --> VAL["validate.py (deterministic check)"]
SKILL -.->|"references, loaded only when needed"| FORMS
SKILL -.->|"references, loaded only when needed"| REF
SKILL -.->|"instructs Claude to run"| SCRIPTS
Skill discovery is the mechanism by which Claude decides, out of every installed skill, which one is relevant. At startup Claude pre-loads only the name and description from each skill into its system prompt — nothing else — and uses those two fields alone to judge relevance across a library that could hold 100 or more skills. When a request matches, Claude reads the full SKILL.md body via bash, and deeper bundled files only if the task requires them.
flowchart TD
START["Startup: preload name + description of every skill"] --> REQ["User request arrives"]
REQ --> MATCH{"Request matches a skill's description?"}
MATCH -->|"No"| SKIP["No skill loaded, answer normally"]
MATCH -->|"Yes"| BODY["Read full SKILL.md body via bash (Level 2)"]
BODY --> NEED{"Task needs a bundled file or script?"}
NEED -->|"No"| DONE["Complete task with body guidance"]
NEED -->|"Yes"| READ["Read reference file or run script (Level 3)"]
READ --> DONE
The cleanest way to place Skills is Anthropic's own one-liner: "MCP connects Claude to data; Skills teach Claude what to do with that data." The three abstractions are complementary, not competing.
Dimension
Claude Skill
Tool
MCP server
What it provides
Procedural knowledge / methodology
A single capability or action
Connectivity to external data & systems
Physical form
A folder (SKILL.md + optional files)
A JSON schema + handler code
A program speaking the MCP protocol
Loaded into context
Only name + description until triggered
Full tool schema (unless deferred)
Tool schemas for the server's tools
Best for
Review workflows, conventions, testing patterns
get_weather, send_email
Databases, GitHub, Drive, browsers
Because a skill's scripts are executed by Claude, where it runs matters. On the Claude API, skills run in a sandbox with no network access and no runtime package installation. On claude.ai, network access varies by admin settings. In Claude Code, skills have full local network access.
[Animation slot: staged reveal of a skill folder — SKILL.md first, then reference files and scripts appearing as "loaded on demand."]
Post-Reading Check — What a Skill Is
1. On disk, what is a Claude Skill?
2. At startup, what does Claude pre-load from each installed skill?
3. Using Anthropic's framing, which statement best distinguishes Skills from MCP?
Pre-Reading Check — Authoring SKILL.md
1. Which two frontmatter fields are the only required ones in a valid SKILL.md?
2. Why must the description be written in the third person?
3. A skill "doesn't work" and never activates. Where does the fault most often lie?
2. Authoring SKILL.md
Key Points
Every skill opens with YAML frontmatter (delimited by ---) followed by a Markdown body.
Exactly two fields are required: name (≤64 chars, lowercase/numbers/hyphens, gerund form preferred, no "anthropic"/"claude") and description (≤1,024 chars, third person).
The description is the trigger contract — it must state both what the skill does and when to use it, with concrete trigger terms.
The body carries procedural knowledge; keep it under ~500 lines and add only what Claude doesn't already know.
Most skills that "don't work" simply never trigger — the fault traces back to the description.
The name rules are mostly mechanical, but the reserved-word ban is easy to trip over (a skill named claude-helper is invalid), and the gerund recommendation (processing-pdfs, analyzing-spreadsheets) makes the library read as a catalog of activities rather than vague nouns.
Field
Limit
Rules & best practice
name
≤ 64 chars
Lowercase, numbers, hyphens only; no reserved words "anthropic"/"claude"; should match folder name; prefer gerund form.
description
≤ 1,024 chars
Non-empty; describe both what the skill does and when to use it; write in the third person.
Because the description alone drives discovery, three properties separate one that fires from one that sits dormant: it is specific with concrete trigger terms, it states both what and when, and it is written in the third person. Anthropic's contrast:
Good: "Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction."
Bad: "Helps with documents" (no trigger terms, no when).
Bad: "Does stuff with files" (specifies nothing).
Below the frontmatter, the Markdown body holds the procedural knowledge. Anthropic's mental model is a table of contents: give the overview and workflow, and point to deeper materials rather than inlining every detail. Keep it under 500 lines, and respect the default assumption that "Claude is already very smart" — add only context Claude doesn't have.
The recurring authoring mistakes all degrade triggering: a vague description, a missing when, first/second-person phrasing, reserved words or a bad name, and an over-stuffed body past ~500 lines. Anthropic recommends evaluation-driven development: build three or more evals, baseline without the skill, then write minimal instructions and measure the lift.
[Animation slot: side-by-side "good vs. bad description" — highlight trigger terms (file types, operations, user phrasings) lighting up as matches.]
Post-Reading Check — Authoring SKILL.md
1. Which two frontmatter fields are the only required ones in a valid SKILL.md?
2. Why must the description be written in the third person?
3. A skill "doesn't work" and never activates. Where does the fault most often lie?
Pre-Reading Check — Progressive Disclosure
1. Which sequence correctly orders the three loading levels?
2. Why can you install 100+ skills without a meaningful context penalty?
3. A user asks only to extract text from a PDF (no forms). What happens to FORMS.md?
3. Progressive Disclosure
Key Points
Progressive disclosure loads a skill's content in stages "as needed," enabled directly by the filesystem architecture.
Anthropic frames the context window as a "public good"; a skill should occupy only what the current task requires.
Three levels: metadata (~100 tokens/skill, always), the SKILL.md body (<~5k tokens, on trigger), and bundled resources (effectively unlimited, only when needed).
Unused files cost zero tokens, so you can install many skills and bundle unbounded reference material without a context penalty.
Authoring implications: body under 500 lines, references one level deep, and a table of contents for any reference file over 100 lines.
Progressive disclosure is what makes Skills viable at scale. Rather than loading everything upfront, "Claude loads information in stages as needed." It enforces the discipline of the context window as a public good through a three-level hierarchy, each loaded at a different moment for a different token cost.
flowchart TD
L1["Level 1: Metadata (name + description) - ~100 tokens/skill - ALWAYS loaded at startup"] --> L2["Level 2: SKILL.md body - under ~5,000 tokens - loaded WHEN triggered"]
L2 --> L3["Level 3+: Bundled files and scripts - effectively unlimited - loaded ONLY as the task needs them"]
L1 -.->|"unused skills stop here, cost only metadata"| SHELF["Rest on disk, zero tokens"]
L2 -.->|"untriggered body stays on disk"| SHELF
L3 -.->|"unread references and scripts stay on disk"| SHELF
Level
When loaded
Token cost
Content
1: Metadata
Always (at startup)
~100 tokens per skill
name + description
2: Instructions
When triggered
Under ~5,000 tokens
The SKILL.md body
3+: Resources
As needed, per task
Effectively unlimited
Bundled files & scripts, read/run via bash
A worked walkthrough: at startup the system prompt carries only the Level 1 line. A user asks, "Extract the text from this PDF and summarize it." (1) Level 1 → trigger: the request mentions PDFs and extraction, so the skill is relevant. (2) Level 2 → load body: Claude reads SKILL.md and finds the "Extracting text" workflow. (3) Level 3 → selective read: the task needs extraction but not forms, so Claude runs scripts/extract.py and never readsFORMS.md — it "remains on the filesystem consuming zero tokens."
The naive alternative is stuffing all organizational context into the system prompt on every request — paying the full cost of all context whether or not the task needs it. Progressive disclosure inverts this: the always-on cost is ~100 tokens per skill, and deep material loads only when a task reaches for it, so the context window stays spent on the request at hand.
[Animation slot: token-cost meter that ticks up only as each level loads — metadata (tiny), body (moderate), one reference file — while unread files stay grayed out at zero.]
Post-Reading Check — Progressive Disclosure
1. Which sequence correctly orders the three loading levels?
2. Why can you install 100+ skills without a meaningful context penalty?
3. A user asks only to extract text from a PDF (no forms). What happens to FORMS.md?
Pre-Reading Check — Bundling Scripts & Choosing Skills over Tools
1. When Claude runs a bundled script, what enters the context window?
2. You keep pasting the same "here's how our team does X" guidance into conversations. Which abstraction does that signal?
3. When a skill body references an MCP tool, what convention prevents Claude from failing to locate it?
4. Bundling Scripts and Choosing Skills over Tools
Key Points
A bundled script is a helper program Claude runs via bash; its code never enters context — only its output does.
Ship scripts for deterministic work: it is more reliable, saves tokens, saves time, and ensures consistency ("sorting a list via token generation is far more expensive than running a sorting algorithm").
Good scripts follow Anthropic's rules: solve, don't punt; no undocumented "voodoo constants"; and make execute-vs-read intent explicit ("Run validate.py" not "See validate.py").
The plan-validate-execute pattern catches errors before any destructive write.
Reach for a Skill to capture how, a tool for a single action, and MCP for access — and compose all three, referencing MCP tools by fully qualified ServerName:tool_name.
Level 3 can hold executable scripts, not just reference docs. The mechanic that makes this powerful is that the script's code never loads into context — only its output consumes tokens. Some work (sorting, validating a schema, computing a checksum, transforming a file) is deterministic and better handled by code than by a language model generating each step token by token. Anthropic lists four benefits even when Claude could generate the code: more reliable, saves tokens, saves time, ensures consistency.
A well-authored validation script embodies three rules: it solves rather than punts (catching FileNotFoundError / JSONDecodeError with actionable messages), documents its constants (MAX_FIELDS = 200 with a reason, not a magic number), and is invoked with explicit intent ("Run validate.py"). It also illustrates the plan-validate-execute pattern: Claude writes intended changes to changes.json, a validator checks the plan with specific errors, and only then does Claude execute — errors caught before any destructive write.
Skills rarely work alone: MCP provides access, Skills provide procedures, tools enable actions. A skill in the middle knows which MCP tool to call (by fully qualified ServerName:tool_name), how to interpret the result, and when to hand off to a deterministic script.
flowchart LR
REQ["Request: analyze last quarter's sales"] --> MCP["MCP server: BigQuery:bigquery_query pulls the data"]
MCP --> SKILL["Skill: competitive-analysis supplies the methodology"]
SKILL --> SCRIPT["Bundled script: scripts/qoq.py computes deltas deterministically"]
SCRIPT --> TOOL["Tool: write_file saves the formatted report"]
The decision comes down to what kind of thing you are adding. A tool adds a capability Claude lacks; a skill adds knowledge Claude lacks (it can already write SQL, but doesn't know your team always filters by date range first).
flowchart TD
Q1{"Can Claude even reach the data or system?"} -->|"No"| MCP["Use an MCP server (connectivity)"]
Q1 -->|"Yes"| Q2{"Is this one concrete atomic action?"}
Q2 -->|"Yes"| TOOL["Use a Tool (single capability)"]
Q2 -->|"No"| Q3{"Are you capturing HOW to do a repeatable procedure?"}
Q3 -->|"Yes"| SKILL["Use a Skill (procedural knowledge)"]
Q3 -->|"Needs deterministic compute"| SCRIPT["Use a Skill with a bundled script"]
Q2 -->|"Needs runtime state across a session"| MCP
Because a skill is a folder, distribution is ordinary file distribution — commit to Git, share the directory, publish to a repository — and the Skills API supports versioning. That same power is a security consideration: a skill can direct Claude to run code and invoke tools, so use skills only from trusted sources. A description that says "extracts text from PDFs" is no guarantee about what the bundled scripts actually do; treat installing a third-party skill like running any third-party code.
[Animation slot: the four hybrid layers (MCP → Skill → script → tool) lighting up in sequence for one request, with a token counter showing the script step adding only its output.]
Post-Reading Check — Bundling Scripts & Choosing Skills over Tools
1. When Claude runs a bundled script, what enters the context window?
2. You keep pasting the same "here's how our team does X" guidance into conversations. Which abstraction does that signal?
3. When a skill body references an MCP tool, what convention prevents Claude from failing to locate it?