Direct answer
A well-designed skill is invoked at the right moment, does its job, and returns control, while a poorly designed one is a nuisance, ignored when needed or activated unnecessarily, causing confusion in the model's behavior, hindering output quality and context window erosion due to excessive token consumption.
A well-designed skill is invisible: it's invoked at the right moment, does its job, and returns control. A poorly designed skill is a nuisance: it's ignored when needed, activated when not needed, or worse, activates behavior that confuses the model. In this article, I'll recount what worked on my brownfield portfolio, which skills I had to rewrite from scratch because they were ignored, and three practical rules that will help you get past Skill that you wrote al Skill that the model really uses.
Independence Disclaimer: I am not affiliated with Obra nor Anthropic. What follows is personal experience on sixty-plus years of skill (some official Superpowers, others custom) installed in my
.claude/skills/ About a year.
The Rule of Three when
Before writing a single line of SKILL.md, answer three questions. This is the rule I stole from a conversation with the skill "using-superpowers" of obra and have applied to all my custom skills. The three questions are: 1. Prima di scrivere una sola riga di SKILL.md, rispondi a tre domande. 2. Sono la regola che ho rubato a una conversazione con la skill "using-superpowers" 3. di obra e che ho riapplicato a tutte le mie skill custom. 4. Le tre domande 5. sono:
- When The problem that the skill solves appears? (the situation that it activates)
- What Does he need to do a skill, in concrete terms? (the behavior that imposes it)
- I'm ready to translate. Please provide the Italian text. Does the skill know it has finished? (closure criterion)
The first when ends up in description of the front matter.
The nothing and like body of the SKILL.md file. All three
must be Specifics for the domainVagueness in one of these three = skill that doesn't work.
Negative example (skill that the model ignores)
---
name: code-helper
description: Use when coding to write better code
---
You are a helpful coding assistant. Write clean code.
What's wrong with it? Everything, but especially: Note: I've kept the original formatting, punctuation, and capitalization style. Let me know if you need any further assistance!
- When we are weakUse when coding, Matcha is practically always, so the model does not have a precise trigger to activate it.
- General thingWrite better code does not describe a behavior, it describes an intention.
- Nothing likeThere is no closure criteria. When does the skill end? Never? Always?
Result on my portfolio: skills similar to this one that I had written in the first months were invoked There is no Italian text to translate. You provided a blank slate for me to work with. Please provide the Italian text you would like me to translate, and I will be happy to assist you., worsening the output instead of improving it. After three weeks I have disabled them.
Positive example (skill invoked by the model)
---
name: debugging
description: Use when investigating a bug that did not resolve on first attempt.
Drives a scientific-method loop (hypothesis -> test -> measure) with
checkpoints between cycles, and stops when the failing test turns green.
metadata:
type: rigid
---
What's right?
- When specifiedUse when investigating a bug that did not resolve on the first attempt. It does not activate on the initial try; it activates when the trivial fix has not worked.
- Concrete thingThe scientific method involves a loop with checkpoints. It's not about being a good debugger but rather precise procedural behavior.
- As definedThe criteria for closure is an observable condition.
This is a skill debugging About Superpowers (summary). It works.
If you're looking for it in upstream and study the body, you'll see that the 200-300 lines of the file expand to nothing e like steps, while
when stay condensed in the description.
Frontmatter surgical: name + description, nothing more
The front matter of the SKILL.md file I've read is impressive for How little it contains. Often just two fields:
---
name: code-reviewer
description: Use after writing or modifying code to review for quality,
security, and maintainability. Focuses on what was just changed (not the
entire codebase). Stops with a structured report flagging CRITICAL,
HIGH, MEDIUM issues.
---
Optional fields that you sometimes see:
metadata.type=rigid|flexibleReport if the skill should be followed exactly or if it is adaptable to context. Default flexible.metadata.bypass=auto|promptCheck if the skill is invoked automatically or asks for user confirmation. Default auto.
Adding unknown fields from Claude Code's runtime does not break the skill, but rather becomes informative noise. Resist the temptation to put excessive metadata in the front matter (version, author, tags, tested_on) - those information live better in the README of the skill package, not in the SKILL.md file which is parsed every session.
The description is written for the model, not for you
The description is the most important thing of the skill. The model reads it Every time What are the chances of invoking a skill? Three practical rules
- Verb + Specific Noun. Use when investigating a bug (verb + noun) beats "Use when something is wrong" (verb + abstract noun). Typical verbs: investigate, refactor, review, validate, summarize, brainstorm. Specific nouns: bug, dead code, pull request, configuration drift, query, prompt.
- Condition that restricts. Use after writing or modifying code restricts to the moments post-write, always beats "Use when coding", restrictive condition avoids noise.
- Observable output. "Stops with a structured report flagging CRITICAL, HIGH, MEDIUM issues" tells the model what the skill is. It helps the model decide if the skill is what it needs.
Progressive disclosure body
The body of the SKILL.md file is loaded alone when The skill is invoked. This is crucial: it means you can write long instructions (300-500 lines) without worrying about token consumption in the "base case" (skill not invoked). However, once invoked, the instructions go into context, and how many go into context count.
Progressive disclosure pattern:
SKILL.md (~150-250 righe)
├── Overview + when to invoke (riassunto del description)
├── Core procedure (steps high-level)
├── Anti-patterns (cosa non fare)
└── References to subdir lazy-load:
references/
├── advanced-workflows.md (load only if step X requires)
├── edge-cases.md (load only if user reports edge case)
└── examples-checklist.md (load only on user request)
The main body contains the happy-path flow. When the current task needs it (e.g., the user requests an advanced workflow not covered by the base flow), the main body instructs the model to read the specific file under references/Savings: the first step of an invocation
typical remains under 250 lines; only unusual cases pull in references.
Body monolith of 800 lines
A custom skill I had written in the first months of my portfolio had 800 lines in the main body. It contained:
- Overview (50 lines)
- Happy path (200 lines)
- Alternative workflows (300 lines in total)
- Fifteen examples (200 lines)
- Final checklist (50 lines)
Problem: every time the skill was invoked, all this would enter into context. For an invoked skill, every third or fourth message, the cumulative overhead would erode the context window.
Solution applied: split into main body (200 lines of happy path) + six references/workflow-N.md Lazy loading + a single
references/examples.md Loaded only on explicit request.
Token consumption per invocation typical: -65%.
Reference subdirectory: when, where, how
The folder references/ Next to SKILL.md is the official mechanism
for extending a skill without inflating the main body.
Three principles:
-
One file per concept. Don't have a single file called "miscellaneous.md" with ten sections. It's better to have separate files, each with a name that describes its content:
code-review-checklist.md,security-anti-patterns.md,performance-edge-cases.md. -
Link is explicitly in the body. Don't expect that the model will find the references on its own. Write in the main body:
If the task requires XPHX0XPHX, read
references/x.mdbefore proceeding"Without an explicit link, the references remain dormant. - References are read-only for the model. I am documentation, not code. Nothing like "execute this command" that changes the state. The state is changed by the main body or the user.
Naming convention that avoids collisions
The name of the skills folder becomes the name of the SKILL.md file path.claude/skills/<name>/SKILL.mdPractical convention:
- I don't see any Italian text provided. Please share the text you'd like me to translate, and I'll be happy to assist you.:
code-reviewer,tdd-guide,debug-flow. - verb or descriptive noun:
debugging(noun),refactor-cleanerI'm ready to translate. Please provide the Italian text you'd like me to translate. - Avoid fixed pluginsDon't call your custom skill by that name
superpowers-debuggingCalling hermy-debuggingodebug-domain-x. - Avoid versioning in the name:
tdd-guide-v2Don't use a version control system like Git to manage your code; instead, use its history through file names.
Plugin skill vs. custom skill: coexistence
When you installed Superpowers (or another plugin by Claude Code that provides skills), the upstream skills lived in a separate plugin folder. Your custom skills remained in .claude/skills/The runtime indexes
all Skill.md files regardless of their origin.
Potential Collision Two skills with the same nameThe runtime complains with a warning (and typically loads only one of the two, with uncertain behavior). Solution: rename your custom skill to avoid collisions.
Mild case: Two skills with a similar descriptionNo runtime warning, but the model chooses among them in a non-deterministic way. Solution: differentiate the description so that each covers a separate disjoint situation. Example of disambiguationA skill code-reviewer of Superpowers (review post-write generic) + a skill code-reviewer-fintech Custom review post-write with a focus on PSD2 regulation. Description differentiated between when it is activated and what it specifically seeks.
Measuring whether the skill is truly invoked
There is a brutal but effective way to find out if your skills are actually being used: Eliminate temporarily those that you suspect are useless and observe.If no subsequent session shows a decline in output, the skill was noise and you can disable it.
On my portfolio, I've done this exercise three times (every four-five months). Cumulative result: I have disabled 9 custom skills out of 23 because they didn't contribute. The remaining 14 are the ones that actually work.
Pre-commit checklist for a new skill
- Respond to the three questions (when/what/how).
- Description = verb + specific noun + restrictive condition + observable output (max 2-3 lines).
- Progressive disclosure body: happy path 150-250 lines, references separate by workflow advanced.
- Warning section explicit: what the skill MUST NOT do.
- Mental test: would a typical session of your domain activate this skill at the right moment?
- Real test: in the first two weeks, check if it's invoked. If not, reformulate the description.
When a skill is not the right solution
Design skill is a tool, not an end. Sometimes the correct answer is XPHX0XPHX do not write a skillThree situations: . XPHX0XPHX Tre situazioni: . XPHX1XPHX
- Desired behavior is already in the model. If Claude responds correctly to the typical task without skill, adding a skill is overhead. The skills serve for Forcing an unconventional behavior (e.g. TDD on business logic, code review after writing).
-
Desired behavior is a specific user preference.
If the rule applies only to your personal workflow (e.g. "commit message in Italian"), go to
CLAUDE.mdDue to project requirements, not a global skill. - Desired behavior is a real tool. If you need an action on an external system (querying the database, calling the API), a MCP server is better than a skill. Skills train the model, while MCPs give them tools.
A custom skill in the portfolio: i18n-bulk-translator
Real example of a custom skill I wrote for my portfolio (here illustrated, not production-ready copy-paste):
---
name: i18n-bulk-translator
description: Use when translating a new batch of i18n keys across 17
target languages via the on-prem Ollama qwen2.5:14b pipeline. Drives
the xlf.py + auto-translate-new-keys.py workflow with checkpoint
between languages, and stops when all targets reach >= 95% coverage
per the audit script.
metadata:
type: rigid
---
# i18n-bulk-translator
## When to invoke
[descrizione del trigger specifico]
## Procedure
1. Run `scripts/i18n/xlf.py extract` to gather new IT source keys.
2. For each target language (17 total), spawn translation batch...
[5-6 steps high-level]
## Anti-patterns
- Do NOT batch all 17 languages in one call (timeout).
- Do NOT skip audit step between batches.
## References
- references/language-priority.md (order in cui tradurre).
- references/audit-thresholds.md (soglie per quality gate).
- references/edge-cases.md (placeholder gestione, route slug).
Practical results: before this skill, every batch of translation was a five-seven message prompt re-engineering. After that, it's a single message "translate the new batch" and the skill takes control.
What I learned writing this article
The Rule of Three when It seems obvious to read and write, but in the first six months of custom skill development I had never put it on paper black and white. I had "intuitions" about when a skill would work and when not, but didn't know how to articulate them. Writing this cluster forced me to translate my intuition into three operational questions.
The second lesson is about noise. The initial adoption phase of Superpowers (and general custom skills) tends to over-installation: install thirty skills because "they might be needed". Thirty months later, most were never used effectively, and those that were used did so with mutual annoyance (description overlap). Less is more applies strongly to skill design.
Avoided pattern
- Skill as a reference manual. The skills are not documentation: they are operational instructions. If you want to write "background context" or "history of this skill" in the body, move everything to references/ and only link it when the model needs it.
-
Skill that combines two responsibilities. A skill
"debug-and-test" that makes both bug investigation and TDD enforcement is
an incorrect abstraction. Two separate skills (
debugging+tdd-guideThey work better with separate descriptions because the model can activate either one or the other based on context.
A story worth sharing
Placeholder Section If you have experimented with a skill pattern that works (or an anti-pattern that you paid dearly for), and want it to become part of the next article in the series,
Write to me federico@federicocalo.devWith your explicit consent (and pseudonymization) the history enters the next cluster as a reader story.
Sub-page Superpowers ← Next cluster: Brainstorming skills →
Related deep dive: Claude Code Workflow: Superpowers + Get Shit Done - la guida pratica.
Frequently asked questions
What are the three questions that should be answered before writing a single line of SKILL.md?
The three questions are: 1. What is the purpose of this skill? 2. How will it be invoked by the model? 3. What specific information does it need to accomplish its task?
Why is it important for the description in the front matter of the SKILL.md file to be written for the model, not for the user?
The description should be written for the model because it will read it every time the skill is invoked, and a clear understanding of the skill's purpose is crucial for its proper functioning.
What is the progressive disclosure pattern in the body of the SKILL.md file, and why is it beneficial?
The progressive disclosure pattern involves loading only the necessary instructions when the skill is invoked, allowing long instructions to be written without worrying about token consumption. This approach helps to prevent unnecessary context window erosion.
How can you determine if a custom skill is truly being used by the model?
You can temporarily eliminate suspected useless skills and observe subsequent sessions for any decline in output; if no decline occurs, the skill was likely noise and can be disabled.
Commenti
Caricamento commenti...
Sign in to comment