A Claude Skill is a folder Claude Code auto-loads when your prompt matches it. The anatomy is four parts: a folder named after the skill, a SKILL.md file with YAML frontmatter at the top, an optional scripts/ folder for deterministic code, and an optional references/ folder for docs the skill should pull in. Get the description field right and Claude invokes the skill on its own. Get it wrong and the skill sits on disk forever. I have built 40+ Claude Skills for my own operations and for client work at Formaum. Here is how I build one that actually fires.

What a Claude Skill is

A Skill is a folder of instructions Claude Code loads into context when it decides the skill is relevant to your prompt. It is the difference between pasting the same 200-line procedure into chat every time and just saying "run the audit." If you want the conceptual version, I wrote a separate post on what Claude Skills are and why they exist. This post is the build tutorial.

Skills live in one of two places. Personal skills go in ~/.claude/skills/ and follow you across every project. Project skills go in .claude/skills/ inside the repo and travel with the codebase. Claude scans both at startup. Use project skills for anything tied to a specific client or stack. Use personal skills for procedures you run across every project.

The anatomy of a working skill

Every skill is a folder. The folder name is the skill name. Inside the folder, four things matter:

The thing most tutorials skip: the body of SKILL.md does not load until the skill is invoked. The frontmatter loads on every prompt. That is the whole game. The description has to be tight because it is paying context rent every single turn. The body can be as long as it needs to be because it costs nothing until you use it.

Step 1: Name it like a verb-noun

The folder name becomes the slash command. /audit, /callsheet, /proposal. Verb-noun or short single-verb. Lowercase, hyphens for multi-word, no spaces.

Bad names: helper, my-skill, assistant. Good names: review-pr, generate-invoice, debug-build. The name is the first signal Claude uses to decide if the skill is relevant. "helper" matches nothing because it could mean anything.

Step 2: Write the description (this is the whole job)

The description field is the single most important thing in your skill. Claude reads the description of every available skill on every turn. If your description matches the user's intent, the skill loads. If it does not, the skill never runs. People spend hours on the body and 30 seconds on the description and then wonder why the skill never fires.

Three rules:

  1. Write it the way the user would ask for the task. If you would normally say "review this code," the description should contain the phrase "review code," not "perform a quality assessment of source files." Match the user's vocabulary, not your formal one.
  2. Include trigger phrases explicitly. List the actual phrases that should fire the skill. "Triggers on /audit, 'audit this client,' 'run an audit on [name]'." Claude pattern-matches on these.
  3. Stay under 200 characters when you can. The description is read every turn. Long descriptions cost context for no benefit. Tight and specific beats long and abstract.

Here is the frontmatter pattern I use:

---
name: audit
description: Generate problem-first workflow audits for client engagements. Creates styled HTML deliverables with SVG flow diagrams, gap analysis, and prioritised recommendations. Triggers on /audit, "audit [client]", "run an audit on [name]".
---

That is it. Two fields. The body comes after.

Step 3: Structure the body (when to use, how to use, examples)

The body is markdown. Claude reads it top to bottom when the skill fires. The structure that has worked across every skill I have shipped:

  1. When to use this skill . one paragraph. Restate the trigger conditions. This is for Claude, not for you.
  2. Inputs . what the skill needs from the user before it can run. Client name, file path, target metric. List them.
  3. Procedure . numbered steps. Treat Claude like a new hire who has done this exact task once. Be specific. "Read the file at X. Extract the sections matching pattern Y. Write the output to Z."
  4. Output format . what the deliverable looks like and where it goes. Include the file path, the markdown structure, and any naming convention.
  5. Examples . one or two real (anonymized) runs. Examples beat instructions for steering output quality.
  6. References . links to references/ files the skill should load only when needed. Voice rules, API docs, client-specific patterns.

Step 4: Test in actual conversation

Save the file, restart Claude Code, and trigger it three ways:

  1. Explicit invocation. Type /your-skill-name and confirm it loads. If it fails here, the file is malformed.
  2. Trigger phrase. Use one of the phrases from your description in a normal message. The skill should auto-invoke. If it does not, the description is too vague.
  3. Negative test. Say something the skill should NOT match. If it fires anyway, your description is too broad and it will steal context from other skills.

