>_

Claude Code Skills Not Triggering: 4 Silent Causes [2026]

Robin||12 min
Last updated: September 15, 2026
claude-codeskillsagent-skillstool-selectionmeasurement
Claude Code skills not triggering or only activating some of the time - why most skill files online are dead weight, silently broken skills, Claude ignoring a skill, SKILL.md description field, when_to_use frontmatter, skill listing character budget, skillListingBudgetFraction setting, silent description truncation, skill-doctor report, claude plugin eval, progressive disclosure, primeline-ai/primeline-skills

Claude Code skills not triggering is almost never a bug in the skill

You wrote a skill. The instructions inside it are good. You have tested them by pasting them into a chat and they work. Then you install it, do the exact work it was built for, and Claude never calls it. You go back and improve the body. It still never runs.

I had twenty skills on this machine and I went looking for how many of them were actually being chosen. The answer sent me into the frontmatter, not the body, and then into a character budget I did not know existed.

TL;DR: Claude picks a skill from a short listing of names and descriptions loaded at startup. The body of the file is invisible at that moment. So there are four ways a correct skill never runs: the description says what it does instead of when you need it, the field everyone reaches for does nothing on its own, the description gets silently deleted to save space, or the model does the job by hand instead. Three of the four give you no error.

The questions people actually ask, and where each is answered here. Why does my skill not trigger? The listing is the whole decision. Why do my skills only fire some of the time? Same answer, and I measured the size of it. Why are most skill files you find online pointless? They put the work in the half nobody reads. Is Claude ignoring my skill, or never seeing it? Two different problems, two different fixes. Should I use when_to_use? It is appended to description, so it changes nothing by itself. Why did it work and then stop? Your description was probably deleted. How do I check my own setup? Four commands.

161commands and skills on my machine
0of them declare when_to_use
37say when to reach for them
20,950characters of description competing for space

The model never reads your skill before it picks it

Claude Code loads a listing at startup: every available skill's name and description, and nothing else. That listing sits in the context window for the whole session. When you type a request, the choice of which skill to invoke is made against that listing alone.

The body of your SKILL.md is not in the running at that point. It gets loaded after the skill is chosen. Anthropic calls this progressive disclosure and documents it as three levels: metadata always loaded, the file body loaded on trigger, bundled files loaded on demand.

That single fact explains most of what follows. If you are fixing a skill that never triggers by editing its body, you are editing something the model has not seen yet.

Claude Code skill selection order - startup skill listing with name and description, request arrives, choice made from the listing alone, SKILL.md body loads only after the skill is chosen, progressive disclosure, skill never triggering
The choice is made from the listing. The body of your skill is not in the room yet. (click to expand)

Why most skill files you find online are dead weight

The most upvoted question in this corner of the internet is why nearly every skill file people publish looks useless. Open ten of them and nine start the same way: "You are an expert full-stack engineer." Then a long, careful body.

That body is not the problem. The problem is where the effort went. All of it sits in the half the model has not read yet when it decides. The description, the one line that is in the room at decision time, is usually an afterthought.

This also settles a question people ask in the wrong shape. "Claude is ignoring my skill" and "Claude never saw my skill" look identical from the outside and have opposite fixes:

What you seeWhat is actually happeningThe fix
The skill never runs, on any wordingIt was never in the running. The description does not name your situation, or it was cut for spaceRewrite the description, or free up listing space
It runs sometimes, not alwaysSame cause, weaker. The description half-fits, so the choice is a coin flipOne sentence naming the situation. In my runs that moved a tool from 0 of 10 to 10 of 10
It runs, and does the wrong thingIt really was chosen, and the body is at faultNow, and only now, edit the body

The third row is the only one where rewriting the body helps. The first two are decided before the body exists.

There is a fourth possibility worth ruling out before any of this: a skill may be the wrong shape for the job. A slash command you always type yourself, a subagent, or a server has different rules about when it runs. Skills vs plugins vs MCP vs subagents is the map for that choice.

Cause 1: the description says what, not when

Most descriptions are labels. They answer "what is this tool" accurately and completely, and they lose.

