How to write a SKILL.md file
Updated
A SKILL.md file is a Markdown file that opens with YAML frontmatter, where name and description are required, followed by the instructions your agent follows. It sits in a folder named after the skill, with scripts, reference docs and data files in subfolders the agent opens only when it needs them. New to skills? Start with what agent skills are.
The folder layout
The Agent Skills specification requires one file. The subfolders are optional:
skill-name/
SKILL.md # required: frontmatter, then instructions
scripts/ # optional: code the agent can run
references/ # optional: docs the agent reads when needed
assets/ # optional: templates, images, data files
The spec says name must match the folder name. In Claude Code, personal skills live in ~/.claude/skills/<skill-name>/SKILL.md and load in all your projects. Project skills live in .claude/skills/<skill-name>/SKILL.md, and committing them shares them with your team. Other agents use other folders. npx skills init my-skill creates a SKILL.md template in a new my-skill folder.
The frontmatter fields
Frontmatter is the YAML block between two --- lines at the top of the file. Claude Code reads it only if the opening --- is the very first line. The spec defines six fields:
| Field | Required | Rules |
|---|---|---|
name | Yes | 1 to 64 characters, lowercase letters, numbers and hyphens (rules below) |
description | Yes | 1 to 1,024 characters. What the skill does and when to use it |
license | No | A license name, or a reference to a license file bundled with the skill |
compatibility | No | 1 to 500 characters on environment needs: intended product, system packages, network access. Most skills don't need it |
metadata | No | A map of string keys to string values, for properties the spec doesn't define |
allowed-tools | No | A space-separated string of pre-approved tools. Experimental, and support varies between agents |
The name rules are strict. A valid name:
- uses only lowercase
a-z,0-9and hyphens - doesn't start or end with a hyphen
- doesn't contain two hyphens in a row
- matches the folder name
So content-gap-matrix passes, while Content-Gap-Matrix, -gap-matrix and content--gap fail. The spec's skills-ref tool checks them: skills-ref validate ./my-skill.
Claude Code treats every field as optional, but the spec and the skills CLI both require name and description, so write both. Claude Code also accepts fields of its own, such as disable-model-invocation: true, which means only you can start the skill. If you'll upload the skill to claude.ai or use it through the Skills API, stick to the six fields above: those paths reject any other field with an error.
Write a description that says when to use it
At startup, agents load only the name and description of every installed skill, about 100 tokens each. The full SKILL.md loads when a task matches, and the description is what the agent matches against. Give it two parts: what the skill does, and when to use it, in the words a user would type.
# Too vague to match a request
description: Helps with SEO.
# Says what it does and when to use it
description: Audits title tags and meta descriptions for length and duplicates. Use when the user asks to fix titles or write meta descriptions.
A few rules of thumb:
- Put the main use case first. Claude Code cuts each listing entry at 1,536 characters, and drops some descriptions when many skills are installed.
- Name the tools and tasks people mention, such as "Search Console", "losing traffic" or "refresh".
- If the skill fires too often, narrow the description. If it never fires, add the phrases users actually say.
Write the body instructions
Everything after the closing --- is the body. The spec sets no format but recommends step-by-step instructions, examples of inputs and outputs, and common edge cases. Four habits help:
- Keep it under 500 lines. The agent loads the whole file when the skill activates, and the spec suggests under 5,000 tokens.
- State what to do, not why. In Claude Code, a loaded skill stays in the conversation, so every line costs tokens on later turns.
- Write rules for the whole task. Claude Code doesn't re-read the file later, so "validate the schema after every edit" holds up better than "validate the schema".
- Put the important parts first. After Claude Code compacts a long conversation, it keeps only the first 5,000 tokens of each skill it re-attaches.
Scripts, references and assets
Agents load a skill in three stages: name and description at startup, the body when the skill activates, and other files only when a step needs them. So keep long material out of SKILL.md.
scripts/holds code the agent runs. Supported languages depend on the agent; Python, Bash and JavaScript are common. A script should be self-contained or document its dependencies, give helpful error messages, and handle edge cases.references/holds docs the agent reads on demand, such as a detailed API reference. Keep each file focused, since smaller files use less context.assets/holds static files: templates, images, and data files such as lookup tables and schemas.
Split content out when SKILL.md nears 500 lines, or when material such as a full API spec is needed only on some runs. Link each file from SKILL.md with a path relative to the skill folder, one level deep, and say what it contains and when to open it. In a skill used only in Claude Code, ${CLAUDE_SKILL_DIR} stands for the skill's own folder, so ${CLAUDE_SKILL_DIR}/scripts/<file> works from any directory.
A worked example: content-decay-predictor
Content Decay Predictor is one of the 65 skills we publish. It predicts which pages will keep losing Search Console clicks. Its folder:
content-decay-predictor/
SKILL.md
references/
output.schema.json
scripts/
decay.py
The frontmatter, as published:
---
name: Content Decay Predictor
description: Builds per-URL clicks and impressions time-series from Search Console, fits a trend to detect sustained decline and inflection points, and predicts which pages will keep decaying ranked by projected click loss. Use when the user asks which content to refresh, what pages are losing traffic, or wants a proactive content-refresh queue.
category: content
---
The description follows the pattern: what the skill does, then when to use it. Two lines don't follow the spec. The name has capitals and spaces; under the spec it would be content-decay-predictor, the same as the folder. And category is our own field, not a spec field: Claude Code ignores fields it doesn't recognize, but a claude.ai upload would reject it.
The body is a run of labeled sections: role, objective, inputs, authentication, tool calls, a numbered procedure, error handling, missing data and output. The inputs show how specific a body can get:
## INPUTS
- `site_url` (REQUIRED): verified GSC property.
- `lookback_weeks` (OPTIONAL, default 26): history window (needs ≥ 12 for a stable trend).
- `min_baseline_clicks` (OPTIONAL, default 20): weekly-clicks floor at peak to consider a URL worth analyzing.
- `horizon_weeks` (OPTIONAL, default 8): projection horizon.
The trend math lives in scripts/decay.py, which the body tells the agent to run. The output section asks for one JSON object matching references/output.schema.json, so the result has a defined shape, and a closing FILES section says what each file is for. The spec suggests assets/ for schemas, but its folder names are recommendations. To study the full folder, install it with npx skills add https://seoskills.sh --skill content-decay-predictor.
Test it, then get it listed on seoskills.sh
First, check that an agent picks the skill up. In Claude Code, ask something that matches the description and see whether Claude loads it, or start it with /skill-name. If it doesn't trigger, ask "What skills are available?" to confirm it loaded, then reword the description to match how you asked.
To get a skill listed here:
- Publish it in a public GitHub repository, as a folder with a SKILL.md.
- Make sure it's findable on skills.sh. Our daily sync searches skills.sh for SEO skills.
- On the next sync, it enters our review queue and stays hidden until someone reads and approves it for relevance to SEO, substance, and a static security scan. Off-topic, thin and duplicate skills are dropped.
npx skills add <owner>/<repo> --list shows whether the skills CLI finds your skills. Skill safety explains what the scan looks for. You can also open an issue on the catalog repo about your skill.