Skip to content
Claude Code Skills Explained: SKILL.md, Where Skills Go and When to Use One
← All postsAI Tools

Claude Code Skills Explained: SKILL.md, Where Skills Go and When to Use One

November 7, 2026·FixMyPrompt Team·11 min read
Share

What a Claude Code skill is, how SKILL.md frontmatter works, where to put skills, how to stop Claude running one on its own, and how to move a long procedure out of CLAUDE.md into a skill.

#claude code skills#skill.md#claude code custom commands#claude code slash commands#claude.md#claude code plugin

If you keep pasting the same checklist into Claude Code, or your CLAUDE.md has a twelve-step deploy section in the middle of it, you want a skill. A skill is a Markdown file of instructions that Claude loads only when the task calls for it. You can also run one yourself by typing its name after a slash.

This guide covers how skills load, where they go, the frontmatter fields worth knowing, and how to tell whether a piece of guidance belongs in a skill, in CLAUDE.md or in a hook.

What a skill is

A skill is a folder with a SKILL.md file in it. The file has two parts. YAML frontmatter at the top says what the skill is for, and the Markdown below it holds the instructions.

---
description: Writes release notes from the commits since the last tag. Use when the user asks for release notes or a changelog entry.
---

Write release notes for the commits below. Group them under Added, Changed and Fixed. Leave out merge commits and anything that only touches tests.

What makes skills cheap is how they load. At the start of a session, Claude Code puts only each skill's name and description into context, so Claude knows what is available. The body loads when the skill is used. A 300-line reference skill costs a line or two of context until the moment Claude needs it.

Compare that with CLAUDE.md, which is read in full at the start of every session, including the sessions that never touch the thing a section describes.

Custom slash commands are now part of the same system. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both give you /deploy. Your old command files keep working, but skills can do more: they can carry supporting files, and Claude can load them on its own when they apply.

Where skills go

Where you save a skill decides which sessions see it:

LocationPathLoads in
Personal~/.claude/skills/<name>/SKILL.mdAll your projects, on this machine
Project.claude/skills/<name>/SKILL.mdThis repo. Commit it and your team gets it
Nested<subdir>/.claude/skills/<name>/SKILL.mdWork in that part of a monorepo
Plugin<plugin>/skills/<name>/SKILL.mdAnywhere the plugin is enabled, as /plugin-name:skill-name

There are also enterprise skills, deployed by an administrator through managed settings, and skills synced from your claude.ai account.

When two skills share a name, enterprise wins over personal and personal wins over project. Plugin skills never clash, because their names carry the plugin's prefix. Personal skills in ~/.claude/skills/ do not load in cloud sessions or Cowork. If a scheduled cloud task needs a skill, commit it to the repo or enable it on your claude.ai account.

Claude Code watches these folders, so a skill you add or edit mid-session is picked up without a restart.

Your first skill

This one writes release notes, and it pulls the real commit list in before Claude reads anything. Save it as .claude/skills/changelog/SKILL.md:

---
description: Writes release notes from the commits since the last tag. Use when the user asks for release notes, a changelog entry or "what shipped".
disable-model-invocation: true
allowed-tools: Bash(git log *)
---

## Recent commits, newest first

!`git log --oneline --no-merges --decorate=short -50`

## Instructions

Write release notes from the commits above the first one that shows a `tag:`. Group them under Added, Changed and Fixed, one line each, in plain words a user would understand. Leave out commits that only touch tests or CI. If there are no commits above the tag, say nothing has changed since the last tag.