I ran this as a proper experiment rather than guessing, and wrote the whole thing up separately: one skill, one frozen prompt, 230 runs, and the only thing that changed between arms was the sentence describing the tool. A description that stated only what the tool does was picked 0 times out of 10. The same tool, same body, with one added sentence saying when you need it, was picked 10 out of 10.

Claude Code skill description experiment results - four arms, 230 pre-registered runs, description stating what the tool does picked 0 of 10, adding a when clause picked 10 of 10, length control arm, vocabulary control arm, tool selection, SKILL.md description field
Same tool, same instructions, same task. Naming the situation took it from never picked to always picked. (click to expand)

Three control arms rule out the obvious alternatives. A near identical length sentence describing a different situation scored 0 of 10, so it is not about adding text. A fitting sentence sharing no vocabulary with the prompt scored 10 of 10, so it is not keyword matching.

The rewrite is small. Here is the shape:

yaml
# before: accurate, and never chosen
description: Candidate comparison with a tradeoff table

# after: names the situation the reader is in
description: >
  Candidate comparison with a tradeoff table. Use when the user is weighing
  two or more named alternatives against each other and wants a reasoned
  recommendation with the tradeoffs made explicit, rather than an
  off-the-cuff opinion. Example requests: 'which of these two should I go
  with', 'A or B here, and why'.

Write it as the user's situation in plain words. Do not stuff it with keywords you hope will match, because the experiment shows you do not need to, and chasing keywords is how you end up writing for a string matcher instead of a reader.

Cause 2: the field you were told to use is not a lever

Skill frontmatter has a field called when_to_use. It reads like the purpose built answer to exactly this problem. It is not, and the documentation says why.

From the Claude Code skills reference: when_to_use is "Additional context for when Claude should invoke the skill... Appended to description in the skill listing and counts toward the 1,536-character cap."

Appended. The two fields are joined into one string before the model sees anything. In my experiment I put the identical sentence in when_to_use in one arm and in plain description in another, then hashed the listing line out of all fifty transcripts. Both produce the same 311 byte entry, same SHA-256. Same score, 10 of 10 either way.

Claude Code when_to_use versus description frontmatter field - both arms produce a byte identical 311 byte skill listing entry, same SHA-256 across 50 transcripts, appended to description, 1536 character cap, skill selection
Identical text in either field renders a byte-identical listing entry. There is no special selection channel. (click to expand)

So the field is not required. The text is what matters, and it matters wherever you put it.

Nobody on my machine uses it anyway

I checked all 161 commands and skills in my own setup on 14 September 2026. Exactly zero declare when_to_use. Grepping for the literal string "when to use" or the field name returns nothing at all, across every file. If you search your own setup for the field name and find nothing, that is not proof your setup is broken. It is the normal state.

One honest limit on this one: both arms scored at the top of the range, and two conditions at 100% cannot prove they are identical in harder cases. What the byte comparison does prove is that in this setup the same characters reach the model either way, which is a mechanism rather than a statistic.

Cause 3: your description was silently deleted

This is the cause that produces the "it worked last week" report, and it is the one almost nobody checks.

The listing has a character budget. It defaults to one percent of the context window, controlled by a setting called skillListingBudgetFraction. Each entry's description plus when_to_use combined is capped at 1,536 characters. When the total overflows, Claude Code does not warn you and does not refuse. It drops descriptions, starting with your least used skills, until it fits. Those skills stay in the listing as bare names with no text at all.

A bare name is close to useless for selection. The skill is present, visible, and unpickable.

Two things make this worse than it sounds.

It is zero sum once the budget is full. I measured this directly: adding 267 characters to one skill's description grew the total listing by only 20 characters. The other 236 came out of seven other skills, which silently became names only. One of the seven was security-review. Lengthening one description is not adding, it is trading, and you do not get to choose who loses.

Claude Code skill listing character budget is zero sum - adding 267 characters to one skill description grew the total listing by only 20 characters, seven skills stripped to bare names including security-review, skillListingBudgetFraction, silent description truncation
A full listing budget is a trade, not an addition. You do not get to pick who loses the space. (click to expand)

The eviction order is a trap. Descriptions are dropped least used first. A skill nobody has used yet is exactly the skill that gets stripped first, which keeps it unseen, which keeps it unused. A brand new skill can therefore be deleted from the listing before it ever had a chance.

