Back to Insights
21 Jun 20264 min readAI & LLMs

Your Skill's Description Is the Whole Ballgame

Agent skills run on progressive disclosure: at the start of a session the model sees only each skill's name and description — not its body. From that one sentence it decides whether your skill is relevant. Only if it bites does the full SKILL.md load into context. Which means two things most people writing skills get wrong:

  1. A vague description is a skill that never fires. You can write the most useful skill in the world; if its description is "Helps with database stuff," the model won't reach for it, because nothing in that sentence tells it when. The skill is dead weight — present in the directory, absent from every session.
  2. A bloated body taxes every session that does use it. When the skill triggers, the whole SKILL.md loads. A 10,000-token skill body is 10,000 tokens you pay on every task that touches its domain.

Both are mechanical and checkable, so we wrote skill-lint.

What it checks

$ skill-lint myskill/
skill-lint — myskill/SKILL.md  (desc 3w · body ~9 tokens)

  ● HIGH  description is only 3 words — too thin to trigger reliably
          say what it does AND when to use it (the exact tasks/keywords that should invoke it).
  ● INFO  description states what it does but not WHEN to use it
          add a 'use when…' / 'trigger when…' clause so the model knows to reach for it.
  ● INFO  `name` (helper) doesn't match the directory (myskill)

The description, as a trigger. The model matches on it, so skill-lint measures it as one: a description under ~10 words is flagged HIGH (it can't carry both what and when); under ~20 is a WARN; and a description that says what the skill does but never says when to use it gets an INFO nudge to add a "use when…" clause. The skills that fire reliably are the ones whose description spells out the trigger — the file patterns, the user phrasings, the exact tasks. Look at a well-built skill and the description reads like a routing rule, because that's what it is.

The body, as a recurring cost. skill-lint reports the body's token size and flags it past ~5,000, with the fix the docs recommend: keep SKILL.md a lean overview and push the detail into referenced files that load only when needed. That's progressive disclosure applied one level down — the skill itself shouldn't dump everything into context the moment it's chosen.

Stale bundled references. Skills ship helper files (scripts/…, references/…), and SKILL.md points at them. When one moves or is deleted, the pointer rots and the skill sends the model after a file that isn't there. skill-lint checks the bundled-path references against the skill directory.

  ● WARN  1 referenced file(s) not found in the skill
          fix or remove: `scripts/run.sh`

A note on getting this right, because it's the kind of check that's easy to do badly: a naive version flagged every backtick that looked file-ish — including code identifiers like Anthropic.Tool and example filenames like app.py mentioned in prose. Those aren't bundled files, and nagging about them makes the tool noise. The fix is to only treat a reference as a file when it's a path (it has a slash) or an explicit markdown link — and a test pins exactly that, so a real, well-documented skill comes back clean instead of drowning in false positives.

Using it

skill-lint                      # ./SKILL.md
skill-lint path/to/skill/       # pass the dir; it finds SKILL.md
skill-lint ~/.claude/skills/*/  # audit a whole library

It exits non-zero on findings, so it slots into CI for a skills repo. Run it across your skills directory and you'll usually find the same two things: a couple of skills with descriptions too thin to ever trigger, and one that grew a 12,000-token body nobody noticed was loading on every related task.

The honest limits

It checks shape, not quality. It can tell you a description is 4 words and has no trigger clause; it can't tell you a 40-word one is actually a good router — that the keywords match how people really ask. "Has a trigger cue" is a heuristic for "is discoverable," not a guarantee. And body size is a proxy for cost, not a verdict on whether the content earns it. Treat skill-lint as the smoke detector for the failure modes that are mechanical — undiscoverable, over-heavy, pointing at missing files — and keep writing the description like the routing decision it is.

The real lesson

A skill isn't code that runs when called; it's a candidate the model chooses from a one-line pitch. So the highest-leverage thing in the whole file is the description — and the most common failure isn't a bug in the skill, it's a skill that's invisible because its pitch never said when to use it. Write the description as a trigger, keep the body lean enough that loading it isn't a tax, and let a linter catch the day either one drifts.

We build and run agent skills and fleets on Claude Code in production. If you're building a skills library, talk to us.


Get the tool → skill-lint in agent-ops — open source (MIT), a single dependency-free script, part of our toolkit for running coding agents in production.

AI agentsskillsClaude Codediscoverability

Found this useful?