The course, and what it is really about
Introduction to agent skills is Anthropic's free, self-paced course on Claude Code skills. Six lessons, no stated prerequisites, and completion certificates for people who finish. The lesson titles below are the course's own.
| # | Lesson | What it actually teaches |
|---|---|---|
| 1 | What are skills? | The shape of a skill, and when a skill beats CLAUDE.md |
| 2 | Creating your first skill | Frontmatter, matching, and name collisions |
| 3 | Configuration and multi-file skills | Metadata fields and progressive disclosure |
| 4 | Skills vs. other Claude Code features | Picking between CLAUDE.md, hooks, subagents and MCP |
| 5 | Sharing skills | Git, plugins, marketplaces, enterprise settings |
| 6 | Troubleshooting skills | Why a skill does not fire, and what to check first |
Here is the part the course does not lead with, and the reason this is worth your evening. Agent Skills is no longer a Claude Code feature. Anthropic released the format as an open standard, and it has been picked up across the industry: GitHub Copilot, VS Code, Cursor, OpenAI Codex, Gemini CLI, Amp, Goose, OpenCode, JetBrains Junie and roughly forty others now read the same SKILL.md.
For a QA team that matters more than it does for most people. Your regression checklist, your bug-report format, your definition of a good Playwright locator: write that once as a skill and it applies in whichever agent your developers happen to be using. You are not writing Claude Code configuration. You are writing a portable document that agents agree to read.
What a skill is, and the problem it solves
The pain point is repetition. If you have explained your bug-report format to Claude three times this week, you have found a skill. The rule of thumb from the course is exactly that: anything you have explained three times is a candidate.
A skill is a folder. Inside it, a file called SKILL.md that opens with YAML frontmatter and continues with ordinary Markdown. The frontmatter decides when Claude reaches for the skill. The body decides what happens when it does.
Two details in that picture earn their place. First, the folder name is what you type: a skill at .claude/skills/flaky-triage/ is invoked as /flaky-triage. Second, SKILL.md is that exact spelling, uppercase name and lowercase extension, and it must sit inside the named folder rather than loose at the skills root. Both are common first-attempt mistakes.
Custom slash commands and skills have merged. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both give you /deploy. Existing command files keep working. Skills add the folder for supporting files, richer frontmatter, and automatic loading when Claude judges them relevant.
What sits in context, and what does not
This is the single idea the rest of the course rests on, and the one most people get half right.
At startup the agent loads a listing of every available skill: names and descriptions only. That listing is cheap. When your request semantically matches one of those descriptions, the full SKILL.md body is read into the conversation.
The consequence is the thing to remember. The quality of the skill body has no bearing on whether the skill fires. Claude has not read it yet. Only the description is in the room when the decision is made. A brilliant 400-line checklist behind a description that says "helps with testing" will sit there unused all week.
It is also why skills scale where CLAUDE.md does not. A twentieth skill costs one more line in the listing. A twentieth section of CLAUDE.md costs its full length in every conversation you ever have, including the ones about something else entirely.
Once invoked, the rendered skill content stays in the conversation across later turns, and Claude Code does not re-read the file. Write guidance that should hold for a whole task as standing instructions, not as one-time steps.
The description is the entire trigger
Given the section above, the description is the highest-leverage line in the file, and it is worth more attention than the body on a first draft.
A good description answers two questions: what does this do, and when should it be used. Write the second half in the words you actually type, not the words you would use in documentation.
description: Helps with docs.
That tells the agent as little as it would tell a new hire. Compare:
description: Writes pull request descriptions in the team format.
Use when creating a PR, writing a PR, summarising changes on a
branch, or when asked what changed since main.
Four phrasings, because you will not use the same one twice. Matching is semantic rather than keyword-based, so intent overlap is enough. But breadth still helps: every phrasing you add is another way in.
Two failure modes, and their fixes:
- The skill never fires. Test your own variations. "Why is this slow", "profile this", "make this faster" should all reach a performance skill. Any variation that misses is a phrase to add.
- The wrong skill fires. Two descriptions overlap. Make them distinct rather than merely accurate.
frontend-reviewandapi-reviewbeat two skills that both say "reviews code".
Where skills live, and who wins a name clash
Where you put the folder decides who gets it.
| Level | Path | Reaches |
|---|---|---|
| Enterprise | Managed settings | Everyone in the organisation |
| Personal | ~/.claude/skills/<name>/SKILL.md | All your projects |
| Project | .claude/skills/<name>/SKILL.md | This repository, everyone who clones it |
| Plugin | <plugin>/skills/<name>/SKILL.md | Wherever the plugin is enabled |
On Windows the personal path is C:/Users/<you>/.claude/skills. Use forward slashes in skill content regardless of platform.
When two skills share a name, enterprise beats personal, and personal beats project. Read that middle one twice, because it is the useful one: cloning a repository cannot quietly replace a convention you set for yourself. Plugin skills sit outside the contest entirely, namespaced as plugin-name:skill-name, so they load alongside rather than fighting for the bare name.
The course frames plugins as "last in the priority order". The outcome it describes is right, in that a plugin cannot silently override your work, but the mechanism is namespacing rather than ranking. Worth knowing if a quiz asks you to order the four.
Frontmatter, field by field
There are two answers to "which fields are required", and knowing which one you are being asked about is most of the battle.
The portable answer: the Agent Skills spec
If the skill has to work in Copilot, Cursor, Codex or anything else that reads the open format, the spec is binding and narrow:
| Field | Required | Constraint |
|---|---|---|
name | Yes | 1 to 64 characters, lowercase letters, digits and hyphens only, no leading, trailing or doubled hyphen, and it must match the parent directory name |
description | Yes | 1 to 1024 characters, non-empty |
license | No | A licence name, or a bundled licence file |
compatibility | No | Up to 500 characters, for environment requirements |
metadata | No | A free map of string keys to string values |
allowed-tools | No | Space-separated pre-approved tools. Marked experimental |
The Claude Code answer
Claude Code accepts every spec field plus a long list of its own, and it is looser about what you must supply. In Claude Code all frontmatter fields are optional; description is merely recommended, and name defaults to the directory name. The fields worth knowing beyond the spec:
| Field | What it does |
|---|---|
when_to_use | Extra trigger phrases, appended to the description in the listing |
disable-model-invocation | Only you can invoke it. For anything with side effects: deploy, commit, send |
user-invocable: false | Only Claude can invoke it. For background knowledge that is not a useful command |
disallowed-tools | Removes tools from the pool while the skill is active. This is the guardrail field |
paths | Glob patterns that limit when the skill activates |
context: fork | Runs the skill in a separate subagent context |
model, effort | Model and reasoning effort while the skill is active, for the current turn only |
Correct this one in your notes. allowed-tools does not restrict what Claude may touch. It pre-approves the listed tools so they run without a permission prompt, for the turn that invoked the skill, and every other tool stays available under your normal permission settings. If you want a read-only skill, the field is disallowed-tools, or deny rules in your permission settings. Treating allowed-tools as a sandbox is a false sense of safety, and a project skill can grant itself broad access, so read the allowed-tools of any skill you inherit from a repository.
Progressive disclosure, and the 500-line rule
An activated skill loads its whole SKILL.md. A single 2,000-line file is expensive on every invocation and miserable to maintain. The fix is structural.
Keep SKILL.md to the essential instructions plus pointers, and split the detail into files that get read only when they are needed. The conventional layout is scripts/ for executable code, references/ for documentation, assets/ for templates and data.
The part people miss is the loading condition. Do not just link the file, say when to open it:
For the full architecture, read references/architecture.md.
Read it only when the question is about system design, not
when the question is where to put a new component.
Scripts are the sharper trick. A script can be executed without its contents ever entering context, so only the output costs tokens. That suits environment checks, transformations that must be identical every time, and anything more reliable as tested code than as freshly generated code. The instruction has to say run this, not read this.
The published targets: metadata around 100 tokens, an activated body under about 5,000 tokens, and SKILL.md under 500 lines.
Skills against the other four mechanisms
Lesson 4 is a selection problem, and it is the lesson that pays off fastest in a real repository.
| Use | When | Example from a QA repo |
|---|---|---|
| CLAUDE.md | Always true, every conversation | Never edit files under fixtures/golden/ |
| Skill | Sometimes relevant, task-specific | The accessibility review checklist |
| Hook | An event should trigger it, not a request | Run the linter on every file save |
| Subagent | Isolation, or different tool access | Investigate a large refactor without filling the main context |
| MCP server | You need to reach an external system | Pull the ticket from Jira |
The distinction that gets muddled most often is skill against hook. Hooks are event-driven and deterministic; skills are request-driven and advisory. If it must happen every single time regardless of what anyone asks, that is a hook. If it should shape how Claude reasons when the topic comes up, that is a skill.
The second most muddled is skill against subagent. A skill adds knowledge to the conversation you are already in. A subagent goes away, works in its own context, and comes back with a result. Delegation is a subagent. Expertise is a skill.
MCP is not really on this list at all. It is a transport for external tools, not a way to shape behaviour. A mature setup runs all five and lets each do the one thing it is good at.
Skills inside subagents, and the trap
This is the sharpest gotcha in the course, and it is worth understanding in both directions.
Subagents do not inherit your skills. They start with a fresh context. A skill that works perfectly in normal conversation is simply absent when you delegate to a subagent, and no amount of prompt wording brings it back.
To give a custom subagent specific expertise, list it explicitly. Subagents are Markdown files in .claude/agents, or you can create one with /agents:
---
name: frontend-reviewer
description: Reviews frontend code for accessibility and performance.
tools: Read, Grep, Glob
skills:
- accessibility-audit
- performance-check
---
Note what that does: the listed skills are injected in full at subagent startup, not loaded on demand. Every task that agent handles carries them. That is the point, and it is also the cost.
The built-in agents (Explore, Plan, general-purpose, Verify) do not preload skills at all. The course puts this more strongly, saying built-in agents cannot access skills whatsoever; the current documentation is narrower, in that they do not preload, but can still invoke a skill through the Skill tool unless it has been removed from their tools. Either way, if you need guaranteed expertise in delegated work, write a custom subagent.
The reverse direction is newer than the course. Put context: fork on a skill and the skill itself runs in a subagent, with the skill body as the prompt and an agent field choosing the execution environment. That only makes sense for skills that contain an actual task; a skill of guidelines forked into a subagent gives it instructions and nothing to do.
Sharing a skill across a team
Three channels, in ascending order of how much you are willing to enforce.
Commit it
Put the skill in .claude/skills/ and push. Anyone who clones the repo has it, with no install step, and updates arrive on the next pull. Best for team standards and anything that references your codebase structure. The whole .claude directory travels this way: agents, hooks, skills, settings.
Ship it as a plugin
Mirror the same layout inside a plugin, publish to a marketplace, and other teams can install it. Best when the skill is genuinely useful outside your repository. Plugin skills stay namespaced, so they never collide with what people already have.
Mandate it through managed settings
Enterprise skills carry the highest priority and override personal and project skills of the same name. This is the channel for things that must be uniform: security review standards, compliance workflows. Managed settings also carry related controls, such as restricting which marketplaces plugins may come from:
"strictKnownMarketplaces": [
{ "source": "github", "repo": "acme-corp/approved-plugins" },
{ "source": "npm", "package": "@acme-corp/compliance-plugins" }
]
Pick by the operative word. Committing to a repo is available. A plugin is installable. Managed settings are mandatory, and note that a per-repo skill cannot deliver "no opt-out": a personal skill of the same name would take precedence over it.
Troubleshooting, symptom by symptom
Almost every failure resolves to one of four symptoms, and each points at a different file.
| Symptom | Usual cause | First move |
|---|---|---|
| Never fires | The description | Ask "what skills are available?" to confirm it loaded, then add the phrasings you actually use |
| Missing from the list | Structure or YAML | SKILL.md, that exact spelling, inside a named folder. Run with --debug to see the parse error |
| Wrong skill fires | Overlapping descriptions | Make them distinct, not merely correct |
| Yours is ignored, another runs | Priority | A higher level has the same name. Renaming yours is usually faster than escalating |
| Plugin skills absent | Plugin structure | Clear cache, restart, reinstall, then validate |
| Fires then crashes | Runtime | Missing dependency, missing chmod +x, or backslashes in a path |
Validate before you debug behaviour. It catches the structural faults in seconds:
claude plugin validate ~/.claude/skills
claude plugin validate .claude/skills
For portable skills, the reference implementation of the open standard has its own validator, skills-ref validate ./my-skill.
If your frontmatter YAML is malformed, Claude Code loads the body with empty metadata. The result is a skill that still works when you type /name but never fires on its own, because there is no description to match against. That combination looks like a description problem and is actually a syntax problem, which is exactly why the validator goes first.
One more cause worth knowing, which the course does not cover. With many skills installed, the listing is trimmed to a character budget and descriptions get cut, starting with the skills you invoke least. A skill can stop firing without you having touched it. /doctor estimates the listing's context cost and names the biggest contributors.
A first skill for a QA team
Skip the PR-description example from the course; you have written one before. Here is a skill that earns its place in a test repository on day one, because flaky triage is the task everyone does inconsistently.
mkdir -p .claude/skills/flaky-triage
---
name: flaky-triage
description: Diagnose and classify a flaky test. Use when a test
passes locally but fails in CI, when a test fails intermittently,
when someone says a test is flaky, or when asked to investigate
a red build that goes green on re-run.
---
When triaging a flaky test:
1. Re-run the test 20 times in isolation and record the failure rate.
Use scripts/rerun.sh rather than running it by hand.
2. Re-run it 20 times as part of the full suite. A test that only
fails in the suite is an ordering or shared-state problem.
3. Diff a passing trace against a failing one.
4. Classify it as one of: timing, ordering, shared data, or
environment. Say which, and give the evidence.
5. Propose the smallest change that removes the race. Do not
propose a retry, and do not propose an increased timeout,
unless step 4 concluded the environment is genuinely slow.
6. If the root cause is a product bug rather than a test bug,
say so plainly and stop.
For the retry and wait patterns this codebase already uses, read
references/retry-patterns.md, but only when proposing a fix.Four things in there are deliberate, and they are the transferable part:
- The description lists four real phrasings. Nobody walks up and says "perform flaky triage". They say "this keeps failing in CI".
- Step 1 points at a script. Twenty runs is exactly the kind of work that should be executed rather than reasoned about, and the output is all that reaches context.
- Step 5 forbids the lazy fix. Standing instructions are where you encode judgement, not just procedure. A retry that hides a race is how flaky suites become permanent.
- The reference file carries a condition. It is read when proposing a fix, not during diagnosis.
Commit it. Everyone who clones the repo now triages the same way, and the argument about whether to add a retry happens once, in review of this file, rather than every sprint.
Where the course and the current docs disagree
The course is sound on concepts. Some of the specifics have moved since it was recorded, and two are worth correcting in your own notes rather than just noting in passing. Take the quiz on the course's answers; build on these.
| Point | As taught | As documented now |
|---|---|---|
allowed-tools | Restricts which tools Claude may use | Pre-approves tools so they skip the permission prompt. It restricts nothing. disallowed-tools is the restricting field |
| Creating a skill | Restart Claude Code, since skills are scanned at startup | Change detection is live. Adds, edits and deletes are picked up in the session. Restart only if the skills directory itself did not exist when the session started |
| Required fields | name and description are required | True in the open spec. In Claude Code every field is optional, description is recommended, and name falls back to the directory name |
| Description limit | 1,024 characters | 1,024 in the spec. Claude Code truncates the combined description and when_to_use at 1,536 characters in the listing, under a budget that can trim it further |
| Plugin priority | Plugins rank last | Plugin skills are namespaced plugin:skill, so they never enter the contest |
| Built-in agents | Cannot access skills at all | Do not preload skills, but can still invoke one through the Skill tool |
| Validation | Install the verifier, uv is quickest | claude plugin validate <dir> ships with Claude Code. skills-ref validate covers portable skills |
And the material that simply postdates the course: context: fork and agent for running a skill in a subagent, paths for glob-scoped activation, disable-model-invocation and user-invocable for controlling who can invoke, when_to_use for extra trigger phrases, $ARGUMENTS and argument-hint for parameterised skills, hooks in skill frontmatter, and Skill(name) permission rules for allowing or denying individual skills.
None of this makes the course wrong to take. It is free, it is well sequenced, and the concepts are stable. Treat the specifics the way you would treat any tooling course recorded more than a few months ago: right about the shape, worth checking on the details.
Eight questions, with answers
These cover the assessed material rather than reproducing the course's own quiz. Answers are hidden. Try each one before opening it.
1. A team PR checklist must apply automatically, with nobody typing a command. Where does the skill go, which field decides whether it activates, and why not CLAUDE.md?
.claude/skills/ at the repository root, so it is committed and everyone who clones gets it. The description decides activation, so it must explicitly mention reviewing PRs and checking code changes in the words people actually use. It beats CLAUDE.md because CLAUDE.md occupies context in every conversation, including the ones about something else, whereas the skill loads only when a review is genuinely being asked for. It beats a slash command because nobody has to remember to invoke it.
2. You create a personal skill and it does nothing. Give two causes, and say exactly what Claude had in context when your request arrived.
Most likely the description is too vague or too narrow, since matching runs against the description alone. Second, a higher-priority skill of the same name may be shadowing it. Third, if the frontmatter YAML is malformed, the body loads with empty metadata, so /name still works but nothing matches automatically.
At the moment of the request Claude held only names and descriptions. The body had not been read. That is why the quality of the body has no effect on whether the skill triggers.
The course adds a fourth cause, that you did not restart. That is no longer generally true: Claude Code watches skill directories and picks up changes live. A restart is only needed when the skills directory itself did not exist at session start.
3. Which frontmatter fields are required, and what are the limits?
Ask which context. Under the Agent Skills spec, name and description are both required: name is 1 to 64 characters of lowercase letters, digits and hyphens, with no leading, trailing or doubled hyphen, and it must match the parent directory name; description is 1 to 1024 characters. Optional spec fields are license, compatibility (up to 500 characters), metadata and allowed-tools.
Inside Claude Code, every field is optional. description is recommended, name defaults to the directory name and only sets the display label, and there is a much longer list of extra fields available.
4. Your onboarding skill has reached 2,000 lines covering architecture, component placement, and an environment check script. Restructure it, and give the token consequence of each move.
Apply progressive disclosure. Keep SKILL.md under 500 lines holding the essential instructions and pointers. Move the architecture write-up to references/, the check into scripts/, templates into assets/.
State the loading condition for each reference, so a question about where to add a component never drags in the architecture guide. For the script, instruct Claude to run it rather than read it: execution keeps the file contents out of context entirely and only the output costs tokens. Net effect, context holds a table of contents instead of the whole book.
5. Match each to a mechanism: lint on every save; always use strict mode; an accessibility checklist during frontend review; investigate a refactor without polluting the main conversation; query an external ticket system.
Lint on save is a hook, because hooks are event-driven. Strict mode is CLAUDE.md, an always-on standard. The accessibility checklist is a skill, task-specific expertise loaded on demand. The refactor investigation is a subagent, isolated context, returns a result. The ticket system is an MCP server. The real lesson is to layer them rather than force everything into one.
6. You add a skill, confirm it works in conversation, then delegate to the built-in Explore agent. It ignores the skill. Why, and what is the fix?
Subagents start with a fresh context and do not inherit your skills, and built-in agents do not preload skills at all. The fix is a custom subagent: a Markdown file in .claude/agents, or /agents to create one, listing the skill in the frontmatter skills field. Those skills are injected in full when the subagent starts, not loaded on demand, so every task it handles carries them. Confirm the skill exists in .claude/skills first.
Precision worth having: the course says built-in agents cannot access skills at all. The documentation says they do not preload them, and can still invoke one through the Skill tool unless that tool has been removed. The practical advice is unchanged.
7. A security standard must apply identically across every repository, with no opt-out. Which channel, and why do the others fail?
Enterprise managed settings. Enterprise skills have the highest priority and override personal and project skills of the same name, which is what "no opt-out" requires.
Per-repository .claude/skills/ fails twice: it has to be repeated in every repo, and a personal skill of the same name would beat it. Plugins fail because they depend on individuals installing them. A related control in managed settings, strictKnownMarketplaces, restricts which marketplaces plugins may come from.
8. Name the first thing to check for each: never fires; missing from the available list; a neighbouring skill fires instead; loads then crashes.
Never fires, the description: add the phrasings you actually type and test variations. Missing from the list, the structure: SKILL.md in that exact spelling inside a named folder, with parseable YAML, and --debug to surface the error. Wrong skill fires, overlapping descriptions that need to be made distinct. Crashes mid-run, the runtime: missing dependency, missing chmod +x, or backslashes where forward slashes belong.
In all four, run the validator first. claude plugin validate ~/.claude/skills catches structural faults before you start debugging behaviour.
The closing idea from the course is the one to actually act on: good skills come from real friction. Look at your own week. Whatever you have explained most often is the first skill you should write, and it will be better than anything you invent as an exercise.