Skip to main content
Claude Code tips · Lesson 3 of 6 · 10 min

Claude Code Skills Examples: Write One That Actually Triggers

Claude Code skills examples from a real repo: SKILL.md frontmatter, why the description decides triggering, what loads when, and skills vs CLAUDE.md.

By Matthews WongReviewed on Checked against Claude Code v2.1.296

Key takeaway

A Claude Code skill is a folder with a SKILL.md file: YAML frontmatter whose description tells Claude when to use it, then the instructions. Only the description sits in context until the skill is used, so the description decides whether it triggers, and a long procedure costs almost nothing until it is needed.

You will be able to

  • Write a SKILL.md whose description names the words a real request will contain.
  • Predict what a skill costs in context before and after it is used.
  • Choose between CLAUDE.md, a skill and a manual-only command for a given rule.
Watch it work

Step through the diagram

Press Play, or step with the arrows. Every step is written out below the diagram.

How a skill loads: description first, body on demand

Each skill puts only its description into Claude's context at session start; a matching request, a typed /name or a hook report loads the full body, which then stays in the conversation.

Reviewed on 13 October 2026 · Claude Code v2.1.296

Step 1 of 6. A skill is a SKILL.md file: frontmatter whose description says when to use it, then the instructions. Everything Claude reads shares one context window.

Keys: ← → step · Home / End · K play or pause

  1. A skill is a SKILL.md file: frontmatter whose description says when to use it, then the instructions. Everything Claude reads shares one context window.

  2. At session start, CLAUDE.md loads in full, but each of the four skills adds only its description to a short listing. The bodies stay on disk.

    name: drawing-blog-diagrams description: Draw in-article explanatory diagrams for blog posts …
  3. You ask for a diagram. Claude compares the request with every description in the listing; this one says “Use when adding a diagram”, so it matches.

    Use when adding a diagram, figure, illustration or in-article image to a blog postPredict the next step The description matched. What enters the context now? (The skill's full body · Nothing more: the description is enough · Every skill's body at once)
  4. Only now does Claude Code load the full body into the conversation. It stays there for the session and is not re-read, so write standing instructions.

  5. You can also type /drawing-blog-diagrams. Custom commands have been merged into skills: a file in .claude/commands/ and a skill folder both create a slash command.

    .claude/commands/deploy.md → /deploy .claude/skills/deploy/SKILL.md → /deployPredict the next step The figure hook reports subject-absent. What happens next? (Nothing: only your requests trigger skills · The diagram skill gets pulled in)
  6. This repo's figure hook reports codes such as subject-absent. The diagram skill lists those exact codes in its description, so a hook report pulls in the right skill.

    and when the figure-fitness hook reports subject-absent, subject-distant, own-work-preferred, caption-restates-alt, alt-prefix, overused-figure or portrait-figure.

What is a Claude Code skill, and what goes in SKILL.md?

A skill is a folder with a SKILL.md file in it. The file has two parts: YAML frontmatter between --- markers, then Markdown instructions. Project skills live in .claude/skills/ inside the repository and reach everyone who clones it; personal skills live in your home folder and follow you across projects. The folder name, or a name field, becomes the command you can type, such as /drawing-blog-diagrams.

Read more (2)

Every frontmatter field is optional, but description is the one the docs recommend, because Claude uses it to decide when to apply the skill. Other fields decide who may invoke it (disable-model-invocation, user-invocable), which tools are pre-approved for the turn that invokes it (allowed-tools) and which files activate it (paths). Claude Code ignores a field it doesn't recognise without reporting an error, so a misspelt field quietly does nothing.

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 command files keep working. A skill adds a folder for supporting files, control over who invokes it, and the ability for Claude to load it on its own, so the docs suggest skills for new work. This repository never had a .claude/commands/ folder; it went straight to skills.

Why does the description decide whether a skill triggers?

At session start Claude Code puts a listing of skill names and descriptions into context, not the bodies. Claude matches your request against that listing, so if the description doesn't contain the words your request will use, the skill never loads, however good its instructions are. The docs' first check for a skill that won't trigger is whether its description includes the keywords people would naturally say.

Read more (2)

Two limits shape how you write it. The description, plus the optional when_to_use text, is cut at 1,536 characters in the listing, so put the key use case first. And when you have many skills, Claude Code drops descriptions to fit a listing budget of about 1% of the context window, starting with the skills you invoke least.

This repository's four descriptions are written as trigger lists. They name the files, scripts and terms a request will contain: BLOG_FIGURES, scripts/generate-blog-diagram.mjs, merge-blog-staging, JSON-LD. Each runs to roughly 500 to 800 characters, well under the cap, and each body stays well under the 500 lines the docs suggest as a ceiling for SKILL.md.

When should a rule be a skill rather than CLAUDE.md?

CLAUDE.md loads in full at the start of every session and is paid for on every request. A skill costs only its description until it is used, then its body enters the conversation. The docs' split: put "always do X" rules in CLAUDE.md, and put reference material Claude needs only sometimes, or a workflow you trigger by name, in a skill. Their rule of thumb is to keep CLAUDE.md under 200 lines; this repo's file is well past that, and its long blog procedures are the obvious candidates to move into the skills it already has.

Read more (2)

Once a skill loads, it stays. Its content enters the conversation as one message and Claude Code does not re-read the file on later turns, so write standing instructions, such as "run the tests after every edit", rather than one-time steps. After compaction, Claude Code re-attaches each invoked skill but keeps only its first 5,000 tokens, within 25,000 tokens for all skills together, so put the critical rules at the top.

