HomingoLearn
Agent skills · 7 min read

How to write a SKILL.md for Claude Code: structure, frontmatter and common mistakes

The difference between a skill Claude uses well and one it ignores is mostly in how SKILL.md is written. Here is a structure that works.

By Homingo Learn ·

A Claude Code skill is a folder with a SKILL.md inside, in ~/.claude/skills/<name>/ for you alone or .claude/skills/<name>/ for a whole repository. Claude sees each skill’s name and description (unless the skill turns automatic use off, see below), and reads the rest of SKILL.md only when it decides the skill fits the request or when you type /name. So the file has two jobs: get chosen at the right moment, then steer the work well. This guide covers both.

SKILL.md frontmatter fields

Frontmatter is YAML between --- lines at the top. Every field is optional, but write a description every time. The fields you will use most:

  • name: the command name, in lowercase letters, numbers and hyphens; defaults to the folder name.
  • description: what the skill does and when to use it. This is what Claude matches requests against.
  • when_to_use: extra trigger phrases or example requests, added to the description (and counted in its length).
  • argument-hint: an autocomplete hint such as [version]; whatever you type after /name replaces $ARGUMENTS wherever it appears in the body.
  • allowed-tools: tools Claude may use without asking while the skill runs, for example a specific script.
  • disable-model-invocation: true: Claude never picks the skill by itself (its description is left out of Claude’s context); it runs only when you type /name. Use it for anything with side effects, like a deploy. The opposite, user-invocable: false, hides it from the / menu so only Claude uses it.
---
name: changelog-entry
description: Write a CHANGELOG.md entry for the current branch from its commits and diff. Use when the user asks for a changelog entry, release notes for a branch, or "what changed".
allowed-tools:
  - Bash(git log *)
  - Bash(git diff *)
---

The top of SKILL.md. The body below goes in the same file, under this frontmatter.

Write the description like a request

  • Lead with the job, in the words a user would type: “Write a changelog entry”, not “Changelog utilities”.
  • Name the triggers: list the phrasings and file types that should bring the skill in.
  • Say what it is not for if it overlaps with another skill.
  • Keep it tight. The skill list truncates long descriptions, so the main use case goes first.

The SKILL.md body: an order of work with gates

The body is instructions Claude follows, so write it as steps, not as an essay. A structure that holds up:

# Changelog entry

## Steps
1. Find the base branch (`git symbolic-ref refs/remotes/origin/HEAD`, usually main),
   then run `git log --oneline main..HEAD` and `git diff --stat main...HEAD` against it.
2. Group the changes: Added, Changed, Fixed. Skip pure refactors and test-only commits.
3. Write one line per user-visible change, in the past tense, no commit hashes.
4. Save the draft to a temp file and run the checker that ships with this skill:
   `python ~/.claude/skills/changelog-entry/scripts/check_entry.py <file>`
   (in a project install: .claude/skills/changelog-entry/...). Fix every FAIL it prints.
5. Show the entry to the user before editing CHANGELOG.md.

## Rules
- Never invent a change that is not in the diff.
- If the branch has no user-visible change, say so instead of writing an entry.

## Reference
- House style: reference/style.md (read it before step 3).
- Good entries to imitate: reference/examples.md.
  • Numbered steps keep Claude from skipping ahead.
  • Gates with checkable rules (“show the entry before editing”) beat vague advice (“be careful”).
  • Pointers to reference files say when to read them, so they load only when needed.

Reference files and scripts

Keep SKILL.md short (the official guidance is under 500 lines) and move long material into files next to it: a style guide, a spec format, examples, a checklist. Deterministic checks belong in scripts that Claude runs rather than reads: a linter for your format, a QA script for output files. A script gives the same answer every time; an instruction is interpreted.

changelog-entry/
  SKILL.md            the steps and rules
  reference/
    style.md          house style, read at step 3
    examples.md       three good entries
  scripts/
    check_entry.py    fails on hashes, future tense, empty sections

Common mistakes

  • A vague description, so the skill is never chosen. Test it in a fresh session, so earlier conversation does not steer Claude, and ask in plain words; if Claude does not pick the skill, rewrite the description.
  • Everything in one file. A 1,000-line SKILL.md costs context every time it loads. Split it.
  • No stopping rules. Say when to stop and ask the user, and what never to do.
  • “Check the output” without saying how. Name the command and the pass condition, and tell Claude to read the output before reporting a pass.
  • Side effects with automatic invocation. Anything that deploys, sends or deletes should use disable-model-invocation: true.

For a worked example aimed at video, see Claude Code skills for video, which builds a reel QA skill step by step.