Write, structure, and improve agent skills following best practices. Consult this skill whenever creating a new skill, improving an existing skill's description or body, structuring a SKILL.md file, or deciding how to organize skill content — even for quick fixes like rewriting a description that undertriggers.
Resources
1Install
npx skillscat add kvnwolf/devtools/create-skill Install via the SkillsCat registry.
Creating Agent Skills
A skill is a markdown file that injects specialized instructions into the agent's context. Well-written skills dramatically improve the agent's output for specific tasks; poorly written ones waste tokens or never trigger at all.
Anatomy
skill-name/
├── SKILL.md ← required (the only file the agent loads on trigger)
├── scripts/ ← optional (executable code for deterministic tasks)
├── references/ ← optional (docs loaded into context as needed)
└── assets/ ← optional (templates, icons, fonts used in output)Every skill has a SKILL.md with YAML frontmatter between --- markers. The frontmatter contains metadata; the body contains instructions.
---
name: my-skill
description: What it does and when to trigger it.
---name and description are the two essential fields. For the complete list of frontmatter fields (allowed-tools, context, model, hooks, etc.), see references/frontmatter.md.
Three-Level Loading
Skills load progressively to minimize token cost:
| Level | When Loaded | Budget | Content |
|---|---|---|---|
| Metadata | Always at startup | ~100 tokens per skill | name + description only |
| Body | When skill triggers | < 5k tokens ideal | SKILL.md markdown content |
| Resources | On demand | Unlimited | Files in references/, scripts/, assets/ |
The agent sees all skill descriptions at startup and decides which to load based on the current task. The body only enters context when the skill triggers. Resources load only when the body explicitly tells the agent to read them.
Writing the Description
The description is the single most important part of a skill — it determines whether the agent ever loads the rest. A vague description can drop activation rates to ~20%; a well-crafted one reaches 50-90%.
Rules
- Write in third person (the description is injected into the agent's system prompt; first/second person causes discovery problems).
- Stay under 1024 characters.
- Lead with what the skill does, then list when to consult it.
- Be task-oriented, not user-oriented — say "whenever installing components" rather than "whenever the user asks to install components." This ensures the skill triggers regardless of whether a human or another skill initiated the task.
- Be broad with triggers. The agent uses LLM reasoning for routing (not keyword matching), so natural language works well. Include edge cases and indirect phrasings that might not seem obvious.
Formula
[Capability in third person]. Consult this skill whenever [trigger 1], [trigger 2], [trigger 3], or [edge-case trigger].Bad vs. Good
Bad: "Helps with components" — too vague, won't trigger reliably.
Bad: "This skill should be used when the user wants to install shadcn components" — formulaic, user-dependent.
Good: "Install and customize shadcn/ui components to match project conventions. Consult this skill whenever installing, adding, or customizing shadcn/ui components — whether from a direct request or any task that involves running the shadcn CLI or editing shadcn component files."
Writing the Body
The body is what the agent reads when the skill triggers. Every line costs tokens across potentially millions of invocations, so each one should earn its place.
Core Principles
Only add what the agent doesn't already know. Challenge each paragraph: "Does the agent really need this?" For instance, the agent knows what PDFs are — don't explain that. But the agent doesn't know your project's compound component pattern — explain that.
Use imperative form. Write "Run the migration script" rather than "You should run the migration script" or "The migration script should be run."
Explain WHY, not just WHAT. Instead of rigid directives, give reasoning so the agent can adapt to edge cases:
# Heavy-handed (yellow flag)
NEVER use `--overwrite` when installing components.
# Reasoning-based (preferred)
Skip the `--overwrite` flag — existing components contain project-specific
customizations (compound patterns, import fixes) that would be lost on overwrite.If you find yourself writing MUST, NEVER, or ALWAYS in caps, that's a signal to reframe. Explain the reasoning instead — the agent is smart enough to follow intent when it understands the consequences.
Match freedom to fragility. Not all instructions need the same specificity:
| Freedom | When | Example |
|---|---|---|
| High | Multiple valid approaches, context-dependent | "Choose an appropriate caching strategy" |
| Medium | Preferred pattern exists but variation is acceptable | Pseudocode with parameters |
| Low | Operations are fragile, consistency is critical | Exact scripts, precise configs |
Keep It Under 500 Lines
If SKILL.md approaches 500 lines, move detailed content into references/ files and point the agent to them with clear guidance on when to read each one:
For the complete API reference, see `references/api.md`.
For migration patterns from v1, see `references/migration.md`.Progressive Disclosure
Use references/ and scripts/ directories to keep the main SKILL.md lean while providing depth on demand.
When to Split
- SKILL.md exceeds ~300 lines and contains distinct sections that aren't always needed
- Content spans multiple domains or frameworks (create one reference per domain)
- Advanced features are optional or infrequently used
Rules of Thumb
- Keep references one level deep from SKILL.md (no
references/sub/nested.md). - Add a table of contents to reference files longer than 100 lines.
- For domain-specific content, organize by variant so the agent reads only what's relevant:
cloud-deploy/
├── SKILL.md (workflow + domain selection)
└── references/
├── aws.md
├── gcp.md
└── azure.mdBundled Scripts
Place pre-made scripts in scripts/ for operations that are deterministic, repetitive, or error-prone. Scripts are more reliable than having the agent write them from scratch every time, save tokens, and ensure consistency.
skill-name/
├── SKILL.md
└── scripts/
├── validate.sh
└── generate-config.pyGood candidates for scripts:
- File transformations with precise rules (parsing, formatting, conversion)
- Validation and verification steps
- Setup/scaffolding sequences with many exact commands
- Any operation where the agent tends to reinvent the same helper across invocations
In SKILL.md, tell the agent to execute the script (not read it as reference) and explain what it does so the agent understands the output:
Run the validation script to check the generated output:
`scripts/validate.sh <output-path>`
It returns exit code 0 on success or prints the failing checks to stderr.Handle errors inside the script rather than leaving the agent to figure them out — scripts should solve problems, not punt them. Justify any non-obvious configuration values in comments to avoid "magic constants."
Patterns
These recurring patterns work well across different skill types. See references/examples.md for full before/after demonstrations.
Reference Skills (Domain Knowledge)
For skills that provide conventions, patterns, or style guides without prescribing a specific workflow. Structure with clear sections, tables for quick lookup, and code examples.
## Variable Types
### Client Variables (`VITE_` prefix)
Variables the browser can read. Must have `VITE_` prefix.
### Server Variables (no prefix)
Variables only available on the server.
## Quick Reference
| Task | Action |
|------|--------|
| Access env var | `import { env } from "@/lib/env"` |Task Skills (Step-by-Step Workflows)
For skills that prescribe an exact sequence of operations. Use numbered steps with clear conditionals and provide exact commands or file contents.
## Steps
### 1. Create config file
### 2. Install dependencies
### 3. Run initial setupBefore/After Examples
Show transformations clearly. This pattern helps the agent understand the desired output better than verbose descriptions:
**Example 1:**
Input: Added user authentication with JWT tokens
Output: feat(auth): implement JWT-based authenticationOr for code:
// Before (default)
export { Button, buttonVariants }
// After (project pattern)
export function Button({ className, ...props }: ButtonProps) { ... }Quick Reference Tables
End with a lookup table for common operations:
## Quick Reference
| Task | Pattern |
|------|---------|
| Add render prop | `useRender.ComponentProps<"tagname">` |
| Merge props | `mergeProps<"tagname">({ ...defaults }, props)` |Known Issues and Workarounds
Document gotchas with clear error messages and solutions:
## Known Issue: Custom Data Attributes
**Error:**
`Object literal may only specify known properties...`
**Workaround:**
Use `["data-slot" as string]: "value"` to bypass strict typing.Naming Conventions
- Folder names: kebab-case, no spaces or capitals (
processing-pdfs, notProcessingPDFs) - Skill names: lowercase letters, numbers, hyphens only, max 64 characters
- Avoid reserved words (
anthropic,claude) and XML angle brackets in names - Prefer gerund form for clarity:
installing-components,managing-databases - File must be exactly
SKILL.md—SKILL.MDorskill.mdwon't be discovered
Common Pitfalls
| Pitfall | Why It's a Problem |
|---|---|
| Vague description | ~20% activation rate vs. 50-90% with specific triggers |
| "When to use" only in body | The description is the trigger mechanism; the body loads after triggering |
| First/second person in description | Causes discovery problems when injected into system prompt |
| Deeply nested references | The agent may partially read nested files; keep references one level deep |
| Time-sensitive information | Becomes stale; use "old patterns" sections instead |
| Inconsistent terminology | Pick one term and use it everywhere |
| Over-explaining basics | Wastes tokens — the agent already has general knowledge |
| Hardcoded absolute paths | Use relative paths or {baseDir} references |
| All-caps MUST/NEVER/ALWAYS | Yellow flag — reframe with reasoning instead |
| Too many options without a default | Provide one recommended path with an escape hatch |
Pre-Ship Checklist
Before finalizing a skill, verify:
-
SKILL.mdexists with exact casing - Folder is kebab-case, no spaces
-
nameanddescriptionin YAML frontmatter - Description is third-person, under 1024 chars
- Description covers what it does AND when to trigger
- Body is under 500 lines
- Body uses imperative form
- No unexplained MUST/NEVER/ALWAYS in caps
- Instructions explain WHY, not just WHAT
- Includes concrete examples (before/after, input/output)
- References are one level deep
- Large reference files (>100 lines) have a table of contents
- Bundled scripts handle errors internally (no "voodoo constants")
- Consistent terminology throughout
- No time-sensitive information that will go stale