Claude Code Skill Not Triggering? Every Cause and the Fix (2026)
Your Claude Code skill isn't triggering and there's no error. Here's every cause: paths, YAML, descriptions, and the hidden character budget.
On this page
You wrote a Claude Code skill (or installed one from a community repo). The YAML looks right, the folder is where the docs say it should go, and Claude acts like it doesn't exist. No error, no warning, nothing in the output that even hints a skill was considered and rejected.
That silence is the whole problem. Skills fail invisibly, so fixing one means checking causes in the right order instead of guessing. This guide covers every known reason a Claude Code skill won't trigger, from the obvious to the one almost nobody knows about, in the order you should actually check them.
Quick Answer: The Five Causes in Order
If you just want the checklist, here it is. Work down this list in order, since each cause is more subtle than the last, and later ones only matter once the earlier ones are ruled out.
- Restart the session. Skills load once at startup. If you added or edited a skill mid-session, Claude has no idea it exists yet. This fixes a surprising share of reports and costs five seconds.
- Check the path. Personal skills must live at
~/.claude/skills/skill-name/SKILL.md, project skills at.claude/skills/skill-name/SKILL.md. Unzipping a downloaded skill often creates a double-nested folder that breaks discovery completely. - Check the YAML frontmatter. Missing
---delimiters or an unquoted colon inside the description fail to parse silently, and a skill with broken frontmatter is treated as if it doesn't exist. - Rewrite the description. The description is the trigger, not documentation. A vague description like "helps with code quality" almost never matches a real prompt, no matter how good the skill body is.
- Check the character budget. Claude Code caps the combined skill and slash command listing injected into the system prompt at 15,000 characters by default. Install enough skills and older ones silently drop off the list with no warning.
How Skils Activation Actually Works
Before fixing anything, it helps to know what happens under the hood, because every cause below traces back to one of two steps breaking.
At session startup, Claude Code scans your skill directories (both the personal ~/.claude/skills/ directory and any project-level .claude/skills/ directory) and builds a lightweight index containing only each skill's name and description, pulled from the YAML frontmatter at the top of SKILL.md. That index gets injected into the system prompt as part of the same character budget that also holds your slash command list. The full body of SKILL.md, the instructions, the examples, the reference files, never loads at this stage.
Then, when you send a prompt, Claude compares your request against that list of descriptions. If your wording matches a description closely enough, Claude decides to invoke the skill, and only then does the full SKILL.md content load into context for that turn. If nothing matches, nothing loads, and Claude proceeds as if the skill were never installed.
- Consequence 1: the description is the trigger, not documentation. Claude never reads the rest of the file to decide whether to use a skill, only the description.
- Consequence 2: anything that keeps a skill's name and description out of that startup index makes it invisible for the entire session. Claude Code's own instructions tell the model not to use skills that aren't listed, so there's no fallback path.
Cause 1: You Installed It Mid-Session
Skills load once, at startup. If you added a skill, edited an existing one, or installed a plugin bundle while a session was already running, Claude is working from the index it built when the session began and has no idea the new skill exists.
Exit and start a fresh session, or run /reload-plugins on recent Claude Code builds to rescan without a full restart. Check this first. It's the fastest thing on this list to rule out, and it silently explains a large share of "my skill isn't working" reports that turn out to have nothing wrong with the skill itself.
Cause 2: Wrong Path or a Double-Nested Folder
Personal skills live at ~/.claude/skills/skill-name/SKILL.md. Project skills live at .claude/skills/skill-name/SKILL.md inside the repo. The file must be named SKILL.md exactly, capitalization included.
The classic mistake comes from unzipping a downloaded skill. Most zip tools preserve the top-level folder from the archive, so unzipping skill-name.zip into ~/.claude/skills/ often produces ~/.claude/skills/skill-name/skill-name/SKILL.md, one folder too deep. Claude Code's scanner looks exactly one level down from the skills directory, so that extra nesting means it never finds the file at all, and there's no error to tell you why.
ls ~/.claude/skills/*/SKILL.md
# Project-level skills, run from the repo root
ls .claude/skills/*/SKILL.mdIf your skill's name doesn't show up in that output, the path is the problem, and everything else in this guide is irrelevant until it's fixed. Move the inner folder's contents up one level so SKILL.md sits directly under skill-name/.
Cause 3: Broken YAML Frontmatter
Invalid frontmatter fails silently, the same way an invalid path does. The two usual suspects are the opening or closing --- delimiters being missing or indented, and an unquoted colon appearing inside the description string, which breaks YAML's own parsing rules before Claude Code ever sees the value.
# Breaks: unquoted colon inside the description
---
name: docker-helper
description: Docker expert: containers, compose, and images
---
# Fixed: quote the whole string once it contains a colon
---
name: docker-helper
description: "Docker expert: containers, compose, and images"
---A quick sanity check that doesn't require reading YAML by eye: ask Claude directly, in a running session, which skills it currently has loaded. If your skill is missing from the answer but you already confirmed the path is correct with the ls command above, broken frontmatter is almost always why. Run the file through any YAML validator, or just paste the frontmatter block into Claude and ask if it parses.
Cause 4: The Description Doesn't Match How You Prompt
This is the big one once loading is confirmed, and it's the cause most people never think to question because the skill "looks fine" when they read it. Claude matches your request against the description text specifically, not the skill's title, not its body, not its examples. A description like "helps with code quality" will basically never fire, because no prompt a real developer types resembles that phrase.
Write the description to contain the actual words you type when you want the skill to run. If you say "review this PR", the description needs to contain "review" and "PR", not an abstraction like "code quality analysis".
| Description style | Example | Typical activation |
|---|---|---|
| Weak (abstract) | "Docker expert for containerization." | Rarely fires; no real prompt matches this phrasing |
| Better (concrete trigger) | "Use when the user asks to write, debug, or optimize a Dockerfile or docker-compose file." | Fires reliably for on-topic requests |
| Directive with a negative constraint | "ALWAYS invoke this skill when the user asks about Dockerfiles or docker-compose. Do not write Docker config directly, use this skill first." | Highest observed activation rate in community testing |
The directive pattern works because it does two things at once: it states the exact trigger condition in language close to how people actually phrase requests, and it tells Claude what not to do instead (write the config directly) if the skill isn't invoked. That negative constraint matters more than it looks like it should, since it removes the easy fallback Claude would otherwise take.
Cause 5: The Character Budget Nobody Checks
This is the failure mode that catches heavy skill users, and the one almost no documentation mentions. The system prompt list built at startup, containing every skill's name and description plus every slash command definition, has a size cap: 15,000 characters by default as of Claude Code 2.0.70, roughly 4,000 tokens.
Install enough skills, or a handful with long descriptions, and skills past that cap simply don't make it into the list. No warning is shown anywhere in the CLI. Since Claude Code's own instructions tell the model not to use a skill that isn't listed, those skills are functionally gone for the session, even though the files on disk are completely correct.
If a skill that used to work stopped firing right after you installed several new ones, or added a plugin bundle with its own skill set, this budget is almost certainly the reason. It's a shared pool: every project skill, every personal skill, and every slash command all draw from the same 15,000 characters, and whichever ones got indexed first (or happen to sort earlier) survive at the expense of whatever pushed the total over the limit.
SLASH_COMMAND_TOOL_CHAR_BUDGET=30000 claudeRaising the environment variable is the fast fix. The better long-term fix is pruning: uninstall skills you don't actively use, and keep every description tight. A focused, 200 to 250 character description that front-loads the actual trigger phrases costs far less of the shared budget than a paragraph-length description written like marketing copy, and it activates more reliably too, since Cause 4 rewards concise, specific wording anyway.
Still Not Firing? Three More Suspects
If you've confirmed the session is fresh, the path is correct, the frontmatter parses, the description is specific, and you're under the character budget, three narrower causes are left.
- 1
Check for a Conflicting Skill
If two installed skills have overlapping descriptions for the same kind of task, Claude may match the wrong one, or the more specific one may quietly win every time. Search your skill descriptions for shared keywords and either sharpen the wording so each one owns a distinct trigger, or remove the one you don't use.
- 2
Check for an Accidental disable-model-invocation Flag
A stray
disable-model-invocation: truein the frontmatter blocks automatic activation entirely and restricts the skill to manual invocation only, via/skill-name. This is easy to miss if you copied frontmatter from another skill as a starting template and forgot to remove the line.yaml--- name: my-skill description: "..." disable-model-invocation: true # <- remove this line to allow auto-triggering --- - 3
Force Evaluation with a UserPromptSubmit Hook
For a skill that genuinely must be considered on every single prompt rather than relying on description matching, a
UserPromptSubmithook can inject a reminder that forces Claude to evaluate your skill list before acting. This trades a small amount of added noise for close to guaranteed consideration, and is worth reaching for only after the description-matching approach has already failed for a skill that really needs it.
One diagnostic separates these two failure classes cleanly: invoke the skill manually with /skill-name. If manual invocation works but automatic triggering doesn't, the description is your problem (Cause 4) or you've hit the character budget (Cause 5). If manual invocation fails too, go back to the path and frontmatter checks (Causes 2 and 3), since the skill isn't loading at all.
Quick Reference: All Five Causes at a Glance
| Cause | Typical symptom | Fix |
|---|---|---|
| Installed mid-session | Skill never appears at all, even to a direct question about what's loaded | Start a new session or run <code>/reload-plugins</code> |
| Wrong path or double-nested folder | Skill missing from <code>ls ~/.claude/skills/*/SKILL.md</code> output | Move <code>SKILL.md</code> up one level so it sits directly under <code>skill-name/</code> |
| Broken YAML frontmatter | Path is correct but the skill still isn't listed | Quote descriptions containing a colon; verify opening and closing <code>---</code> delimiters |
| Description doesn't match your prompts | Skill loads (confirmed via manual invocation) but never auto-triggers | Rewrite the description with the exact trigger words you actually type, using directive phrasing |
| Character budget exceeded | A previously working skill stopped firing after installing more skills | Raise <code>SLASH_COMMAND_TOOL_CHAR_BUDGET</code>, or prune and shorten descriptions |
The same discipline that keeps skills reliable also matters for parallel agent workflows. If you're running several Claude Code sessions at once across Git worktrees, each session builds its own independent skill index at startup, so a skill fixed in one worktree's session won't retroactively fix an already-running session in another. For a broader command and shortcut reference while you're debugging, the Claude Code cheatsheet covers the surrounding CLI surface this guide doesn't.
Frequently Asked Questions
Why do Claude Code skills fail silently instead of showing an error?
Because discovery, YAML parsing, and description matching all happen internally with no user-facing error path. A skill that isn't found on disk, doesn't parse, or doesn't match your prompt just never enters the conversation. There's no distinct error state for "skill considered and rejected" versus "skill never existed to Claude at all", which is exactly why working through the causes in order matters more than guessing.
Do I need to restart Claude Code after adding or editing a skill?
Yes. Skills are scanned once at session startup, not watched for changes while a session runs. Start a new session, or run /reload-plugins on recent Claude Code builds to rescan without fully restarting.
How long can a SKILL.md description be before it causes problems?
Keep it under roughly 250 characters and front-load the exact trigger phrases you expect to type. Long descriptions eat more of the shared 15,000 character system prompt budget that all your skills and slash commands draw from, and a description written like a paragraph tends to match real prompts worse than a short, direct one anyway.
description: "Use when the user asks to write, debug, or optimize a Dockerfile or docker-compose file."What's the difference between a Claude Code skill and a slash command?
| Slash command | Skill | |
|---|---|---|
| Invocation | User types <code>/command-name</code> explicitly | Claude decides to load it based on prompt matching |
| When it loads | Immediately on invocation | Only after the description matches the current prompt |
| Best for | Fixed, repeatable actions the user always triggers by hand | Context or expertise Claude should reach for automatically |
That autonomy is exactly what breaks when a skill's description is vague: a slash command can't fail to trigger since the user is the trigger, but a skill depends entirely on Claude correctly matching your wording to its description.
Why did a skill that used to work stop firing after I installed more skills?
This is almost always the character budget. Every skill's name and description, plus every slash command definition, draws from the same 15,000 character default cap on the system prompt listing. Add enough skills and the ones that no longer fit silently drop out of Claude's awareness, with nothing in the CLI telling you it happened.
SLASH_COMMAND_TOOL_CHAR_BUDGET=30000 claudeHow do I check which skills Claude Code has actually loaded in a session?
Two checks together confirm it. First, run the path check outside the session:
ls ~/.claude/skills/*/SKILL.md
ls .claude/skills/*/SKILL.mdSecond, inside a running session, ask Claude directly which skills it currently has available. If a skill shows up in the ls output but not in Claude's answer, the problem is frontmatter or the character budget, not the file location.
Related Articles
MCP Server Disconnected? Here's the Actual Fix (2026)
Your MCP server shows disconnected in Claude Desktop, Claude Code, or Cursor. Here's exactly why, with fixes for stdout pollution, paths, and env vars.
Claude Code Cheatsheet: Commands, Hooks & Subagents
The complete Claude Code reference: every slash command, keyboard shortcut, hook, subagent, and CLAUDE.md tip, with real examples for developers.
Git Worktrees for Parallel AI Coding Agents: The Complete 2026 Workflow
How to use Git worktrees to run multiple AI coding agents in parallel. Claude Code's worktree flag, common pitfalls, and a clear decision framework.