Here is what my own setup looks like, measured rather than estimated:

What I measuredSkillsCommandsTotal
Entries20141161
Characters of description5,39315,55720,950
Mean characters per entry269110130
Entries with no description at all02626
Entries declaring when_to_use000
Entries saying when to reach for them53237

Two limits are in play here and they are in different units, so keep them apart. The per entry cap is 1,536 characters. The listing budget is a share of the context window, so it is measured in tokens. Converting my own 20,950 characters at roughly four characters per token gives about 5,200 tokens of description text. On a 200,000 token context the default one percent budget is 2,000 tokens, so the text is more than twice the room it has. On a one million token context the same budget is 10,000 tokens and the same setup fits with room to spare.

That is the part I had not seen written down anywhere: the same setup is over budget or under budget depending on which model you are running. Switch to a smaller context and descriptions start disappearing, with no message and no error.

Claude Code skill listing budget depends on context window size - skillListingBudgetFraction one percent of 200k tokens is over budget for 20,950 characters of descriptions while one percent of 1M tokens fits, silent truncation, model switch changes skill selection
Switching to a smaller context window can delete your descriptions, with nothing in your own setup changed. (click to expand)

There are three levers, all documented:

json
{
  "skillListingBudgetFraction": 0.02
}

Raising the fraction gives the listing more room, at the cost of context you wanted for work. There is also a SLASH_COMMAND_TOOL_CHAR_BUDGET environment variable for a fixed character count instead of a fraction, and a skillOverrides setting that lets you mark low value skills as name only on purpose, freeing room for the ones that matter. Mine is at 0.02, which is double the default, and it was set deliberately after I hit this.

This lives in primeline-ai/evolving-lite - the self-evolving Claude Code plugin. Free, MIT, no build step.

Cause 4: the model does the job by hand instead

The three causes above are all about being chosen. This one is different: the skill is chosen correctly, or would be, and the work still happens somewhere else.

I wrapped a one line shell command in a skill and ran ten sessions on tasks that fit it. The wrapper was picked once. In eight of the ten runs the model ran the underlying script directly, without going through the skill. One run reached neither.

So the skill was not rejected. It was routed around.

Claude Code skill wrapper bypassed by the model - skill invoked 1 of 10 runs while the underlying script ran directly 8 of 10, invocation counting undercounts real usage, when to delete a skill instead of rewriting its description
A skill that wraps a one-line command gets bypassed, not refused. Invocation counts undercount real usage. (click to expand)
And if you measure success by counting how often the skill was invoked, you would record one out of ten and conclude the skill is broken, when the work got done nine times out of ten by a shorter path.

That has a practical consequence for how you judge any of this. Counting invocations undercounts real usage whenever the skill wraps something the model can reach directly. Before you rewrite a description, ask whether the skill is adding anything the model cannot already do in one step. If it is not, the honest fix is to delete the skill, not to make it more findable.

There is a second version of the same problem that bit me harder. In the experiment above, the arm that never selected the tool gave a better answer than the arm that did, because the tool's own instructions forbade reading files and the model went and read the actual data instead. Raising the selection rate on a tool like that raises the rate at which a worse shortcut gets taken. Fix the body before you fix the description.

The part I cannot explain

I am not going to sell this as solved, because it is not.

After rewriting descriptions properly, I had ten tools carrying a clear sentence about when to reach for them. Across roughly 50,000 real tool calls, those ten were used 14 times in total.

Fourteen. On tools whose wording I had already proven works in a controlled test.

I have three candidate explanations and no measurement that separates them. The chance to use those tools may genuinely be rare in my day to day work. The model may be correctly judging that the tool is not worth the detour. Or my wording may fit the test prompt and not fit how I actually ask for things. All three are plausible. None is established.

What I can say is that the controlled result and the real world result are both true at once. Description wording decides the choice when the opportunity is held fixed. It does not follow that fixing wording gets your tools used, and anyone telling you otherwise is extrapolating past their evidence, including me if I stopped this section one paragraph earlier.

The four commands I would run on your setup

Run these before changing anything. Each one answers a different question above.

1. How many of your skills say when to reach for them?

