CoreCodeBlog

Guides

Claude Code skills: how to use them and write SKILL.md

Published · Last checked

A skill is a SKILL.md file of instructions: Claude uses it when it is relevant, or you can invoke it directly with /skill-name. This page walks through Anthropic's Extend Claude with skills documentation: creating a first skill, where skills live, how to write the frontmatter, how to control who invokes a skill, and what to check when one does not trigger. The documentation was checked on October 30, 2026.

Key points
  • Create a SKILL.md file and Claude adds it to its toolkit. Claude uses it when relevant, or you invoke it directly with /skill-name.
  • A personal skill goes in ~/.claude/skills/<skill-name>/SKILL.md and a project skill in .claude/skills/<skill-name>/SKILL.md. On a name clash, enterprise wins over personal, and personal over project.
  • Every field is optional. Only description is recommended, because Claude uses it to decide when to apply the skill.
  • To stop Claude from using a skill on its own, set disable-model-invocation: true in its frontmatter.
  • Custom commands have been merged into skills: .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both create /deploy and work the same way.

When to write a skill

The documentation's test: you keep pasting the same instructions, checklist, or multi-step procedure into chat, or a section of CLAUDE.md has grown into a procedure rather than a fact. Unlike CLAUDE.md content, a skill's body loads only when it is used, so long reference material costs almost nothing until you need it. For CLAUDE.md itself, see how to write CLAUDE.md.

The documentation also says custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way, and existing .claude/commands/ files keep working. What skills add is a directory for supporting files, frontmatter to control whether you or Claude invokes them, and the ability for Claude to load them automatically when relevant.

Create your first skill

This example comes from the documentation: a skill that summarizes the uncommitted changes in a git repository and flags anything risky. First, create a directory for it in your personal skills folder. Personal skills are available across all your projects:

mkdir -p ~/.claude/skills/summarize-changes

Second, write SKILL.md. Every skill needs this file, in two parts: YAML frontmatter between --- markers that tells Claude when to use the skill, and markdown content with the instructions Claude follows when the skill runs.

---
description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
---

## Current changes

!`git diff HEAD`

## Instructions

Summarize the changes above in two or three bullet points, then list any risks you notice such as missing error handling, hardcoded values, or tests that need updating. If the diff is empty, say there are no uncommitted changes.

The directory name, or the frontmatter name when you set one, becomes the command you type, and the description helps Claude decide when to load the skill automatically. The !`git diff HEAD` line uses dynamic context injection: Claude Code runs the command and replaces the line with its output before Claude sees the skill content, so the instructions arrive with the current diff already inlined.

Third, test it. Open a git project, make a small edit to any file, and start Claude Code by running claude. Either way works:

What did I change?     # matches the description, so Claude can invoke it automatically
/summarize-changes     # or invoke it directly with the skill name

Either way, Claude should respond with a short summary of your edit and a list of risks.

Where skills live

Where you save a skill decides which sessions load it. Save it under your home directory to get it in every project, commit it to a repository to share it with everyone who works there, or distribute it through a plugin or managed settings to reach a whole team.

LocationPathLoads in
Enterprise.claude/skills/<skill-name>/SKILL.md in the managed settings directoryAll users on machines where your organization deploys it
Personal~/.claude/skills/<skill-name>/SKILL.mdAll your projects on this machine, but not Cowork or cloud sessions
Project.claude/skills/<skill-name>/SKILL.mdSessions in this repository. Commit it so your team gets it too
Nested<subdir>/.claude/skills/<skill-name>/SKILL.mdSessions started in or below <subdir>; a session started above it loads the skill once Claude works on files there
Additional directory.claude/skills/<skill-name>/SKILL.md in a directory you pass with --add-dirThat session
Plugin<plugin>/skills/<skill-name>/SKILL.mdWherever the plugin is enabled, as /plugin-name:skill-name

