Claude Code Skills: Why a Growing Library Gets Harder to Pick From

A 5-skill library already has 2 confusable pairs. At 100 skills, that's 990.

Claude Code Skills: Why a Growing Library Gets Harder to Pick From

You already know the moves. Write a procedure down as a skill instead of re-deriving it every time. Build one meta-skill - a skill whose only job is writing other skills - that interviews you the moment you solve something hard and generates the next skill for you, so the library grows without thirty afternoons of manual writing. And trust progressive disclosure to keep the whole thing cheap: only the name and a one-line description sit in context all the time, the full procedure loads when a skill actually fires.

That third piece is why nobody worries about library size. Add a skill, the index grows by one line. Add the thirty-first, the thirty-second, doesn’t matter - the always-on cost is flat per skill, forever. That reassurance is correct as far as it goes. It just doesn’t go as far as choosing correctly does.

Here’s what that reassurance quietly skips. Cheap to hold in context is not the same claim as easy to pick correctly. A library that looks equally disciplined at 5 skills and at 100 skills is not equally easy to choose from at those two sizes, and the gap between “looks fine” and “is fine” grows faster than the library does. Grow a skill library 20x - 5 skills to 100 - and its index cost grows 20x right along with it, exactly as advertised. The number of skill pairs whose triggers could be confused for each other grows 495x over that same jump. Token cost and confusion cost are not the same curve, and progressive disclosure only ever promised to flatten the first one.

Check whether your library already has this

Section titled “Check whether your library already has this”

Pull up your skills directory - .claude/skills/, or wherever your team keeps it. List every description line, side by side, no bodies. Now ask, for each pair you can see doing similar-sounding work: could one real prompt from a real user plausibly fire either one? Judge each pair against a prompt that carries none of your own intent behind it - just the words a tired teammate would actually type.

Under five skills, or every description reads as obviously distinct even side by side: close the tab. You don’t have this yet. The arithmetic below is real, but at that size it’s a rounding error, not a risk.

Five or more skills, and you can already name a pair that gave you pause: keep reading. The rest of this post puts a number on exactly how fast that pause turns into a real cost, and why it keeps getting worse even as your team gets more disciplined about writing descriptions.

The gap progressive disclosure never promised to close

Section titled “The gap progressive disclosure never promised to close”

Anthropic’s engineering post on the format, Equipping agents for the real world with Agent Skills (2025-10), establishes the mechanism: a skill’s metadata - its name and description - is always loaded into the system prompt, while the body loads only when the skill fires. Their skills documentation puts the number on it: metadata costs about 100 tokens per skill, every time, no matter the library size, and their authoring guidance keeps the body under 500 lines. That’s the whole progressive-disclosure pitch in one fact. A library of 5 skills costs 500 tokens to hold in the index. A library of 100 costs 10,000. Twenty times the library, twenty times the index. Flat, linear, exactly as promised.

But “always loaded” and “correctly chosen from” are different claims about the same 100 tokens. The description is cheap, and it’s also the only signal the agent gets at the moment it decides which skill to reach for - every other qualifying detail a human author put in the body, the steps, the tripwires, sits invisible until after the pick is already made. So the question a growing library actually raises has nothing to do with affording more descriptions. It’s whether any two of those descriptions, read side by side with no body to fall back on, could plausibly describe the same incoming request. That question has nothing to do with token cost, and everything to do with how many pairs of skills exist - a different kind of arithmetic than a per-skill count, and one the 100-token figure never touches.

A library’s cost to hold is linear in the number of skills. Its cost to choose from correctly is a question about pairs, and pairs is a different shape of number entirely.

The toy: five skills, ten pairs, two collisions

Section titled “The toy: five skills, ten pairs, two collisions”

Take a real-looking small library - one platform team’s, five skills, real trigger descriptions:

SkillDescription
hunt-flaky-testA test passes locally but fails in CI, or fails intermittently with no code change.
cut-releaseCutting a new version: tagging, changelog, publish.
security-reviewReviewing a diff or PR against our security rules before merge.
triage-incidentProd is down or degraded; need the diagnostic order and rollback steps.
rotate-secretsA credential or API key leaked or is expiring and needs rotation.

