CCLearn

Skills, and what happened to custom commands

verified against Claude Code 2.1.261 · 2026-09-0914 min

By the end you can

  • Name the three triggers that mean a prompt should become a skill
  • Create a minimal working skill and say where its command name comes from
  • State what a skill costs in context that a CLAUDE.md rule does not
  • Explain why .claude/commands/ files still work and what skills add over them
  • Prove a skill loaded using /skills and /context rather than assuming it did
  • Tell a skill that triggered from a skill that worked, and run the baseline comparison that settles it

You have a paragraph you keep retyping — the six steps for cutting a release, or "check the migration is reversible, then the index, then the rollback note". You have pasted it into three sessions this week, each time slightly differently, and each time the result was slightly different too.

Lesson 5.3 showed you one of these without naming it: the recipe /run-skill-generator writes to .claude/skills/run-<name>/ so every future session and every teammate launches the app the same way. That is a skill.

The third time you paste it

The docs give three separate triggers, and they are worth reading as three:

What you noticeWhat to do about it
You paste the same playbook or multi-step procedure into chat for the third timeCapture it as a skill
You keep typing the same prompt to start a taskSave it as a user-invocable skill
A CLAUDE.md section has grown into a procedure rather than a factMove it into a skill

The first two come from the adoption table in Features overview; the third from the opening of Skills, which pairs it with the pasting trigger in one sentence.

That third one is the one people miss. A CLAUDE.md line like "we use conventional commits" is a fact: short, always relevant, cheap to keep loaded. A CLAUDE.md section that says "first run the schema check, then regenerate types, then…" is a procedure that happens to be sitting in a file that loads on every single turn, whether today's task involves migrations or not.

What a skill is on disk

Two things: a directory, and a SKILL.md inside it.

bash
mkdir -p ~/.claude/skills/release-notes
yaml
---
description: Drafts release notes from commits since the last tag. Use when the user asks for release notes, a changelog entry, or what shipped since the last release.
---

1. Find the most recent tag and list the commits since it.
2. Group them into Added, Fixed, and Changed. Drop pure chores.
3. Write one line per entry, in the past tense, naming user-visible behaviour
   rather than the files that changed, and flag breaking changes separately.

Save that as ~/.claude/skills/release-notes/SKILL.md and you can type /release-notes. Where did that name come from? Not from anything in the file:

The directory name becomes the command you type, and the description helps Claude decide when to load the skill automatically. — Skills

So the command name is the folder, which is the whole of this lesson's trap.

The two halves do different jobs. The frontmatter between --- markers tells Claude when to use the skill — Lesson 7.2's whole subject. The markdown below is what Claude follows when it runs, written the way you would write it for a competent colleague who has not done this task before.

Custom commands did not go away — they became skills

If you have used Claude Code for a while, you have a .claude/commands/ directory. There is nothing you need to do to it:

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. Your existing .claude/commands/ files keep working. — Skills

Same command, same behaviour, two layouts. The commands reference is blunt about which is current: "To add your own commands, see skills" (Commands). What the newer layout buys is a short list:

.claude/commands/deploy.md.claude/skills/deploy/SKILL.md
Creates /deployYesYes
Invoked by its file or directory nameFile nameDirectory name
FrontmatterSame fields, except name and pathsAll fields
Supporting files alongside itNoYes — a whole directory
Claude can load it automatically when relevantNoYes

The docs' own recommendation follows: "Prefer a skill for new work, since skills also support supporting files" (Skills). A command file that works today is not a bug to fix; a new procedure you are about to write is a skill.

Skill, CLAUDE.md, or rule

CLAUDE.md, and any .claude/rules/ file without a paths field, hold instructions that are in the window whether or not this task needs them. A skill holds instructions that are not, and the difference is a cost rather than a preference:

Rules load into context every session or when matching files are opened. For task-specific instructions that don't need to be in context all the time, use skills instead, which only load when you invoke them or when Claude determines they're relevant to your prompt. — Memory

Read that against Lesson 3.1's startup table, whose representative figures put CLAUDE.md at 1,800 tokens and every skill description in the session at 450 between them. A CLAUDE.md file is charged whole at turn one; a skill is charged for its name and description at turn one and for the rest of it later, if ever:

Unlike CLAUDE.md content, a skill's body loads only when it's used, so long reference material costs almost nothing until you need it. — Skills

"Almost nothing" is not nothing, and that is the honest version of the trade. Every skill adds its name and description to a listing that is in context on every turn, "whether or not Claude ever uses it" — ten skills you never invoke are ten descriptions you pay for all session. And once a skill is invoked, its body does not politely leave again; Lesson 7.5 is about that bill.

The decision, then, is not "which is better": a fact true of every task in the repo is CLAUDE.md, a fact true only of some files is a rule with paths, a procedure you run sometimes is a skill — and something that must happen every time regardless of what Claude decides is none of these. That is a hook or a permission rule, because none of the three instruction files is enforcement — Lesson 6.2 draws that line and names the mechanisms that give you a guarantee.