The line that starts with !` is dynamic context injection. Claude Code runs the command and puts its output in place of the line before Claude sees the skill. Claude never has to guess what changed, because the commit list is already in front of it.

Type /changelog and you get grouped notes with the test-only commits left out. disable-model-invocation: true means only you can start it. Leave that line out and Claude will also run it when you ask something that matches the description, such as "what shipped this week?"

Two things tripped us up while testing this one:

  • The allowed-tools line is required. An injected command never asks for permission. Unless you are in auto mode, Claude Code checks it against your permission rules, and if the answer is anything but allow, the whole skill aborts with Shell command permission check failed. Pre-approving Bash(git log *) in the frontmatter fixes that.
  • Keep injected commands simple. Our first version used git log $(git describe --tags --abbrev=0)..HEAD, and it aborted with "A nested command in this command can't be checked before it runs". Claude Code will not run a $(...) it cannot check, even with allowed-tools. So the skill hands Claude the last 50 commits and tells it where to stop.

Pick the name with care too. We first called it release-notes, and /release-notes ran Claude Code's own built-in command instead, which shows Claude Code's release notes.

The frontmatter fields worth knowing

Every field is optional. The docs recommend always setting description, because it is what Claude matches your request against. The ones you will reach for most:

FieldWhat it does
descriptionWhat the skill does and when to use it. Put the main use case first: the listing cuts it off at 1,536 characters
nameThe command you type. Defaults to the folder name
disable-model-invocationtrue means only you can start it. Use it for anything with side effects
user-invocablefalse hides it from the / menu, so only Claude can load it. Use it for background knowledge
allowed-toolsTools Claude can use without asking, for the turn the skill runs in
pathsGlob patterns. Claude loads the skill on its own only when working on matching files
contextfork runs the skill in a separate subagent that does not see your conversation
argument-hintShown in autocomplete, such as [issue-number]

Anything you type after the skill name arrives as $ARGUMENTS, and $0, $1 and so on give you single arguments. /fix-issue 482 with Fix GitHub issue $0 in the body becomes Fix GitHub issue 482.

A field name has to match exactly. Claude Code ignores one it does not recognize and gives no error, so disable_model_invocation with underscores does nothing.

Who can start a skill

By default, both you and Claude can. The two invocation fields change that, and they also change what sits in context:

FrontmatterYou can run itClaude can run itDescription in context
(default)YesYesAlways
disable-model-invocation: trueYesNoNo
user-invocable: falseNoYesAlways

The rule of thumb from Anthropic's docs: if a skill deploys, commits, sends a message or does anything else you would want to time yourself, set disable-model-invocation: true. You do not want Claude deciding to deploy because the code looks ready. If Claude tries to run a skill marked that way, Claude Code blocks the call and Claude suggests you run it.

Skill, CLAUDE.md or hook?

These three get mixed up, and the choice matters because each one loads differently.

Put it inWhenExample
CLAUDE.mdA fact Claude needs in every session"Tests run with pnpm test." "Never edit files in generated/."
A skillA procedure or reference you need some of the timeHow to cut a release, the API style guide, a migration checklist
A hookA rule that must hold every time, with no exceptionsBlock rm -rf, format every edited file

CLAUDE.md is for short, always-true facts. A skill is for anything long or occasional. A hook is for the cases where "Claude usually follows it" is not good enough. A skill is still a request to the model, and the docs say so plainly: if Claude skips a rule that has to hold every time, move that rule into a hook. Our Claude Code hooks guide has four you can copy.

The most common mistake is the first row filling up with things that belong in the second. In our study of 1,431 CLAUDE.md and AGENTS.md files from the 3,000 most-starred active GitHub repos, 28% of the full files ran past Anthropic's 200-line guidance, and one in seven was over 5,000 estimated tokens. All of that is read at the start of every session. A lot of the length in long files is procedures: release steps, migration rules, how to add a new endpoint.

Moving a procedure out of CLAUDE.md

Say your CLAUDE.md has this in it, along with forty other lines:

## Database migrations

When you change the schema:
1. Write a new SQL file in supabase/migrations/, numbered after the last one.
2. Never edit a migration that has already been applied.
3. Never run `prisma db push`. This database is shared and it drops tables it doesn't know about.
4. Run the migration against the local database and run the tests.
5. Tell the user the file name. They apply it to production.

Most sessions never touch the schema, and every one of them pays for those lines. Move the steps to .claude/skills/db-migrations/SKILL.md:

---
description: How to change the database schema in this repo. Use when adding or changing tables, columns, indexes or RLS policies.
paths: supabase/migrations/**, prisma/schema.prisma
---

1. Write a new SQL file in supabase/migrations/, numbered after the last one.
2. Never edit a migration that has already been applied.
3. Run the migration against the local database and run the tests.
4. Tell the user the file name. They apply it to production.

The paths line means Claude loads the skill on its own when it works on a migration or the schema file, and the description catches requests like "add a column for X" before any file is open.

Notice that one step did not move. "Never run prisma db push" is the rule where one miss costs you tables, so it stays as a single line in CLAUDE.md, where every session sees it. For a rule like that, a PreToolUse hook that blocks the command is safer still.

Claude Code's /doctor checkup now does a version of this for you. It looks at the guidance that loads in every session and offers to move procedures into skills or nested CLAUDE.md files that load on demand.

When a skill does not trigger

If Claude ignores a skill you expected it to use, work down this list:

  1. Check the description. It should contain the words you would naturally use when asking. "Database schema changes" will not match "add a column" as reliably as a description that says "adding or changing tables, columns, indexes".
  2. Ask Claude "What skills are available?" If yours is missing, check the folder path and the file name, which must be SKILL.md.
  3. Check the YAML. If the frontmatter does not parse, the skill still loads with no fields set. /skill-name works but Claude can no longer match the description. claude plugin validate .claude/skills finds files whose frontmatter is broken.
  4. Check paths. A skill with paths only activates for files inside Claude's current working directory.
  5. Check for an abort message. Shell command permission check failed means an injected ! command was not pre-approved in allowed-tools, and the skill never reached Claude.
  6. Check how many skills you have. The listing of names and descriptions has a budget of about 1% of the context window. With many skills installed, Claude Code drops descriptions for the ones you use least, and those then stop triggering. /doctor shows what the listing costs.

The opposite problem, a skill that fires when you do not want it, has two fixes: make the description narrower, or set disable-model-invocation: true.

Skills and long sessions

Once a skill runs, its text stays in the conversation for the rest of the session. Claude Code does not re-read the file on later turns. Two things follow from that.

Write instructions that should last as standing rules. "Run the tests after every edit" keeps applying. "Run the tests" reads like a step that is done after the first time.

Put the important part first. When a long session is compacted, Claude Code re-attaches the skills you used, but only the first 5,000 tokens of each, within a 25,000-token total that goes to the most recently used skills first. Anything near the bottom of a long skill can be cut, and older skills can drop out completely. If Claude seems to have forgotten a skill after a compact, run it again.

Skills in plugins

A plugin is a bundle of skills, hooks and MCP servers that installs in one step, and its skills are named after the plugin. Our own Claude Code plugin ships three, and you can read them to see a real one:

  • /fmp:doctor collects the repo's CLAUDE.md, AGENTS.md, Cursor and Copilot files, checks them, and writes fixed versions with a list of every change
  • /fmp:import reads your past Claude Code or Codex sessions in a folder and saves the lessons worth keeping as drafts for you to look over

The third, /fmp:sign-in, connects the plugin's session-start hook to your account. Each skill is a single SKILL.md, and every step it takes is written out in plain Markdown, which makes it a fair template for your own.

Skills are good at things you can write down in advance. They are no help with the things Claude worked out halfway through last Tuesday's session, such as why the build fails on a clean checkout or which test is flaky and how to get round it. None of that is in a skill unless you stop and write it. FixMyPrompt Memories is built for that part: what the agent solved is saved to your account and listed at the start of the next session, so it is not worked out again.

If you want to see how much of your CLAUDE.md should be a skill, paste it into the free CLAUDE.md checker. It shows what the file costs every session and which guardrails it never mentions.

Try it on the prompt that sent you here

Paste the prompt that misbehaved and see what is weak in it.

The weak spots and fixes are tuned to this goal.

0 of 5,000 characters

No prompt handy? Try one:

Found this useful? Share it.

Share

Read next

Run a free QA on your own prompt

Get a structured score, specific issues, and a rewritten prompt in seconds.

Run free QA