When two skills share a name (an excerpt of the documentation's table):

One more rule: skills in a .claude/skills/ directory below where you started do not load at startup. They load the first time Claude reads or edits a file in that subdirectory. Until then they do not appear in the / menu and you cannot invoke them by name.

You do not need to restart after changing a skill. Claude Code watches skill directories, so adding, editing or removing a skill under ~/.claude/skills/ or the project .claude/skills/ takes effect within the current session. If you create a top-level skills directory that did not exist when the session started, run /reload-skills.

The frontmatter fields that matter most

All fields are optional. Only description is recommended. A field name must match the table exactly, hyphens included: Claude Code ignores a field it does not recognize without reporting an error. Boolean fields accept yes, no, on, off, 1, and 0 in any letter case, in addition to true and false.

FieldRequiredWhat it does
nameNoCommand name shown in the / menu. Defaults to the directory name.
descriptionRecommendedWhat the skill does and when to use it. Claude uses this to decide when to apply the skill. If omitted, uses the first non-empty line of the markdown content.
when_to_useNoAdditional context for when Claude should invoke the skill, such as trigger phrases or example requests. Appended to description and counted toward the 1,536-character cap.
argument-hintNoHint shown during autocomplete to indicate expected arguments, such as [issue-number] or [filename] [format].
argumentsNoNamed positional arguments for $name substitution in the skill content. Accepts a space-separated string or a YAML list.
disable-model-invocationNoSet to true to prevent Claude from automatically loading this skill. Use for workflows you want to trigger manually with /name. Default: false.
user-invocableNoSet to false when only Claude should invoke the skill: Claude Code hides it from the / menu and does not run it when you type /name. Default: true.
allowed-toolsNoTools Claude can use without asking permission during the turn that invokes this skill. The grant clears when you send your next message.
pathsNoGlob patterns that limit when this skill is activated. When set, Claude loads the skill automatically only when working with files matching the patterns.
contextNoSet to fork to run in a forked subagent context.

The documentation lists more fields, including model, effort, agent, background, hooks, shell, metadata, license and compatibility; they are not covered here. One caveat: Claude Code reads the frontmatter only when the opening --- is the file's first line. Otherwise it treats the whole file, --- markers included, as skill content.

Invoking a skill yourself or letting Claude choose

By default, both you and Claude can invoke any skill. You type /skill-name to invoke it directly, and Claude can load it automatically when relevant to your conversation. Two frontmatter fields restrict this:

FrontmatterYou can invokeClaude can invokeWhen loaded into context
(default)YesYesDescription always in context, full skill loads when invoked
disable-model-invocation: trueYesNot on its ownDescription not in context, full skill loads when invoked
user-invocable: falseNoYesDescription always in context, full skill loads when invoked

The documentation's deploy example:

---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---

Deploy $ARGUMENTS to production:

1. Run the test suite
2. Build the application
3. Push to the deployment target
4. Verify the deployment succeeded

If Claude tries anyway, Claude Code blocks the call and instructs it not to reproduce the deploy steps another way, so expect Claude to suggest running /deploy yourself.

To run a skill directly, put its name at the start of your message: /deploy staging runs the skill directly. After plain text, as in go ahead and /deploy to staging, nothing runs directly. The name counts as your permission for that message: Claude can run the skill while it responds, and judges from your wording whether you asked it to. To write about the skill without permitting a run, leave off the slash.

Arguments and supporting files

Both you and Claude can pass arguments when invoking a skill. Arguments are available through the $ARGUMENTS placeholder, which is replaced with whatever follows the skill name:

---
name: fix-issue
description: Fix a GitHub issue
disable-model-invocation: true
---

Fix GitHub issue $ARGUMENTS following our coding standards.

1. Read the issue description
2. Understand the requirements
3. Implement the fix
4. Write tests
5. Create a commit

When you run /fix-issue 123, Claude receives "Fix GitHub issue 123 following our coding standards...". To access individual arguments by position, use $ARGUMENTS[N] or the shorter $N. If you invoke a skill with arguments but no placeholder in the skill's content receives one, Claude Code appends ARGUMENTS: <your input> to the end of the skill content so Claude still sees what you typed.

A skill directory can hold several files. That keeps SKILL.md focused on the essentials while Claude reads detailed reference material only when needed:

my-skill/
├── SKILL.md (required - overview and navigation)
├── reference.md (detailed API docs - loaded when needed)
├── examples.md (usage examples - loaded when needed)
└── scripts/
    └── helper.py (utility script - executed, not loaded)

Reference the supporting files from SKILL.md so Claude knows what each file contains and when to load it:

## Additional resources

- For complete API details, see [reference.md](reference.md)
- For usage examples, see [examples.md](examples.md)

The documentation's tip: keep SKILL.md under 500 lines and move detailed reference material to separate files.

Writing a good description

Troubleshooting

The skill does not trigger

If the frontmatter YAML is malformed, Claude Code loads the skill body with empty metadata, so /skill-name still works but Claude cannot match against your description. Run with --debug to see the parse error. To find SKILL.md files whose frontmatter does not parse, run claude plugin validate on the skills directory, for example claude plugin validate .claude/skills or claude plugin validate ~/.claude/skills. It requires Claude Code v2.1.233 or later.

The skill triggers too often

Make the description more specific. Add disable-model-invocation: true if you only want manual invocation.

Claude stops following a skill

When a skill is invoked, Claude Code adds its content to the conversation and does not re-read the file on later turns, so word guidance that applies to the whole task as "Run the tests after every edit" rather than "Run the tests". After compaction, Claude Code can keep only the start of an invoked skill, so put the most important instructions near the top of SKILL.md, and invoke the skill again to restore its full content. For a rule that must hold every time, the documentation recommends a hook instead.

Descriptions are cut short

With many skills, Claude Code drops some descriptions to fit the listing's character budget, which removes the keywords Claude needs to match your request. The budget scales at 1% of the model's context window, and descriptions are dropped starting with the skills you invoke least. Run /doctor for an estimate of the listing's context cost and its biggest contributors.

FAQ

Do my old .claude/commands/ files still work?

Yes. The documentation says custom commands have been merged into skills and existing .claude/commands/ files keep working. They support the same frontmatter except name and paths. Prefer a skill for new work, since skills also support supporting files. When a skill and a .claude/commands/ file share a name, the skill wins.

How do I stop Claude from using a skill automatically?

Add disable-model-invocation: true to its frontmatter. Claude can then no longer invoke it on its own, and it runs when you type /name. If you do not want to edit the file, the documentation says you can set the skill to "user-invocable-only" in skillOverrides.

What belongs in CLAUDE.md and what belongs in a skill?

Per the documentation, a section of CLAUDE.md that has grown into a procedure is a candidate for a skill, because, unlike CLAUDE.md content, a skill's body loads only when it is used. For writing CLAUDE.md, see how to write CLAUDE.md; for installing and connecting Claude Code, see Claude Code setup.

Sources