Five skills. List every unordered pair of them and you get ten: hunt-flaky-test/cut-release, hunt-flaky-test/security-review, and so on through all five names taken two at a time. Ten is small enough to check by hand, so do it the obvious way: read each pair of descriptions and ask whether one real prompt could plausibly fire either.

Eight of the ten pairs are clearly distinct - nobody confuses “rotate a leaked credential” with “review this diff.” But two aren’t. hunt-flaky-test and triage-incident both lean on “intermittent” failure language; a prompt like “tests are randomly red in CI, is this an incident?” reads as either one. And cut-release and rotate-secrets overlap in practice, not just in wording: rotating a leaked key commonly ships as a step inside a release, so “rotate the key and cut a release” plausibly triggers either description first.

Exactness stamp: this is a plain-English judgment made against the actual text of the five descriptions above, not a model’s guess and not an estimate. Anyone can re-run it in under a minute - read the same ten pairs, ask the same question, get the same two answers.

Remember that number: every later row in this post runs it out to a bigger library, at the same rate, with no new assumption added. 2 of this 5-skill library’s 10 pairs already blur into each other - a 20% pairwise collision rate, from a library that looks fine skill by skill.

There’s a name for what just happened, and it’s the same math behind a fact you’ve probably heard before: put 23 people in a room and there’s better than even odds two of them share a birthday, despite 365 days to pick from. Nobody’s birthday got more likely. There are just more pairs of people than there are people.

Call this the birthday tax: the cost, in confusable pairs, of adding one more skill to a library where every existing skill can now be paired with it. Quality has nothing to do with it - the toy library above has five perfectly reasonable descriptions, written by someone who clearly thought about triggers, and it still produced two collisions. The tax runs purely on the count of pairs among N things, which is N × (N − 1) ÷ 2, a number that grows with the square of N, not with N itself.

That’s the whole mechanism. A 5-skill library has 10 pairs. Double the library to 10 skills and you don’t get 20 pairs, you get 45 - because every one of the 5 new skills can now collide with every one of the 5 old ones, not just with each other. The index cost of that same jump doubles, exactly as expected. The pair count more than quadruples.

Nobody’s description got worse. There are just more pairs, and the tax is charged on pairs, not on skills.

The table that runs the rate out to a hundred skills

Section titled “The table that runs the rate out to a hundred skills”

Hold the 20% rate from the five-skill toy fixed - the same rate the hand check above found, applied at every size, no new assumption - and run it out:

NIndex tokensPairs C(N,2)Expected collisionsAvg confusable partners/skill
5500102.00.80
101,000459.01.80
151,50010521.02.80
17 (anthropics/skills, real)1,70013627.23.20
202,00019038.03.80
303,00043587.05.80
505,0001,225245.09.80
10010,0004,950990.019.80

Read the first and fourth columns as the whole argument. Index tokens climb in a dead straight line - 500, 1,000, 1,500, 2,000, doubling only when the library doubles. Expected collisions climb away from it: 2, 9, 21, 38, 87, 245, 990. By the time the library hits 30 skills - six times the toy’s size - the hand-checked rate predicts 87.0 expected colliding pairs, an exact arithmetic match to the 20% found by hand at 5, not a new number invented for the jump. At 100 skills the index still costs a trivial 10,000 tokens, while the last column climbs to just under 20 confusable partners per skill - meaning a typical skill in that library shares a plausible trigger with roughly one in five of its neighbors.

Anthropic’s own public skills repository is a real anchor, not a hypothetical one: as of this writing it ships 17 top-level skill categories. Run this toy’s rate at that real size and the table’s formula gives 136 pairs and 27.2 expected collisions - a double-digit number, at a library size plenty of teams already have or will hit within a year, and one no amount of staring at any single description would surface.

The index tokens column and the expected-collisions column are not the same curve, and nothing about the first one warns you when the second one has quietly outgrown it.

Tightening the descriptions, and what it costs

