Short version: A skill's description is the only thing Claude reads before deciding whether to load the rest of it. If the skill never fires, the instructions inside it don't exist. Write the description in third person, say both what it does and when to use it — with the literal words and file types a user would mention — make it slightly pushy, and stay under 1024 characters. Everything else is secondary.

If you're deciding whether a skill is even the right tool versus a subagent or an MCP server, read Skills vs Subagents vs MCP first. This piece assumes you've decided on a skill and it just won't fire.

Why the description is the whole game#

Skills load in stages — Anthropic calls it progressive disclosure. Three levels:

LevelWhen it loadsToken cost
1 — Metadata (name + description)Always, at startup~100 tokens per skill
2 — Instructions (SKILL.md body)Only when the skill triggersUnder ~5k tokens
3 — Resources (other files, scripts)Only when Claude reads themZero until accessed

Read that table again with the failure mode in mind. At startup, Claude sees only Level 1 — every skill's name and description, nothing more. When a request comes in, Claude matches it against those descriptions and, on a match, reads the SKILL.md body off the filesystem with bash. The body does not exist to Claude until the description wins the match.

So the recurring practitioner complaint — "my skill has great instructions and it still doesn't trigger" — is almost always a description problem wearing an instructions costume. You polished Level 2. The decision happens at Level 1.

The anatomy of a description that fires#

A good description packs two halves into one or two sentences, written in third person:

  1. What it does — the capability, concretely.
  2. When to use it — the situations, file types, tool names, and literal phrases a user would say.

Anthropic's canonical example, for a PDF skill:

---
name: pdf-processing
description: >-
  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.
---

The first sentence is the what. The Use when… clause is the when, and it is the load-bearing part. Notice it names the concrete triggers — "PDF files," "forms," "extraction" — the exact tokens a user's request will contain. That string-level overlap is what Claude matches against.

Four ways descriptions fail (and the fix)#

1. Capability-only, no trigger. "Helps with data tasks." There's nothing for a request to match. Add the when: which tasks, which words, which file types.

2. Too timid. "Can optionally assist with PDFs if needed." Hedging language ("optionally," "if needed," "can help") invites Claude to skip it. Claude already has a measured tendency to under-trigger skills — Anthropic's own skill-creator recommends writing descriptions that are a little pushy. State triggers as facts: Use when the user mentions PDFs or forms. Not "can help with."

3. The overstuffed catch-all. "Use for anything involving files, data, code, or documents." This fires on almost every turn, becomes noise, and Claude learns to ignore it — or it collides with every other skill. Specificity is what makes a trigger legible. Name the narrow situation.

4. What without when. "Generates SQL from natural language." States the capability, never says the trigger condition. Add: Use when the user asks to query a database, write SQL, or turn a question into a query.

The limits you can't cross#

These are hard validation rules, not style advice:

That 1024-character ceiling is your entire trigger budget. Spend it on the when, not on adjectives.

Keep the body lean — it's a per-trigger tax#

The SKILL.md body should stay under ~5,000 tokens, because it loads every time the skill fires. This is the same economics as trimming agent tool descriptions: text that rides in context on every turn is a recurring cost, not a one-time one.

The escape hatch is Level 3. Anything long — full API references, worked examples, large templates — goes in a separate file the body points to:

sql-helper/
├── SKILL.md          # lean: when to fire, the core procedure
├── REFERENCE.md      # the full dialect/function reference
└── scripts/
    └── validate.py   # runs via bash; its code never enters context

Claude reads REFERENCE.md only when a task needs it, and runs validate.py for its output without ever loading the script's code. Bundled content costs zero tokens until accessed, so there's no penalty for shipping comprehensive resources — as long as they're not in the body.

Don't guess whether it triggers — test it#

The reliable authoring loop is evaluation-first, not documentation-first:

  1. Write the minimal description and body.
  2. Run the agent on a handful of representative prompts — some that should fire the skill, some that shouldn't.
  3. Watch what actually triggers.
  4. Tighten the description on the misses (add the trigger words it lacked) and the false fires (narrow the scope).
  5. Repeat.

Anthropic ships a skill-creator skill that runs exactly this Draft → Test → Review → Improve loop, and it's the fastest way to converge. In Claude Code you can iterate in place: drop the directory in .claude/skills/<name>/SKILL.md (project, commit it to the repo) or ~/.claude/skills/ (personal), and Claude discovers it automatically — no upload, no restart. Change the description, re-run your test prompts, see the difference immediately.

The one-line takeaway#

If a skill isn't firing, don't touch the instructions. Rewrite the description: third person, what plus a concrete, slightly pushy when, under 1024 characters, with the literal words your users actually type. That single field is the difference between a skill that ships and a skill that sits there.

Next: once your skill fires, the question is whether it should have been a skill at all — Skills vs Subagents vs MCP.