Bundled skills, and what your own file does to one

You have been invoking skills since Level 5 without writing one. /code-review, /debug, /loop, /batch and /claude-api are bundled skills:

Bundled skills are prompt-based: they give Claude detailed instructions and let it orchestrate the work using its tools. Most built-in commands instead execute fixed logic directly. — Skills

So /code-review is not behaviour coded into the CLI, which is what most built-in commands are. It is a file of instructions handed to Claude, exactly like the one you just wrote — which is why the commands reference marks those entries Skill in its Purpose column.

/doctor joined that list late. It became a bundled skill in v2.1.205; before that it was a built-in command that opened a read-only diagnostics screen.

The consequence: a skill of yours with a bundled skill's name replaces the bundled command, but not its aliases — a project code-review skill replaces /code-review, while /review, which is an alias of it, goes on running the bundled one. Lesson 7.6 takes that collision apart; for now, treat reusing a name that already exists as a decision rather than an accident.

Proving it loaded

You have written a file. You have not yet established that Claude Code read it. Two commands, and they do not report the same thing:

CommandWhat it shows
/skillsAvailable skills from project, user, and plugin sources. Type to filter by name, description or source; press t to sort by token count
/contextEverything occupying the window, broken down by category — including the skills section

They are not interchangeable: "The skills section in /context also includes bundled skills, which /skills doesn't list" (Debug your configuration). So /skills answers "did my file load" and /context answers "what am I paying for".

A third state looks like failure and is not: a skill can appear in /skills and still never fire on its own, because its frontmatter forbids that or because its description does not match how you phrase requests. The badge tells you which — a "user-only" label means Claude will not trigger it. That is Lesson 7.2.

The check that is not a check

One sentence deserves to end this lesson, because it is Level 5's argument in new clothes:

Seeing a skill trigger tells you Claude found it, not that it did what you intended. — Skills

The documented way to know is a baseline comparison: collect a few realistic prompts, run each in a fresh session with the skill available and again with it disabled, and compare. Freshness is the load-bearing part — "leftover context from authoring the skill will mask gaps in the written instructions". You spent twenty minutes explaining the procedure while writing the file, so of course it performs well in that session. It has the explanation. Your teammate, tomorrow, has only the file.

Checkpoint

  1. You have a CLAUDE.md section headed "Releasing" with eight numbered steps. Name two costs of leaving it there, and say what you would keep in CLAUDE.md after moving it.

    Show answer

    First cost: all eight steps are in the window on every single turn, whether or not today's task is a release. CLAUDE.md is charged whole at turn one — the startup table's representative figure is 1,800 tokens — while a skill is charged for its name and description at turn one and for the body only when it is used. Second cost: you get none of what the skill layout buys. There is no /releasing you can type, nowhere to put supporting files, and no description for Claude to match a request against.

    Keep the facts, move the procedure. A line that is true of every task in the repo — "we use conventional commits" — belongs in CLAUDE.md; the ordered steps are a procedure you run sometimes, which is the third documented trigger for making a skill. If part of the section is only true of certain files, that part is a rule with paths, not CLAUDE.md either.

  2. A colleague says "the skill just doesn't work — /deploy isn't even a command". What is the first thing you ask to see, and what are you expecting to find?

    Show answer

    Ask for /skills, and expect the skill to be missing from it. That absence is the documented symptom "Skill doesn't appear in /skills", and the listed fix is the layout: a folder with SKILL.md inside, .claude/skills/name/SKILL.md — so what you are looking for on disk is a flat .claude/skills/deploy.md, or a directory named something other than deploy, since the directory name is what becomes the command you type.

    The trap is that the symptom is an absence, so the conclusion available to your colleague is "skills do not work" rather than "my layout is wrong". A perfect description does not rescue a wrong folder name, because the command name comes from nothing inside the file.

  3. You wrote a skill, invoked it in the same session, and it did exactly what you wanted. What have you established, and what would you have to do to establish the thing you actually care about?

    Show answer

    You have established that Claude found the skill, and nothing more: "Seeing a skill trigger tells you Claude found it, not that it did what you intended." What you care about is whether the written instructions carry the procedure on their own, and that session cannot tell you — you spent twenty minutes explaining the procedure while writing the file, so the session has the explanation as well as the file.

    The documented way to settle it is a baseline comparison: collect a few realistic prompts, run each in a fresh session with the skill available and again with it disabled, then compare. Freshness is the load-bearing part, because "leftover context from authoring the skill will mask gaps in the written instructions". Your teammate tomorrow has only the file.

  4. /skills lists a skill you have never seen fire on its own. Give two different explanations, and say which command would distinguish them.

    Show answer

    Either its frontmatter forbids automatic invocation, or its description does not match the way you actually phrase requests. Both are consistent with what you see, and neither is a loading failure — the skill is listed, so the file was read.

    /skills itself separates them: the badge tells you which, and a "user-only" label means Claude will not trigger it. No such label and the frontmatter permits automatic loading, which leaves the description as the suspect. That is Lesson 7.2's subject.

Sources