Section titled “Tightening the descriptions, and what it costs”

The fix follows straight from the toy: go back to the two colliding pairs and narrow what makes them collide. Take hunt-flaky-test and triage-incident, before and after:

# before - the pair the toy flagged as ambiguous
hunt-flaky-test: "A test passes locally but fails in CI, or fails
intermittently with no code change."
triage-incident: "Prod is down or degraded; need the diagnostic
order and rollback steps."
# after - an explicit anti-trigger added to each side
hunt-flaky-test: "A test passes locally but fails in CI, or fails
intermittently with no code change. Do NOT use
for a live production incident - that's
triage-incident."
triage-incident: "Prod is down or degraded and needs the diagnostic
order and rollback steps. Do NOT use for a
single failing test with no production impact -
that's hunt-flaky-test."

An anti-trigger is the explicit “do NOT use for X” clause a description adds to name a neighbor’s territory and rule itself out of it. Read the revised pair side by side and the collision the hand check found is gone; the prompt that used to plausibly match either one now has exactly one reading. cut-release and rotate-secrets take the same treatment: cut-release adds “does NOT include rotating credentials, even during a release,” rotate-secrets adds “does NOT include the rest of the release process.” One line added per skill, four lines total, and the toy’s 10-pair, 2-collision library becomes a 10-pair, 0-collision one.

This is also where the meta-skill from the opening earns its keep, and it is worth being plain about where it comes from: Anthropic ships one themselves (skill-creator, in their public anthropics/skills repo), community-maintained skill-writing skills are common, and this piece claims the lineage rather than the invention. What they all share is an interview that asks for a trigger and its negative case: what should make an agent reach for this, and just as important, when should it NOT fire. Point that same question at an existing library after the fact, one colliding pair at a time, and the edit stays targeted: a patch to the handful of descriptions the pair check actually flagged, not a rewrite of the whole library. If your problem runs the other way - nobody on the team knows the procedure yet, and the agent has to go find out - that is a different job, and it belongs to Commission the skill, don’t write it.

The fix isn’t a new tool. It’s the same trigger-and-negative-case discipline the meta-skill already asks for, aimed at the pairs the count just told you to check.

The rate is a toy, and it’s supposed to be pessimistic

Section titled “The rate is a toy, and it’s supposed to be pessimistic”

Be honest about what the 20% figure actually is: a rate hand-checked against one invented five-skill library, held flat at every later size in the table above. It is not a measurement of any real team’s library, and a sharp reader should ask the obvious question - wouldn’t the rate fall as a team gets more disciplined about writing descriptions while the library grows, rather than staying fixed?

Yes, and that’s the point of holding it fixed. The 20% is a deliberately pessimistic baseline, chosen to isolate what the combinatorics alone contribute once authoring discipline is held constant. A team that tightens every description as it adds skills can genuinely push the rate down below 20% - a careful team’s real number could easily be 10%, or 5%. What discipline can’t do is push down the exponent. The pair count still grows as N × (N − 1) ÷ 2 no matter how careful anyone is, because that shape comes from counting pairs, not from anyone’s writing quality. A lower rate buys a smaller multiplier on the same climbing curve; at 100 skills, even a 5% rate still predicts 247.5 expected collisions against an index that costs 10,000 flat tokens either way.

It’s also worth naming what tightening trigger descriptions does not cover: the sibling discipline of keeping each skill to exactly one job, so scope creep inside a single skill can’t recreate the same blur from the inside. That is a different lever from the pairwise-collision fix argued here, and this piece doesn’t cover it.

Discipline can shrink the multiplier on the curve. It can’t change the curve’s shape.

The fix fights the platform’s own advice

Section titled “The fix fights the platform’s own advice”

There’s a sharper objection than the one above, and this one doesn’t fully resolve. Anthropic’s own skill-creator guidance warns that Claude has a tendency to under-trigger skills - to not use them when they’d be useful. That failure mode - the agent not reaching for a skill that applies, rather than reaching for two at once - is the one their guidance is written to fight. Their stated fix is to write descriptions that are, in their own words, a little bit “pushy”: broader, more assertive about when a skill applies, so it fires when it should.