A skill is still guidance that Claude applies with judgement. For a rule that must hold every time, the skills page itself says to move it into a hook, which runs on its event whether or not Claude is following the skill. That is the next lesson.

How this site does it

The real config behind this lesson

Excerpts from the repository that builds and deploys this website, quoted as they are.

.claude/skills/drawing-blog-diagrams/SKILL.md:1-4
---
name: drawing-blog-diagrams
description: Draw in-article explanatory diagrams for blog posts in this site's visual language instead of sourcing them. Use when adding a diagram, figure, illustration or in-article image to a blog post; when a borrowed diagram has foreign-language labels or is unreadable on the dark page; when working with scripts/generate-blog-diagram.mjs, BLOG_FIGURES, lib/blog-figures.ts, BlogFigure, the stack or columns layout, scripts/audit-blog-figures.mjs or scripts/review-blog-figures.mjs; and when the figure-fitness hook reports subject-absent, subject-distant, own-work-preferred, caption-restates-alt, alt-prefix, overused-figure or portrait-figure. Covers the palette, layout primitives, label writing rules, wiring a figure into a post bilingually, the audit gate and the fitness review.
---

The whole frontmatter of this repo's diagram skill: just name and description. The description is a trigger list. It opens with the use case, then names the scripts, the registry and the component a request will mention, and it ends with the exact finding codes the figure hook prints, so a hook report and the skill share the same words.

.claude/skills/publishing-blog-posts/SKILL.md:8-19
## Purpose

A published post is **six files that must agree**. Editing them by hand works
once and drifts by the third post, and the failure is silent — a missing key
breaks one locale of one page in production, which survives for months.

So nothing is hand-edited: content is staged, one script validates it
completely, and only then is anything written. This skill is that process and
the ways it has gone wrong.

For what to _write_, see **`writing-blog-content`**. For figures, see
**`drawing-blog-diagrams`**.

The body opens with why the procedure exists, then hands off: what to write lives in one skill, figures in another. Small skills that point at each other let a task load only the part it needs, instead of one long file loading everything at once.

What breaks

Mistakes that cost real time

  • A vague description

    "Helps with blog posts" matches everything and nothing. If descriptions are vague or overlap, the docs warn that Claude may load the wrong skill or miss the one that would help. Name the files, commands and phrases a request will actually contain.

  • Broken YAML that fails quietly

    If the frontmatter doesn't parse, or the opening --- isn't the file's first line, your fields don't apply: /name still works, but Claude can't match against your description. Run claude plugin validate .claude/skills, or start with --debug to see the parse error.

  • Too many skills, descriptions dropped

    The listing has a budget. When it overflows, Claude Code keeps every name but drops descriptions, least-used skills first, which removes the very keywords that trigger them. Run /doctor for the listing's cost, and /skills, then t, to sort skills by token count.

  • What I'd change here: the hook codes have drifted

    The diagram skill's description lists seven finding codes, but scripts/review-blog-figures.mjs can now also report missing-translation and audit. A hook report carrying only those two no longer matches the description. A trigger list copied from a script has to be updated whenever the script grows a new code.

Who can invoke a skill, and what it costs before anyone does
(default)YesYesThe description
disable-model-invocation: trueYesNoNothing
user-invocable: falseNoYesThe description
Try it yourself

Do it on your own machine

You need Claude Code and any git repository. Make one skill that loads on its own, watch it trigger, then turn it into a manual-only command.

  1. Create .claude/skills/summarize-changes/SKILL.md. The description says what it does, then lists the words a real request will use.

    ---
    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.
  2. Edit any file, start Claude Code and ask in plain words. The skill should load without you naming it. Then call it directly by typing its name.

    claude
    > What did I change?
    > /summarize-changes
  3. Add disable-model-invocation: true to the frontmatter, start a new session and ask in plain words again. Claude no longer loads it; only /summarize-changes does.

    ---
    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.
    disable-model-invocation: true
    ---
  4. Open /skills and press t to sort by token count, then run /context and find the Skills row. Compare it before and after the change.

    /skills
    /context
Quick quiz

Three questions before you move on

Pick an answer to see why it is right or wrong. Nothing is saved or graded, so guess freely.

  1. 1.Your skill's description says "Helps with blog posts". You ask Claude to add a figure to a post, and the skill never loads. What fixes it?
  2. 2.Your project has dozens of skills. A rarely used one stopped loading on its own, though typing its /name still works. What is the likely cause?
  3. 3.A long skill keeps its most important rule at the very end. After compaction, Claude stops following that rule. Why?
Think it through

Answer in your head, then check

  1. 1.Your skill has excellent instructions, but Claude never uses it unless you type its name. What do you check first?Show the answer

    Answer:The description. Claude matches requests against the descriptions in the listing, so it must contain the words people actually say. Then check that the frontmatter parses: broken YAML loads the skill with empty metadata, so Claude can't match your description.

  2. 2.What part of a default skill is in context before anyone uses it?Show the answer

    Answer:Its name and description, plus when_to_use if set, capped at 1,536 characters. The body loads only when you or Claude invoke the skill, and then it stays in the conversation.

  3. 3.A deploy procedure must never run just because Claude decided the code looks ready. How do you set that up?Show the answer

    Answer:Make it a skill with disable-model-invocation: true. Only typing /deploy runs it, Claude Code blocks Claude's own attempts to invoke it, and its description stays out of context until then.

Go deeper

Related deep dives on this site