Press ESC to exit fullscreen
📖 Lesson ⏱️ 90 minutes

Creating Your First Skill

Hands-on: write, install, and trigger a working skill in a real agent client

What You’ll Build

A skill that gives an agent the ability to roll dice using a random number generator — small enough to build in one sitting, complete enough to demonstrate every part of the format working together. You’ll build it once, then extend it, so you experience the full skill lifecycle rather than just reading about it.

This walkthrough uses Claude Code, but nothing about it is Claude-specific — the same SKILL.md works unmodified in any compatible client, which is the entire point of an open format. If you’re using a different client (VS Code with Copilot, Cursor, etc.), the file goes in that client’s skills directory instead; only the location changes.

Step 1: Create the Folder

A skill is a directory named after the skill, containing SKILL.md. Claude Code looks for personal skills in ~/.claude/skills/ and project skills in .claude/skills/ at your project root (project skills take precedence when both exist and are committed alongside your code, so teammates get them automatically). For this exercise, create a project skill:

mkdir -p .claude/skills/roll-dice

Step 2: Write SKILL.md

---
name: roll-dice
description: Roll dice using a random number generator. Use when asked to roll a die (d6, d20, etc.), roll dice, or generate a random dice roll.
---

To roll a die, use the following command that generates a random number from 1
to the given number of sides:

\`\`\`bash
echo $((RANDOM % <sides> + 1))
\`\`\`

Replace `<sides>` with the number of sides on the die (e.g., 6 for a standard
die, 20 for a d20).

Save that as .claude/skills/roll-dice/SKILL.md. That’s the entire skill — one file, under 20 lines. Walk through what each part is doing before you run it:

  • name — matches the folder name (roll-dice), lowercase with hyphens, as required by the spec.
  • description — this is the only thing the agent reads at startup. Notice it names the trigger conditions explicitly (“d6, d20”, “roll dice”, “random dice roll”) rather than just saying “handles dice.”
  • The body — a single, concrete instruction: generate a random number in a range, substituting the number of sides from whatever the user asked for.

Step 3: Try It Out

  1. Open your project in Claude Code (or your client of choice).
  2. Confirm the skill is discovered — in Claude Code, ask what skills are available, or check that roll-dice is listed among active skills.
  3. Ask: “Roll a d20.”
  4. The agent should activate roll-dice, run the shell command with sides substituted as 20, and return a number between 1 and 20. It may ask permission to run a terminal command first — that’s expected; allow it.

If the agent answers with a number but doesn’t run a command, it didn’t actually use the skill — it just guessed. Tool-use reliability varies by model; if this happens consistently, double-check the file path (.claude/skills/roll-dice/SKILL.md, not .claude/roll-dice/SKILL.md or similar) and confirm the name field exactly matches the folder name.

Step 4: Watch What Actually Happened

This is the part worth pausing on, because it’s the progressive disclosure model from the first lesson, observed rather than described:

  1. Discovery — when your session started, the agent scanned .claude/skills/ and read only roll-dice’s name and description. It did this whether or not you ever mentioned dice.
  2. Activation — your message “Roll a d20” matched the description’s stated trigger conditions, so the agent loaded the full SKILL.md body into context.
  3. Execution — the agent followed the instructions, substituting 20 for <sides> in the command, ran it, and used the result to answer you.

If your client exposes verbose or debug output, look for a moment where it logs having read roll-dice/SKILL.md — that’s activation happening in real time.

Step 5: Break It on Purpose

Understanding failure modes early saves you far more time than reading about them. Try each of these and see what changes:

Rename the folder without updating name. Rename roll-dice/ to dice-roller/ but leave name: roll-dice in the frontmatter. Many clients will now refuse to load the skill, or load it inconsistently — the spec requires name to match the directory, and this is exactly the kind of mismatch skills-ref validate (from the previous lesson) is built to catch.

Weaken the description. Change it to description: Helps with dice. and ask “Roll a d20” again. Depending on the client and model, the skill may still trigger (the word “dice” survives) or it may not, especially on a more oblique prompt like “I need a random number between 1 and 20 for a game.” A vague description costs you exactly the cases where the skill would have been most useful — asks that don’t spell out the domain explicitly.

Ask something adjacent but out of scope. Try “flip a coin.” A well-scoped roll-dice skill shouldn’t claim this — coin flips aren’t dice. Deciding exactly where a skill’s scope should end is a deeper design question than this course goes into — it’s a core topic of the next course in this path, Production Agent Skills Engineering.

Undo your changes back to the original before moving on.

Step 6: Extend It Slightly

Add a second instruction to the body so the skill handles a follow-up case — rolling multiple dice at once:

To roll multiple dice of the same type, repeat the command once per die and
sum the results, or report each roll individually if the user asks to see
them separately.

Ask “Roll three d6 and give me the total.” Confirm the agent handles it without you touching the frontmatter — the description didn’t need to change because “roll dice” already covers this case; only the body needed the added instruction.

What You Just Practiced

Every skill you’ll ever write follows this same loop: write a minimal SKILL.md, run it against a real request, watch whether activation and execution behave as intended, then adjust. The dice skill is trivial by design — the value here is having seen discovery, activation, and execution happen, and having deliberately broken each part to feel what failure looks like, before you build something that matters.

Summary

  • A skill needs only a folder and a SKILL.md file to be fully functional
  • Claude Code discovers project skills from .claude/skills/ and personal skills from ~/.claude/skills/
  • You can observe discovery, activation, and execution directly by watching how and when the agent reads and acts on the file
  • A mismatched name, a vague description, or an out-of-scope request are the three fastest ways to see a skill fail — and the fastest way to learn what each part of the format is actually for

Next, you’ll zoom out from a single skill to how an agent finds any of its installed skills — personal, project, and plugin locations, and what happens when more than one skill could plausibly apply.