Claude Code Skills: How to Write a SKILL.md (5 Copy-Paste Examples)

Published Oct 15, 2026 · 9 min read

Short answer: a Claude Code skill is a folder containing a SKILL.md file. The file has YAML frontmatter (at minimum a name and a description) followed by Markdown instructions. Put it in .claude/skills/<name>/SKILL.md for a project or ~/.claude/skills/<name>/SKILL.md for every project. Claude loads the skill automatically when your request matches the description, or you run it yourself with /name.

Skills are the most underused part of Claude Code. Most people keep pasting the same checklist into chat ("run the tests, then lint, then write a commit message") or let their CLAUDE.md grow into a 400-line procedures manual. Both waste context. A skill fixes this: only its name and description sit in context until it's needed, and the full body loads only when the skill runs.

This guide covers where skills live, every frontmatter field that matters, how skills differ from subagents and slash commands, and five working skills you can paste into a repo today.

Where skill files live

LocationScopeUse it for
.claude/skills/<name>/SKILL.mdThis project, shared through gitTeam workflows: ship a feature, release, review a diff
~/.claude/skills/<name>/SKILL.mdYou, in every repoPersonal habits: PR descriptions, standup notes
A plugin's skills/ folderAnyone who installs the pluginDistributing skills across many repos

The folder name (or the name field) becomes the command you type. A skill can carry supporting files next to SKILL.md. Common subfolders are scripts/ for executable helpers, references/ for long docs Claude should read only when needed, and assets/ for templates.

.claude/skills/
└── release/
    ├── SKILL.md
    ├── scripts/
    │   └── bump-version.sh
    └── references/
        └── changelog-style.md

The SKILL.md format

Every skill has two parts: frontmatter between --- markers and Markdown instructions after it.

---
name: review-diff
description: Reviews the current git diff for bugs, missing tests and risky changes. Use when the user asks for a review, before committing, or before opening a PR.
---

1. Run `git diff --staged` (fall back to `git diff` if nothing is staged).
2. For each problem, report `file:line`, the issue, and a concrete fix.
3. Flag any change to auth, payments, migrations or env handling as HIGH RISK.
4. End with exactly one verdict line: APPROVE or REQUEST CHANGES.

The fields you'll actually use:

Arguments typed after the command are available as $ARGUMENTS. You can also inject live shell output into the prompt before Claude sees it with the !`command` syntax, which grounds the skill in the actual state of your repo instead of guesses.

Skills vs subagents vs CLAUDE.md

CLAUDE.mdSkillSubagent
LoadedEvery session, every turnOnly when invoked or matchedWhen delegated to
Best forFacts: commands, conventionsProcedures and checklistsIsolated roles with their own tools
Context costAlways paidNear zero until usedSeparate context window