Iterate on the description. Not the body. 90% of "my skill is not loading" problems are description problems.

A real skill walkthrough

Here is the skeleton of a comms-check skill I run before sending any client-facing message. It catches voice drift, banned phrases, and tone mismatches in under 10 seconds. I am showing the structure, not the full file.

~/.claude/skills/comms-check/
├── SKILL.md
├── references/
│   ├── voice-rules.md
│   ├── banned-phrases.md
│   └── approved-examples.md
└── scripts/
    └── score.py

And the top of SKILL.md:

---
name: comms-check
description: Review any client-facing message for voice, banned phrases, and tone before sending. Triggers on /comms-check, "comms check this", "review before I send", "is this on-brand".
---

# Comms Check

## When to use
Fire whenever a draft message is about to go to a client, a prospect, or a public surface (LinkedIn, Upwork, email). Skip for internal-only notes.

## Inputs
- The draft message (pasted or referenced by file path)
- Recipient context (client name, channel, stage of relationship)

## Procedure
1. Read references/voice-rules.md
2. Read references/banned-phrases.md
3. Score the draft on 5 axes: factual accuracy, voice match, banned-phrase hits, tone, length
4. Run scripts/score.py to produce the numeric summary
5. Return the score, a one-line verdict, and a revised draft if any axis scores under 4

## Output format
- Score table (5 rows, 1–5 each)
- Verdict line ("send," "revise," or "rewrite")
- Revised draft (only if needed)

## Examples
[two anonymized before/after samples]

Why this works. The description names the exact phrases I actually use. The body tells Claude what to load and when. The references are heavy (the voice guide is 2,000 lines) but they do not cost context until the skill runs. The script handles the deterministic scoring so Claude is not improvising numbers. The whole thing fires reliably because every piece earns its place.

Common mistakes

The skill that works is not the longest one. It is the one with the tightest description, the cleanest procedure, and the examples Claude can pattern-match against. Write the description like a job posting. Write the body like an SOP for a new hire. Move everything else to references and scripts. Then test it in a real conversation before you trust it.

Run on a stack that's holding you back?

Book a 45-minute discovery call. I'll map what moves, what stays, and what makes sense for your operation.

Book a call

Frequently Asked Questions

Where do I put a Claude Code skill so it actually loads?
Two locations. Personal skills go in ~/.claude/skills/your-skill-name/SKILL.md and follow you across every project. Project skills go in .claude/skills/your-skill-name/SKILL.md inside the repo and travel with the codebase. Claude scans both at startup. Restart Claude Code after creating the folder so it picks the new skill up.
Why is my Claude skill not auto-invoking when I ask for it?
The description field is too vague or does not match the phrases you actually use. Claude reads the description of every skill on every turn and pattern-matches it against your prompt. Rewrite the description in the user's vocabulary, include 3 to 5 explicit trigger phrases, and keep it under 200 characters. 90% of auto-invoke failures are description problems, not body problems.
What is the difference between a Claude Skill and a slash command?
They are the same thing now. Anthropic merged custom commands 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. Skills add optional features: supporting files in scripts/ and references/, YAML frontmatter for invocation control, and auto-loading when relevant. Use the skill folder structure for anything you want Claude to invoke without a slash.
How long should a SKILL.md file be?
As short as it can be without losing the procedure. The frontmatter description should be under 200 characters because it is read every turn. The body can be longer because it only loads when the skill fires, but most working skills land between 50 and 300 lines. If your body is over 500 lines, move the heavy content into references/ files that the body loads on demand.
Do I need scripts/ and references/ folders for every Claude skill?
No. The minimum viable skill is a folder with one SKILL.md file. Add scripts/ when you need deterministic processing the model should not improvise (math, file generation, API calls with strict shapes). Add references/ when the skill needs long context the body should pull in selectively. Most of my best skills are SKILL.md plus one or two references. Scripts are for the cases where wrong output is worse than no output.
Genevieve Claire
Genevieve Claire
Founder, Formaum — Claude Code Expert & Full-Stack AI Engineer

Builds bespoke AI automation systems for multi-location operations. Previously EA Sports FIFA ($7B franchise) and Film/TV VFX on Skyfall, Avengers, Game of Thrones. Based in Vancouver, BC.