Claude Code skill not triggering: the causes and how to check each
Updated
The problem
You wrote a skill, saved it as SKILL.md, and asked Claude Code to do exactly what the skill is for. Claude did the task its own way and never used the skill. Typing /skill-name may or may not work. The search is "Claude Code skill not triggering".
The short answer
Claude decides whether to use a skill from its name and description alone, so a skill triggers only if Claude can see that description and it matches what you asked. The common reasons it cannot: the frontmatter does not parse (the skill then loads with no description), disable-model-invocation: true is set, the description is cut off in the skill listing, or the description never says when to use the skill. Pasting the file into Kanon (beta) rules out the parse and length problems in a few seconds; the rest of this page covers the checks it cannot make.
Why it happens
The causes below are documented in the Claude Code skills docs. The order is mine: start with the checks that a linter can answer, then the ones that need a running session.
1. Claude never saw the description
At the start of a session Claude Code loads a listing of every skill's name and description. That listing is all Claude has when it decides whether a request matches a skill. The body of SKILL.md is read only after the skill is chosen.
- The frontmatter is not on line 1. If anything comes before the opening
---, the whole file is read as content and the skill has no name or description. - The YAML does not parse. Claude Code then loads the skill with empty metadata.
/skill-namestill works, but Claude cannot match your description. The usual cause is an unquoted colon in the description, such asdescription: Use when: the user asks for a changelog. disable-model-invocation: true. This takes the description out of Claude's context on purpose, so Claude never runs the skill on its own. Only/skill-nameruns it.- A misspelled key. Claude Code silently ignores keys it does not know, so
descripton:means the skill has no description. In that case Claude Code falls back to the first non-empty line of the body, which is rarely a good trigger.
2. The description was cut
- Per skill: Claude Code cuts
descriptionpluswhen_to_useat 1,536 characters. A "use when" sentence at the end of a long description may never be seen. - Across all skills: the whole listing has a budget of 1% of the model's context window. When you have many skills and the listing overflows, Claude Code drops descriptions, starting with the skills you invoke least. A new skill has never been invoked, so it is a likely candidate to lose its description first. (That last point is my reading of the docs, not something I have measured.)
3. The description does not match the request
A description that only says what the skill does ("Generates changelogs") gives Claude less to match than one that also says when to use it and uses the words people actually type ("Generates a changelog from git history. Use when the user asks for release notes, a changelog, or what changed since the last tag.").
4. The skill is not where Claude Code looks
Personal skills live in ~/.claude/skills/<name>/SKILL.md and project skills in .claude/skills/<name>/SKILL.md — one folder per skill, with SKILL.md inside it. If What skills are available? does not list your skill, Claude Code has not loaded it at all.
A different problem: it triggered once, then stopped
If Claude used the skill at first and drifted later, the cause is different. Claude Code adds the skill's content when it is invoked and does not re-read the file on later turns. After the conversation is compacted, it keeps the first 5,000 tokens of each invoked skill, within a combined 25,000 tokens, starting from the most recent. Put the rules that matter most at the top of SKILL.md, invoke the skill again after compaction, and move rules that must hold every time into a hook.
Check it with the tool
Paste your SKILL.md into Kanon with the Claude Code target. It runs in your browser and sends nothing anywhere.
fm-first-lineandyaml-parse— the frontmatter would load as no fields, so Claude has no description to match.unknown-key— a key Claude Code will ignore. If it differs from a real key only in case,-or_, the message names the real key.desc-required,desc-empty— there is no description to match.desc-truncated— description pluswhen_to_useis over 1,536 characters, and the message says how long it is.desc-when— the description says what the skill does but not when to use it.desc-person— the description is written as "I can…" or "You can…" instead of in the third person, as the docs recommend.
Kanon does not flag disable-model-invocation: true, because it is a valid setting; check for it yourself. Kanon also cannot see your session, so it cannot tell you whether the listing budget dropped your description or whether the skill is in the right folder. The next section covers those.
What to do next
- Lint the file. Fix every error Kanon reports, then every
desc-*warning. - Restart and ask
What skills are available?. If the skill is missing, check the folder:.claude/skills/<name>/SKILL.mdor~/.claude/skills/<name>/SKILL.md. - Look for parse errors by starting Claude Code with
claude --debug, or runclaude plugin validate .claude/skills(v2.1.233 or later) to find everySKILL.mdwhose frontmatter does not parse. - Check the listing budget. Run
/contextand look at the Skills row, or/doctorfor the listing's cost. If descriptions are being dropped, raiseskillListingBudgetFraction(for example0.02for 2%), or set skills you rarely use to"name-only"inskillOverrides. - Rewrite the description with the key use case first, a "Use when…" sentence, and the words you would actually type.
- Test with the words in the description. If Claude still does not pick it up, run it directly with
/skill-name. For a skill in a plugin, an eval with atool_used: Skillgrader andclaude plugin evalmeasures how often it triggers across many prompts.