The short answer: if your skill installed and nothing happens, the problem is
almost never the installation. It is the description field in SKILL.md. The
model decides whether to load a skill by reading that one line, and a line that names a capability
instead of naming a situation gets ignored. One rewrite of that line took an invocation rate from
about 5 percent to about 80 percent, on the same skill, with the same task.
The second most common cause is not an error at all. You edit
SKILL.md while a session is open, and the running process keeps using the version it
read at startup. About eight times out of ten the edit does nothing. There is a reload command and it
reports success, but it does not rescan the directories. You have to start a new process.
On Windows there is one more that everyone hits once: a skill that ships a
.ps1 file dies with check-rules.ps1 cannot be loaded because running scripts is
disabled on this system. That is the machine execution policy, and it is one command to fix.
Everything below is the detail, with the text each failure actually prints.
Ordered by how often they come up. Every string is reproduced as it appeared.
There is no error. The model answers normally and never mentions the skill. The usual
description looks like a label for a tool, something like
API interface design audit tool. A label does not tell the model when to reach for it,
so it never does.
The version that worked names the situation and then the literal words a person would type:
# before, a label that names the tool description: API interface design audit tool # after, the situation plus the literal words a user would type description: API design review. Use when the user says review the API, check the interface design, or audit endpoints.
Measured on the same task, the same skill, with nothing else changed: about 5 percent before, about 80 percent after. A three way test of the same idea put a bare capability line at about 5 percent, a line with the situation at about 40 percent, and a line with the situation plus the literal trigger phrases at about 85 percent.
Two things are happening in that line. The first half says when. The second half says what the user will actually type, including the casual and the half English versions people really use, because that is what arrives in the request.
check-rules.ps1 cannot be loaded because running scripts is disabled on this system.
This is the machine execution policy, not the skill. Fix it once per machine:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Then close the shell and open a new one. The old one keeps the old policy.
deepseek-v4-pro is not a model this version of claude code recognizes "deepseek-v4-pro" is not a model this version of claude code recognizes
Three different spellings of the same variable exist across the user level file, the project level file and the shell, and the project level one wins. So people fix the user level file, see no change, and conclude the skill is broken. Check both files and keep the model id in exactly one place.
On Windows, before debugging anything else, run chcp 65001. Without it the console
mangles non ASCII output and every error you read is half garbage.
A 529 is upstream capacity. It is not a local fault and retrying is the whole fix:
for i in 1 2 3; do claude -p "..." && break; sleep 15; done
A 401 or 429 usually means the key is sitting in the wrong place. Written into a project file, it travels with the repository, gets shared, and starts hitting per project limits. Put it in the user level settings file and keep it out of anything that gets committed.
About eight times out of ten, an edit made while the session is open is invisible to that session. The reload command answers politely and still misses it:
Reloaded skills: 72 skills available (no changes)
The workaround is not a setting. Start a new process. A fresh process lists the new skill immediately, including one written to disk after the session began:
claude -p '/skill-doctor'
If you are iterating on a description, that means one process per attempt. It is slow and it is the only thing that is reliable.
When two descriptions share trigger words, one of them loads and it looks arbitrary which one. This is not a bug you can report, it is two descriptions that both match. Give each one an exclusive keyword so a given request can only match one of them.
There are also two frontmatter switches that make a skill look like it never ran.
disable-model-invocation: true does what it says, and it has to be
false for the model to be able to reach the skill on its own. A skill declared with
context: fork does its work away from the conversation you are watching, which reads
exactly like nothing happened. Leaving context unset was the fix that held.
Four errors account for most of it, and each has a check you can run before you test the skill at all:
| Error | What it means here | The check to run first |
|---|---|---|
ModuleNotFoundError | The dependency is not in the interpreter the skill actually uses | python -m py_compile scripts/process.py |
FileNotFoundError | A relative path resolved against the wrong working directory | Resolve every path from the skill root |
PermissionError | The bundled shell script is not executable | bash -n scripts/run.sh then set the bit |
SyntaxError | Broken YAML header or broken script | Confirm --- on both ends and one space after every colon |
Output going to an unexpected place is the same class of problem. Pick one directory for every artefact a skill produces and write there, always. Skills that scatter files across the working directory look like they produced nothing.
This is the part that makes skills feel random until someone tells you. The loader is more likely to reach for a skill when the request looks like a procedure, and it tends to answer directly when the request looks like a single step.
| The request | Shape | What tends to happen |
|---|---|---|
| Read this PDF | Single step, one artefact | Usually answered directly, no skill loaded |
| Extract the tables from this PDF and batch convert them to Excel | Multi step, several artefacts | A matching skill is loaded almost every time |
| Analyse this file | Vague, no deliverable named | Direct answer, and often not the one you wanted |
| Analyse this sales CSV, compute the monthly trend, produce a standardised table and state the conclusion | Named input, named steps, named output | Skill loaded, output matches what you asked for |
So the test instruction matters as much as the description. If you are checking whether
a skill triggers, do not test it with a two word prompt. Test it with the sentence a real user would
say, with the input, the steps and the deliverable all named in it.
The other half is a cap that is easy to miss. description and
when_to_use are concatenated, and the combined text is truncated at 1536 characters in the
skill listing. This one is in the official documentation, but it is buried in the field reference and
almost nobody reads it before writing their first skill. Everything you wrote past that point is read by
nobody. Put the trigger words in the first hundred characters, not the second thousand.
Twelve steps, in order. Each one assumes the previous one is done.
node --version, and you want 18 or newer. Most of the strange failures below turn out to
be an older Node.npm install -g @anthropic-ai/claude-code then claude --version. Write the
version down. You will need it later, because several behaviours below changed between builds.~/.claude/settings.json,
in the env block. Project level settings override user level, so a key in a project file
wins, gets shared, and produces 401 and 429 for reasons that have nothing to do with your skill.chcp 65001 for the console, and
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser for any skill that
ships a .ps1. Restart the shell after the second one.SKILL.md, in capitals. The directory has no spaces and no non ASCII characters. A
lowercase skill.md is silently not a skill, and the loader does not tell you.Important constraints, near the top.C:\... works on exactly one machine and fails silently on every
other one./reload-skills reporting
no changes is not evidence that your edit landed.If a step fails with a 529, wrap the call in the retry loop from Failure 4 and run the step again before you change any configuration.
Every failure on this page, with the exact text, the environment it appeared in, the cause and the fix, in one CSV. It is a real file on this site, not something generated in your browser. Download it, or fetch it with curl:
https://openspec-mvp.pages.dev/claude-code-skills-failure-matrix.csvcurl -O https://openspec-mvp.pages.dev/claude-code-skills-failure-matrix.csv
19 rows, UTF-8 with a BOM so it opens correctly in Excel. Columns: Symptom, Exact text you see, Environment where it was seen, Root cause, Fix that worked, First reported.
None of these are benchmarks. They are what one person or one vendor measured on their own setup, and they are dated so you can judge how far your setup has drifted since. Where the number came from the vendor that sells the scanner, it says so.
| Date | Who reported it | What the number was | Who measured it |
|---|---|---|---|
| 2026-02-05 | A security vendor's published audit of a public skill registry | 3,984 skills scanned. 13.4% (534) carried at least one critical finding. 36.82% (1,467) carried at least one security flaw. 76 were confirmed malicious by human review. 8 of those were still publicly installable on the day the report went out. | The vendor, on its own scan. Vendor reported. |
| 2026-01 | The same vendor, describing a three week campaign in late January | 12 compromised publisher accounts, 341 to 1,184+ malicious skills published, 9,000+ installs observed | The vendor. Vendor reported, and the count was still moving when it was written. |
| 2026-09-18 | One user filing a bug against the CLI, still open | Idle CPU in the terminal went from 1.0% with no skills to 4.9% with 40 user skills, on Claude Code 2.1.276, Windows 11 Pro build 10.0.26200, Ryzen 9 3950X. Roughly 45 syscalls per second and roughly 0.07 to 0.1% of one core per skill directory. | The person who filed it, on their own machine. Self reported. |
| 2026-09-13 | One user filing a bug, still open | The reload command answered Reloaded skills: 72 skills available (no changes)
for a skill added to disk mid session, on desktop 2.1.266 and CLI 2.1.263. A fresh process saw
the same skill. |
The person who filed it. Self reported. |
| 2026-03-27 (closed 2026-04-26) |
One user filing a bug, now closed | 43 skills injected silently into the session, about 3,950 tokens, roughly 6,000 tokens per session in total, on Claude Code 2.1.84, macOS | The person who filed it. Self reported. |
| 2026-03-25 (closed 2026-03-29) |
One user filing a bug, now closed | Skills listed as disabled still consumed context tokens | The person who filed it. Self reported. |
Two of those rows are worth reading twice. Rows three and six say the same thing from different directions: a skill you are not using still costs you something, in idle CPU in one case and in context tokens in the other. The unit differs, the conclusion does not.
Three situations reliably break a setup that was working yesterday.
A model swap. Every trigger rate on this page was measured against one model on one build. Change either and the numbers move, including the ones you tuned a description against.
An upgrade. The behaviour in the two still open issues above is version specific. Pin your version and write it down, or you will not be able to tell an upgrade regression from your own mistake.
A long session. The longer a session runs, the more likely it is holding a stale copy of a skill you have since fixed. Restart rather than debug.
Everything above is about getting a skill to fire. This part is about what you pay while it sits there doing nothing, and it is the reason the advice on this page keeps coming back to having fewer of them.
A skill directory is scanned whether or not the skill is used. In the September measurement above, the cost was about 45 syscalls per second and about 0.07 to 0.1% of one core for each directory, and it did not depend on how large the directory was. In the same report, one skill directory holding 594 files and 4 MB measured 1.8% CPU and 486 operations per second, while the remaining skill directories together measured 3.8% and 1,965. The scanning is per directory, not per file. Those two figures are from separate readings inside one bug report, so read them as the shape of the problem rather than as a tidy sum.
The same shape shows up on the token side. 43 skills silently present in a session measured about 3,950 tokens before anyone asked for anything, and skills marked disabled were still counted. A skill you switched off is still a skill you are paying for.
The practical rule falls out of those two rows without any interpretation: reduce the number of skill directories, not the size of any one of them. Consolidating five small skills into one skill with five sections costs you less than it looks like it should, and splitting one large skill into five costs you more.
And audit what you install before you install it. The registry numbers at the top of the dated table are from a single vendor's scan and should be read as one measurement, not as a rate, but 76 skills confirmed malicious by human review is not a rounding error in anyone's book.