TL;DR: Create a markdown file in .claude/skills/<your-skill>/SKILL.md with YAML frontmatter (name, description) and the instructions below. The agent auto-discovers it and invokes it when a matching task comes up.
A skill is the smallest, lowest-ceremony way to teach the agent something. Drop a single markdown file in .claude/skills/, name it, write instructions in plain English. The agent picks it up next turn and remembers your way of doing things forever.
Every codebase has unwritten rules. Names go like this, errors get handled like that, this kind of file always needs this extra step. New contributors spend their first few weeks bumping into these conventions; the agent β at every fresh chat β does the same. The cost of re-explaining "we use snake_case for table names, not camelCase" five times a day is not zero, and the embarrassing failure mode is when the agent gets it wrong four times in a row because no one wrote it down.
The instinct to put these rules in CLAUDE.md is correct for project-wide invariants. But many habits aren't project-wide. They're situational: "when you're writing a test, do it like this." "When you're about to push, run this first." "When the user says 'ship it,' don't just deploy β also tag the release first." A 200-line CLAUDE.md full of "in this specific situation, do this specific thing" is hard for any reader (model or human) to use. The agent ends up loading everything every turn.
A skill is the smaller-grained alternative: one markdown file per situation, loaded only when relevant. The format is dead simple β frontmatter with a name and description, prose body with the instructions, optional supporting files alongside. The agent reads the description to decide whether the skill applies; if it does, it loads the body. Multiple skills coexist without fighting; you can write one in two minutes and forget about it for months until the situation comes up again.
SKILL.md with frontmatterdisable-model-invocationCreate a folder under .claude/skills/ named after your skill. Inside, put SKILL.md:
.claude/
βββ skills/
βββ tdd/
βββ SKILL.md β required
βββ examples.md β optional; supporting material
That's the whole structure. The folder name is the skill name. SKILL.md is the required entry point. Anything else next to it is fair game for the skill body to reference.
Open SKILL.md and start with YAML frontmatter:
---
name: tdd
description: Use this when the user asks for a test, when adding a new function, or when fixing a bug β write the test FIRST, then implement.
---
# Body goes here
When working in TDD mode:
1. Read the existing tests in the same module.
2. Write a failing test for the new behavior.
...
The description is the single most important field. The agent reads descriptions of all available skills and decides which ones to load based on what the user said. A vague description ("helps with tests") gets ignored; a specific one ("when the user asks for a test or to fix a bug, write the test first") gets matched.
Write descriptions in the form "Use this when [trigger]" or "For [situation], do [thing]." The phrasing carries more weight than you'd expect.
The body of SKILL.md is the actual instruction set. Aim for under 200 lines. Use imperative voice ("write the test before the implementation"), concrete examples, and explicit "do this, not that" pairs where the wrong answer is tempting.
You can refer to other files in the skill folder via relative path. The agent reads them when the skill is loaded. Good use of helper files: a long code example, a checklist, a reference table.
Two places to drop the skill folder:
.claude/skills/<name>/ inside the project root or any ancestor. Right for codebase conventions ("in this repo we use snake_case table names").~/.claude/skills/<name>/. Right for personal habits across all projects ("always run my lint check before suggesting a commit").Project-local skills keep their bare name. User-wide skills bundled inside a plugin get namespaced as <plugin>:<skill> β two plugins can each ship a tdd skill without colliding. A project-local tdd shadows any plugin's tdd.
Skills aren't only model-invoked. Two ways to trigger one manually:
/<skill-name> (or /<plugin>:<skill> for namespaced ones) and the skill loads immediately. Useful when the agent's auto-match didn't trigger.disable-model-invocation escape hatchSome skills are powerful enough that you don't want the model picking the moment to use them β destructive ones, expensive ones, third-party-API ones. Add this to the frontmatter:
---
name: deploy-to-prod
description: Build, sign, and deploy to production.
disable-model-invocation: true
---
The model now never sees this skill in its system prompt β it can't auto-invoke. But the slash menu still shows it, so a human can run it deliberately. This is the right setting for "I want this on hand but I want to be the one who decides when."