bash
grep -L "[Uu]se when\|[Rr]each for" ~/.claude/skills/*/SKILL.md | wc -l

Read that as a rough screen, not a count. grep -L reads the whole file, not the description field, so a skill that says "Use when" somewhere in its body counts as a hit even though the listing never shows those words. Two of my twenty do exactly that. It tells you which files to open; the real number needs you to look at the frontmatter. On my machine the screen returns 13 of 20. Note the capital letter in the pattern: most real trigger sentences start with "Use when", and a lowercase-only search reports 19 of 20 and makes the problem look total.

2. Is your listing over budget?

bash
claude
/context

/context shows what is eating your context window, including the skill listing. If the listing is near its budget, some descriptions are already gone.

3. Which skills are actually being used?

bash
/skill-doctor

Reports per skill context cost and how often each was invoked in the session, and flags the ones never used. Needs Claude Code 2.1.252 or newer.

4. Does your skill survive a change?

bash
claude plugin eval <plugin-or-path> --ablation with-without

This runs your skill against realistic prompts with and without the plugin loaded and scores the difference. It arrived in Claude Code 2.1.269 on 11 September 2026, so any guide calling it early access is out of date.

One warning about the last one, from running it. Its most common first finding is that the skill exists and does not get picked on natural phrasing, which is the whole problem in this article. But its coverage is bounded by the prompts you give it. I deleted a rule from a test skill that the prompts never exercised, and the suite stayed green while the skill was broken. Before trusting a green result, break the skill on purpose and watch the check go red.

listingnot the body
whennot what
break itbefore trusting green

If you want a set of skills already written this way, the five workflow skills in primeline-ai/primeline-skills all carry a situation sentence in the description, and Evolving Lite is the session memory and hook layer they sit on. If you are still deciding which extension point you need at all, skills vs plugins vs MCP vs subagents covers that choice, and how to build a plugin is the step by step.

Honest scope

One machine, one model. Everything measured here is Claude Opus 5 on Claude Code 2.1.270, on my own setup of 161 commands and skills. Other models may weigh a listing differently. I have not tested that.

The 14 in 50,000 is unexplained. It is the most important number in this article and I cannot tell you why it is that low. See the section above for the three candidates and the missing measurement.

The budget arithmetic is mine, the mechanism is documented. The character counts, the entry counts and the zero sum measurement are from my own machine and I recomputed them while writing this. The 1,536 character cap, the one percent default and the eviction order come from Anthropic's documentation, quoted.

How the counts in that table were taken, since the method changes the answer. Each entry is its description field plus its when_to_use field, read out of the frontmatter only. A one-line grep over whole files gives a different, slightly higher number, because trigger words often sit in the body where the listing never shows them. The entry counts, the zero counts and the 26 commands with no description reproduce from a plain directory listing; the character totals need the frontmatter reader.

One fix I have not tested. A published suggestion for the eviction trap is to invoke an unused skill once by name, to lift its use count off zero so it stops being first in line for deletion. That is a plausible mechanism and I have not run it. Do not take it from me as measured.

Counting invocations is not counting usage. The wrapper measurement shows a skill scoring 1 of 10 while the work got done 9 times. Any number in this article that counts invocations carries that caveat.

FAQ

Why do my Claude Code skills only activate some of the time?+
Because the choice is made from one short line of text and yours only half fits the request. Claude loads a listing of every skill's name and description at startup and picks from that alone; the body of your SKILL.md is not loaded until after the choice. I tested this directly: one skill, one frozen task, 230 runs, and the only thing that changed between arms was the sentence describing the tool. A description saying what the tool does was picked 0 times out of 10. The same tool, same body, with one sentence naming the situation you are in when you need it, was picked 10 out of 10. A half-fitting description gives you the middle of that range, which is what an unreliable activation rate feels like from the outside.
Why are most Claude Code skill files you find online pointless?+
Because the effort went into the half that is not read at decision time. Nearly every published skill file opens with a persona line and then a long body, and leaves the description as an afterthought. The description is the only part in the room when Claude picks a skill, so a careful body behind a vague description is work the model never gets to see. That is also why copying a popular skill file rarely helps: you are copying the part that was never the deciding factor.
Is Claude ignoring my skill, or does it never see it?+
These look the same from outside and have opposite fixes. If the skill never runs on any wording, it was never in the running: the description does not name your situation, or it was silently dropped because the skill listing ran out of space. If it runs but does the wrong thing, it really was chosen and the body is at fault. Only in that last case does editing the body help. Check which case you are in before rewriting anything, because the first two are decided before the body is ever loaded.
How do I know if my skill is silently broken?+
Three of the four failures here produce no error at all, so you have to look rather than wait. Run /context to see whether the skill listing is over budget, since descriptions are dropped without a warning when it is. Run /skill-doctor, which needs Claude Code 2.1.252 or newer, to see per-skill context cost and how often each skill was actually invoked. Then read your own description and ask one question: does it name the situation someone is in when they need this? Accuracy was never the problem. A description can be completely correct and still get picked zero times out of ten.
Why is my Claude Code skill not triggering?+
Almost always because of the description, not the body. Claude picks a skill from a listing of names and descriptions loaded at startup, and the SKILL.md body is not read until after the choice is made. A description that states what the tool does, without stating when you need it, loses. In a 230-run experiment on my machine, a what-it-does description was picked 0 of 10 times and the same tool with one added when-you-need-it sentence was picked 10 of 10.
Should I use the when_to_use field or the description field?+
It makes no practical difference. Anthropic's documentation states that when_to_use is appended to description in the skill listing and counts toward the same 1,536-character cap, so both render as one string. I hashed the listing entry from fifty session transcripts and confirmed the two produce a byte-identical result. Zero of the 161 commands and skills on my machine declare the field at all.
Why did my Claude Code skill stop working after I added another one?+
Your description was probably deleted to make room. The skill listing has a character budget defaulting to one percent of the context window. On overflow, Claude Code silently drops descriptions, least used first, leaving those skills as bare names. I measured a 267-character addition to one skill grow the listing by only 20 characters while stripping seven other skills to names only, one of which was security-review.
How do I increase the Claude Code skill listing budget?+
Set skillListingBudgetFraction in settings.json to a larger fraction of the context window, for example 0.02 instead of the 0.01 default. There is also a SLASH_COMMAND_TOOL_CHAR_BUDGET environment variable for a fixed character count, and a skillOverrides setting that marks chosen skills as name-only on purpose, freeing room for the rest. Every character you give the listing is a character you do not have for work.
Does a new skill get ignored because it is new?+
It can, and the mechanism is documented. Descriptions are evicted least used first when the listing overflows, so a skill with zero uses is first in line to lose its description. Losing the description makes it unpickable, which keeps the use count at zero. A published suggestion is to invoke it once by name to lift it off the floor. I have not tested that fix and report it as a claim, not a measurement.
What does /skill-doctor report in Claude Code?+
Per-skill context cost and invocation count for the current session, and it flags skills that were never invoked so you can disable the expensive ones. It needs Claude Code 2.1.252 or newer. Bundled and enterprise skills are excluded from the report. Start with the highest-cost skills that show zero invocations, since those are pure context tax.
Is claude plugin eval still in early access?+
No. It arrived in Claude Code 2.1.269 on 11 September 2026, so any guide describing it as gated is out of date. It runs your plugin's skill against realistic prompts with and without the plugin loaded and scores the delta, and it can fail a build below a threshold. Its coverage is bounded by the prompts you write, so delete a rule on purpose and confirm the suite turns red before trusting a green run.
Does a better skill description mean the skill actually gets used?+
Not necessarily, and this is the honest gap. After rewriting descriptions to name the situation, ten of my tools carrying a working trigger sentence were used 14 times across roughly 50,000 real tool calls. The controlled experiment and that number are both true: wording decides the choice when the opportunity is held fixed, but it does not manufacture opportunities. I have three candidate explanations and no measurement that separates them.
Should I count how often a skill is invoked to judge it?+
Only with a caveat. I wrapped a one-line shell command in a skill and ran ten sessions on fitting tasks: the wrapper was picked once, and the underlying script ran directly eight times. The work got done nine times out of ten while the invocation count said one. If a skill wraps something the model can reach in one step, low invocation counts may mean the skill is redundant rather than unfindable.

>_ Get the free Claude Code guide

>_ No spam. Unsubscribe anytime.

>_ Related