You wrote a skill. The description is clear. You ask for exactly the thing it does, and Claude reaches for something else.
Before you rewrite the description a fourth time, check whether Claude ever saw the whole thing. Two separate limits trim skill metadata before the model reads it, and both are silent.
The two limits are not the same limit
Claude Code loads a listing of your skills — names plus descriptions — into context at the start of a turn. That listing is how Claude knows what exists. Two independent caps apply to it:
-
A per-entry cap. Each skill's combined
description+when_to_usetext is capped at 1,536 characters. Past that, the tail is cut. This applies regardless of how much room the listing has left. - A shared listing budget. All entries together get a slice of the context window — 1% of it, with a documented fallback of 8,000 characters. When the listing overflows that slice, Claude Code starts dropping descriptions, beginning with the skills you invoke least. Your most-used skills keep their full text; the long tail turns into bare names.
The failure modes look different. Hit the per-entry cap and one skill loses the end of its trigger guidance — often the part listing the edge cases you care about. Hit the shared budget with 30 skills installed and an entire skill becomes a name with no description, which means Claude has nothing to match your request against.
See it instead of guessing
Two commands report on this directly.
/doctor gives an estimate of the skill listing's context cost and names its biggest contributors. That is the fastest way to find out that one verbose skill is eating the budget everything else needs.
/context has a Skills row that reports the listing size after the budget is applied — so it matches what the model actually receives, not what you wrote. (Before v2.1.196 that row counted the full text of every description and could read several times larger than the configured budget, so if you remember this number being useless, it isn't anymore.)
There is also a warning written to the debug log when the listing exceeds its budget. Run with --debug if you want it in the terminal.
Turning the knobs
If the diagnostics say you're budget-constrained, you have three moves, in rough order of how much I'd reach for them:
Trim at the source. Put the key use case in the first sentence. Descriptions get cut from the end, so the ordering of your own text decides what survives. This is free and it makes the matching better anyway — a description that opens with "Diagnose a slow SQL query" matches more reliably than one that opens with three sentences of preamble.
Demote the skills you rarely invoke. The skillOverrides setting takes a per-skill value of on, name-only, user-invocable-only, or off. Setting a low-priority skill to name-only lists it without a description, freeing that budget for skills that need to be matched automatically. A skill absent from skillOverrides is treated as on.
{
"skillOverrides": {
"legacy-context": "name-only",
"deploy": "off"
}
}
Enter fullscreen mode Exit fullscreen mode
Raise the budget. skillListingBudgetFraction sets the fraction of the context window reserved for the listing — 0.02 for 2%, default 0.01. The SLASH_COMMAND_TOOL_CHAR_BUDGET environment variable pins a fixed character count instead. Raising it works, but you are spending context that the actual task would otherwise get, so do this after trimming, not before.
One naming discrepancy worth knowing
The per-entry cap has a setting too, and here the two primary sources disagree on what it's called. The docs page names it skillListingMaxDescChars. The published settings schema defines the same mechanism, with the same 1,536 default, as maxSkillDescriptionChars.
I'm flagging this because I got it wrong in the other direction recently: I checked one source, didn't find the name I expected, and concluded the setting didn't exist. It does. If you look for one name and come up empty, check the other before deciding the knob isn't there.
A debugging order that works
When a skill won't trigger, this sequence finds the cause faster than rewriting prose:
- Run
/doctor. If your listing is over budget, fix that first — nothing about your description matters if it was dropped. - Check whether the skill's
description+when_to_useis near 1,536 characters. If it is, the specifics at the end are gone. - Read your description's first sentence alone. If it's a noun phrase ("SQL helper") rather than a task ("Read SQL and propose indexes"), Claude has nothing concrete to match a user message against.
- Only then rewrite the body.
Most "my skill doesn't trigger" reports I've traced end at step 3. But steps 1 and 2 are the ones you cannot find by staring at the file, which is exactly why they eat afternoons.
Why this gets worse as you improve
The uncomfortable part of the shared budget is that it punishes success. Every skill you add makes every other skill's description slightly more likely to be dropped. A setup that worked at 8 skills can quietly degrade at 25 without a single file changing. If you're building a library that grows, budget checks belong in your routine — not just in your debugging.
Verified against https://code.claude.com/docs/en/skills and the published Claude Code settings schema on 2026-07-27. Behaviour and setting names move between versions — check your own before relying on a number here.
I write these while building Rulestack, packs of production-ready rules, skills, and hooks for Claude Code, Cursor, and Codex. I also post shorter findings like this one on Bluesky at @ai-shop.bsky.social — follow along if this is your kind of problem.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.