That recommendation pulls directly against the fix this piece just argued for. Narrowing a description to kill a birthday-tax collision - adding the anti-trigger, tightening the boundary - is exactly the move that risks pushing a skill back toward under-firing on the legitimate cases it should still catch. This piece doesn’t get to claim both wins. Tightening hunt-flaky-test’s trigger to exclude triage-incident’s territory is a real fix for the collision the toy found; it’s also a real risk that the same skill now under-fires on some flaky-test prompt that used to trigger it correctly. That’s a genuine two-knob problem - narrow enough not to collide, pushy enough not to under-fire - and this piece names it rather than resolves it.

Keep the size of the problem honest too. Most teams will hit “the agent reached for the wrong skill” long before they hit a double-digit collision count from pure combinatorics - from plain under-specification, a vague trigger nobody sharpened, not from the birthday tax. The tax is the failure mode that shows up once the easy 80% is already right: the descriptions are individually reasonable, the library just has more pairs of them than it used to.

Tightening a description to stop a collision is the same move that risks making it under-fire. Nothing in this piece settles which side of that trade a given skill should land on.

Anthropic’s own public skills repository sits at 17 top-level categories today. Run this toy’s rate at that size and the table above already says 27.2 expected colliding pairs - a library this common, today, already carrying a double-digit count of pairs an agent could mix up.

The fix this piece argued for - tighten descriptions, enforce anti-triggers through the meta-skill’s interview - runs straight into the honesty section above: Anthropic’s own guidance says to write descriptions a little pushy, and pushy is the opposite direction from tight. So the reader who takes this post’s fix seriously is left owning a genuine tuning problem with two knobs, not one: narrow enough that two skills stop colliding, pushy enough that neither one quietly stops firing. No single description setting solves that once a library crosses the size where collisions accumulate faster than skills do.

There’s a second kind of fix this piece never walked through, because rewording a description only ever buys back a multiplier, not the shape of the curve: mechanically splitting a library instead of relying on wording alone. Two tools already ship real versions of this today - subagent-scoped skill visibility, where a skills: field preloads only the subset a given subagent can see, and permission.skill rules that gate which skills are even visible to a given agent. Both cut the number of pairs a single agent has to choose among, which is the only lever that changes the exponent itself instead of the rate riding on top of it.

Hold the two curves in your head from here on: the index cost your library pays is linear, the pair count it has to keep distinct is quadratic, and progressive disclosure was built to solve only one of them.


About the numbers. The 20% pairwise collision rate is a toy constant: hand-checked against one invented five-skill library built for this piece, declared as a deliberately pessimistic baseline, and held flat at every later library size in the master table - it is not a measurement of any real team’s skill library. Every other number in the master table (index tokens, pair counts, expected collisions, average confusable partners per skill), plus the hypothetical 5% comparison in the honesty section, is arithmetic that follows directly from that rate plus the combinatorics of choosing 2 items from N, re-derived by an independent script before publishing. Progressive disclosure itself (metadata always in the system prompt, body loaded only on trigger) is documented in Anthropic’s engineering post Equipping agents for the real world with Agent Skills (2025-10), checked 2026-08-16. The ~100-token metadata figure is from Anthropic’s Agent Skills overview, and the under-500-lines body guidance from their skill authoring best practices, both checked 2026-08-16. The finding that Claude tends to under-trigger skills, and the recommendation to make descriptions a little bit “pushy,” come from Anthropic’s own skill-creator skill in the anthropics/skills repository, checked 2026-08-16. The 17-category count for anthropics/skills is a live count of that repository’s top-level skill directories, taken the same day.

The general “write it down once” thesis behind skills at all belongs to write-it-down-once, applied there to the always-loaded rules file instead of an on-demand skill - the birthday tax only exists in the first place because skills are chosen, not injected. For the file format, the metadata/body split, and the per-tool skill-visibility mechanics mentioned above, see Skills; for routing the meta-skill by hand, see Slash commands.