Part 5 of the "Automating Playwright with Claude Code" series. In Part 4, we built a single playwright-form-tester Skill. This post explains the mechanism that lets you install dozens more like it without bloating every session — and shows how to structure a Skill to actually take advantage of it.
If you've ever wondered "wait, if I install 10 Skills, does Claude load all 10 into context on every single request?" — the answer is no, and the reason why is one of the more elegant parts of how Claude Code Skills are designed: progressive disclosure. Understanding it changes how you write Skills, not just how many you install.
Why Progressive Disclosure Matters
- Skill libraries scale for free. You can install 30+ Skills covering your entire test lifecycle without paying a token tax for the ones you're not using right now.
- It changes how you should write Skills. Once you know only the frontmatter is always loaded, you write leaner descriptions and push heavy detail into files Claude only opens on demand.
- It explains Skill-fires-or-doesn't behavior. If a Skill never triggers, or triggers when it shouldn't, the fix is almost always in this loading model — usually the description.
-
It's the difference between a Skill and a bloated
CLAUDE.md. ACLAUDE.mdfile is always fully in context. A Skill isn't — and that's the entire point.Prerequisites
Completed Part 4 of this series, with the
playwright-form-testerSkill installed.-
Comfortable editing a
SKILL.mdfile and creating subfolders alongside it.Table of Contents
- The Three Layers of a Skill
- Step 1: What's Always in Context (Layer 1)
- Step 2: What Loads on Match (Layer 2)
- Step 3: What Loads Only on Demand (Layer 3)
- Step-by-Step: Refactoring Our Form-Tester Skill
- Why the Description Field Is the Most Important Line You'll Write
- Conclusion
The Three Layers of a Skill
Every installed Skill loads in three stages, only as needed:
| Layer | What's in it | When it loads |
|---|---|---|
| 1. Frontmatter |
name + description (~100 tokens) |
Always, for every Skill, at session start |
| 2. Body | The full SKILL.md instructions |
Only when your request matches the description |
| 3. Files |
references/, scripts/, assets/
|
Only when a step in the body actually calls for that specific file |
This is why installing 30 Skills doesn't mean paying for 30 Skills' worth of context on every request — you're only ever paying for Layer 1 across the board, plus Layers 2 and 3 for the one or two Skills that actually apply to what you asked.
Step 1: What's Always in Context (Layer 1)
At the start of every Claude Code session, only this much of each installed Skill gets loaded:
---
name: playwright-form-tester
description: Test HTML forms using Playwright CLI. Use this whenever the user
asks to test, validate, or verify a form (login, signup, checkout, contact,
etc.) on a web page, or mentions form submission, validation errors, or
success messages.
---
- That's it — no workflow steps, no code blocks, nothing else.
- Multiply this by however many Skills you have installed, and you can see why 30 Skills costs roughly 30 × ~100 tokens, not 30 × (full SKILL.md length).
Step 2: What Loads on Match (Layer 2)
The moment you say something like "test the checkout form", Claude matches it against the description field above, and only then pulls in the full body:
## Process
1. Navigate to the target page with `playwright-cli navigate <url>`.
2. Run `playwright-cli snapshot` to get element references (e.g. `e12`).
3. Fill each field with `playwright-cli fill <ref> "<value>"`.
...
- Every other installed Skill that didn't match stays at Layer 1 — its body is never loaded for this request.
- This is the point where your Skill starts costing real tokens, but only for the one request where it's relevant.
Step 3: What Loads Only on Demand (Layer 3)
This is the layer most people don't take advantage of, and it's the one that matters most once a Skill grows complex. If a step in your body references a file — a script, a longer reference doc, a template — that file is only opened if that specific step actually runs.
.claude/skills/playwright-form-tester/
├── SKILL.md
├── scripts/
│ └── check-known-selectors.sh
└── references/
└── negative-test-checklist.md
- A script's execution output is what enters context — not its source code. Claude runs
check-known-selectors.shand only sees the result, not the whole script. -
references/negative-test-checklist.mdonly gets read if the workflow step says "consult the negative test checklist" — otherwise it sits on disk, costing nothing.
Step-by-Step: Refactoring Our Form-Tester Skill
Let's apply this to the Skill from Part 4. Right now, our negative-testing guidance is baked directly into the body:
## Notes
- Always test one valid case and at least one invalid case per form.
- If the form has a CAPTCHA or OTP step, stop and ask the user how to
proceed rather than guessing.
That's short enough to leave inline — but imagine it grew into a 40-line checklist covering SQL injection payloads, Unicode edge cases, and field-length boundaries. At that size, it belongs in a reference file instead:
- Create the file:
mkdir -p .claude/skills/playwright-form-tester/references
- Move the detailed checklist into
references/negative-test-checklist.md. - Point to it from the body instead of inlining it:
## Notes
- Always test one valid case and at least one invalid case per form.
- For a full negative-test checklist (injection payloads, boundary
values, Unicode edge cases), consult
`references/negative-test-checklist.md`.
Now that checklist only enters context on the requests where Claude actually needs it — not on every single form test.
Why the Description Field Is the Most Important Line You'll Write
If a Skill isn't firing when you expect it to, the description is almost always the reason — because it's the only thing Claude has to go on before deciding to load the rest.
# Too vague — likely won't fire reliably
description: Helps with testing.
# Specific, with real trigger phrases
description: Test HTML forms using Playwright CLI. Use this whenever the user
asks to test, validate, or verify a form (login, signup, checkout, contact,
etc.) on a web page, or mentions form submission, validation errors, or
success messages.
- Include the actual words a tester would type — "test the login form," "validate this signup flow" — not just an abstract summary.
- If you have several similar Skills, make sure their descriptions don't overlap so much that Claude can't tell them apart.
Conclusion
Progressive disclosure is why Skills scale where a giant CLAUDE.md file doesn't — you get the benefit of a large, well-organized library while only ever paying for the small slice that's relevant to what you're doing right now. In the next post, we'll use this exact structure to grow our single form-tester Skill into a small pack covering page objects, flaky-test debugging, and locator strategy — much like the framework packs the wider QA-skills ecosystem has started building.
Have you restructured a Skill to use references/ or scripts/ yet? Let me know how it went in the comments!
Top comments (0)