A good rule: if a section of CLAUDE.md starts with "When you do X, follow these steps", move it into a skill. If you want a role with a restricted toolset (say, a reviewer that can't edit files), make it a subagent instead. Skills and subagents work well together: a /ship-feature skill can hand the plan to a planner subagent and the review to a code-reviewer subagent.

5 skills worth copying

1. summarize-changes (auto-invoked, read-only)

---
name: summarize-changes
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.
allowed-tools: Bash(git status:*), Bash(git diff:*)
---

## Current state
!`git status --short`

## Diff
!`git diff HEAD`

Summarize the changes above in 3 to 6 bullets grouped by area.
Then list anything risky: deleted tests, new dependencies, edited env or config files.
Finish with a one-line conventional commit message.

Because the diff is injected with !`git diff HEAD`, Claude reasons about your real working tree, not whatever files happen to be open.

2. write-tests (argument-driven)

---
name: write-tests
description: Writes focused unit tests for a file or function. Use when the user asks for tests, coverage, or edge cases.
argument-hint: [path-or-function]
---

Target: $ARGUMENTS

1. Read the target and its existing tests. Match the test framework and style already used.
2. List the behaviours and edge cases (empty input, boundaries, errors) before writing code.
3. Write the tests. Do not change source code to make tests pass.
4. Run the single test file and report pass/fail with the command you used.

3. release (manual only, has side effects)

---
name: release
description: Cuts a release: bumps version, updates CHANGELOG, tags. Only run when explicitly asked.
disable-model-invocation: true
argument-hint: [major|minor|patch]
allowed-tools: Bash(npm test:*), Bash(git tag:*), Bash(./.claude/skills/release/scripts/bump-version.sh:*)
---

1. Refuse if the working tree is dirty. Show `git status`.
2. Run `npm test`. Stop on any failure.
3. Run `scripts/bump-version.sh $ARGUMENTS`.
4. Add a CHANGELOG entry following references/changelog-style.md.
5. Show the diff and the tag command. Wait for my "go" before tagging.

disable-model-invocation: true matters here: you never want Claude deciding on its own that now is a good time to tag a release.

4. explain-codebase (forked context)

---
name: explain-codebase
description: Produces an onboarding map of the repo or one area of it. Use when the user is new to the code or asks how something works end to end.
context: fork
allowed-tools: Read, Grep, Glob
---

Scope: ${ARGUMENTS:-the whole repo}

Produce:
- A 5-line summary of what the code does
- The entry points and the main request/data flow
- The 10 files a new contributor should read first, with one line each
- Any surprising conventions or footguns

Exploration reads a lot of files. Running it in a forked context keeps all of that out of your main session; you get only the summary back.

5. pr-description (personal skill)

---
name: pr-description
description: Writes a pull request description from the current branch. Use when creating a PR or summarizing branch changes.
---

Run `git log --oneline main..HEAD` and `git diff main...HEAD --stat`.
Write:
- **What**: one sentence
- **Why**: the problem it solves
- **Changes**: grouped bullets
- **Testing**: exact commands run and results
- **Risk**: what could break, and how to roll back

Save this one in ~/.claude/skills/ so it follows you to every repo.

Making skills trigger reliably

  1. Write descriptions like search queries. Include the words people actually type: "review", "tests", "PR", "what changed".
  2. One job per skill. A skill that "handles testing, linting and deployment" matches everything and nothing.
  3. Keep the body short and point to references. Put the 300-line style guide in references/ and tell Claude when to read it.
  4. Use numbered steps with a clear stop condition. "Stop on any failure" and "wait for my go" prevent runaway runs.
  5. Back up must-never rules with hooks. A skill is instructions; a hook is enforcement. Pair a release skill with a hook that blocks git push --force.

Common mistakes

Get 4 tested skills plus the agents they call

The Claude Code Agent Starter Kit ($39) ships /ship-feature, /write-tests, /review-diff and /explain-codebase, wired to four subagents, three safety hooks and five CLAUDE.md templates. Get the Starter Kit: $39 Free safety hooks

FAQ

What is a Claude Code skill?

A skill is a folder containing a SKILL.md file: YAML frontmatter with a name and description, followed by Markdown instructions. Claude loads it automatically when a request matches the description, or you run it with /name. Only the name and description sit in context until the skill is used.

Where do I put SKILL.md?

Use .claude/skills/<name>/SKILL.md for a project skill shared through git, or ~/.claude/skills/<name>/SKILL.md for a personal skill available in every repo. Plugins can also ship skills.

How do I stop Claude from running a skill automatically?

Add disable-model-invocation: true to the frontmatter. The skill then only runs when you type its /name, which is what you want for deploys, releases and anything else with side effects.

What is the difference between a skill and a slash command?

They have been merged. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy. Skills add a folder for supporting files, automatic invocation and options such as running in a forked context.

Why isn't my skill triggering?

Usually the description is too vague. Say what the skill does and when to use it, using the words people actually type, such as review, tests, PR or what changed. Keep one job per skill.

The VibeKit Dispatch

One tested Claude Code / Cursor workflow every week. No hype, unsubscribe anytime.