The directory is what you install, but the file name inside it is not negotiable — the loader looks for the literal string SKILL.md, capitalized exactly.
Why you'd careThe problem it solves
You have a forty-line preamble you paste at the top of every session. How migrations work here. Which columns are soft-deleted. Why the staging seed script has to run before the test suite. You paste it, the session ends, you paste it again. Sometimes you forget a paragraph and the model does the wrong thing, and afterwards you cannot tell whether the model was wrong or the paragraph was missing. A skill is the packaging answer to that: the preamble becomes a directory on disk, the harness finds it without being told, and it loads when the work actually calls for it instead of at the top of every conversation. The first thing to get right is the shape of that directory, because the loader is unforgiving about exactly one part of it — and it is not the part most people guard.
ConceptWhat it is
A skill is a directory. The only member the loader requires is a file called SKILL.md at its root. That file opens with a YAML block fenced by --- lines; everything after the closing fence is Markdown that the model reads as procedural instruction, not as a document to summarize.
The split matters more than it looks. The frontmatter is metadata about the skill — what it is, when to reach for it — and it is what tooling parses. The body is addressed to the model that will do the work. Anthropic's own authoring guidance is blunt that you are writing for another instance of Claude rather than for a human reader, which is why its house style for the body is imperative and verb-first rather than explanatory.
Two names are in play and they are easy to conflate. The directory name is what the harness scans for and what the packaging script uses to name its output file. The name: key inside the frontmatter is a separate required string with its own format rules. Nothing forces the two to agree. Anthropic's skill-creator explicitly instructs that both the directory name and the name field be carried through unchanged when revising a skill, which is a strong hint that you should make them match once and then never touch either again.
Everything else is optional and conventional. scripts/, references/, assets/ are habits, not requirements. A directory containing nothing but a SKILL.md is a complete, valid, working skill.
How it worksThe mechanics
Discovery is a filesystem scan. Claude Code walks its skill locations and a subdirectory counts as a skill if and only if it contains SKILL.md. The check is for that literal file name; skill.md or Skill.md gets walked straight past on a case-sensitive volume, and this is the failure that produces the maddening symptom of a skill that exists on disk and does not appear in the session at all.
my-skill/
├── SKILL.md <- required, this exact name
├── scripts/ <- executable code
├── references/ <- docs read into context on demand
└── assets/ <- files copied into your outputThe file itself is unremarkable:
---
name: my-skill
description: This skill should be used when the user asks to ...
---
# My Skill
To do the thing, first ...Parsing is strict at the front and loose everywhere else. Anthropic's quick_validate.py requires the file to start with --- and extracts the block with the pattern ^---\n(.*?)\n---. A blank line, a byte-order mark, or a comment before the opening fence produces “No YAML frontmatter found”. The block must then parse as a YAML dictionary, and it must contain name and description. Those two keys are required by the spec, the validator and every upload path — but not by Claude Code itself, which reads frontmatter only when the opening --- is the first line, treats a file without it as all body, and defaults name to the directory name and description to the first non-empty body line.
After the closing fence, nothing is enforced at all. There is no mandatory heading, no schema, no section the loader looks for, no length the loader rejects. The body is text, and when the skill fires it is loaded verbatim into the model's context. That asymmetry — rigid header, entirely free body — is the whole design. The header is for machines deciding whether to load; the body is for a model deciding what to do.
At a glanceSee it
How the harness turns a directory on disk into a loadable skill, and the two points where it gives up.
Where it runsSurfaces and availability
| Surface | Status | Notes |
|---|---|---|
| Claude Code | Yes | Confirmed. Scans for directories containing SKILL.md under ~/.claude/skills/ (personal), project .claude/skills/ — every parent up to the repo root plus nested package directories — enterprise, and plugin <plugin>/skills/. Single-file .claude/commands/*.md also still produces the same command, so the folder is not the only accepted form. Source: code.claude.com/docs/en/skills, "Where skills live" (docs.anthropic.com/en/docs/claude-code/skills now 301s here). |
| Agent SDK | Yes | Same filesystem discovery, but not unconditionally. Skills load through setting sources: default query() options load user and project, and if you set settingSources explicitly it must include one of them or no skills load. A skills option filters which discovered skills are exposed, and there is no programmatic registration API. A former divergence has closed: for project and personal skills, Claude Code now applies the allowed-tools frontmatter field in SDK sessions. Source: code.claude.com/docs/en/agent-sdk/skills. |
| Claude Desktop / claude.ai | Yes | Corrected. The install unit is a zip file uploaded through Settings > Features (Pro, Max, Team, Enterprise, with code execution enabled); its contents are this identical folder. No primary Anthropic page documents a .skill archive or a packaging script naming claude.ai, so that claim is withdrawn. Desktop is a management surface over the same account-level skill set ("Customize" in the sidebar). Sources: agent-skills/overview "claude.ai"; code.claude.com/docs/en/skills. |
| Claude API / Messages API | Yes | Indirect, confirmed. Upload the folder to the Skills API (/v1/skills) as a zip archive or as individual files — all files under one top-level directory with SKILL.md at its root — then reference the returned skill_id in container.skills alongside the code execution tool; no beta header is required since Skills left beta on 2026-08-19. Up to 20 Skills per request. Sources: agents-and-tools/agent-skills/overview; build-with-claude/skills-guide. |
| Managed Agents | Yes | Indirect, same route, confirmed. Entries in the Agent object's skills array are {type, skill_id, version}, never a path; up to 500 skills per session, and a session can override the set. Sources: managed-agents/skills; managed-agents/sessions. |
| Amazon Bedrock | No | Confirmed. "Features not supported" lists both "Server-side tools (code execution, web search, web fetch, advisor)" and "Agent infrastructure (Agent Skills, MCP connector, programmatic tool calling)". The path is absent, not disabled. Note the neighbour: Claude Platform on AWS is a separate, Anthropic-operated AWS offering that does support Agent Skills and code execution. Sources: build-with-claude/claude-in-amazon-bedrock; build-with-claude/claude-platform-on-aws. |
| Google Vertex AI | No | Confirmed, same wording: "Agent infrastructure (Agent Skills, MCP connector, programmatic tool calling)" is not supported, and neither is server-side code execution. The surface is now branded Google Cloud Agent Platform. Source: build-with-claude/claude-on-vertex-ai, "Features not supported". |
| Microsoft Foundry | Yes | Was Unverified; now confirmed and it is not a rumour. Agent Skills are supported on Hosted on Anthropic deployments only — Azure-hosted deployments return 400 Bad Request for Agent Skills, code execution and the Files API, among other features, by design. Custom Skills are uploaded through the Skills API, and Foundry "inherits the same Skills behavior as the Claude API". Sources: build-with-claude/claude-in-microsoft-foundry; agents-and-tools/agent-skills/overview. |
| OpenAI Codex CLI / ChatGPT | Yes | Was Unverified; now confirmed, and the file-name convention does carry over. A Codex skill is a directory containing SKILL.md with YAML front matter (name, description). What differs is the directory: .agents/skills in the repo and in $HOME, /etc/codex/skills for admin, plus system skills bundled with Codex. Source: developers.openai.com/codex/skills. |
| Google Antigravity CLI | Yes | Was Unverified; now confirmed. A skill is a folder containing SKILL.md, at <workspace-root>/.agents/skills/ or ~/.gemini/config/skills/; the CLI (agy) also reads ~/.gemini/antigravity-cli/skills/ and compiles skills into slash commands. Frontmatter is looser than the Agent Skills spec, which requires both: description is required and name is optional, defaulting to the folder name. Sources: antigravity.google/docs/skills; antigravity.google/docs/cli/plugins. |
The pattern to read here is stronger than it looked: the SKILL.md folder is now the authoring format across three vendors, not just Anthropic's — Claude Code, Codex and Antigravity all scan directories for a SKILL.md, and two of the three have converged on the same .agents/skills path. Only local harnesses consume the folder directly; every hosted Anthropic surface wants an uploaded object with an ID, which is why you should draft on disk, where the edit-test loop is a file save, and register the skill only once its behaviour has stopped changing. The one place with genuinely nothing to port to is Amazon Bedrock and Vertex AI, where Agent Skills are explicitly absent from the feature list. That is a statement about those two products, not about AWS or Google as such: Claude Platform on AWS supports Skills, and Antigravity has its own.
ExampleIn the real world
Your team's release notes always come out wrong in the same three ways: the wrong date format, the internal ticket IDs left in, and the breaking-change section omitted when there are no breaking changes instead of being marked “None”. You create ~/.claude/skills/release-notes/ and put one file in it.
The frontmatter says name: release-notes and a description that names the trigger phrases people actually use — “draft the release notes”, “write the changelog entry”, “prep the 4.2 announcement”. The body is about six hundred words: the section order, the ISO date rule, the instruction to strip anything matching the ticket prefix, and the rule that the breaking-changes heading is always present and reads “None” when empty.
Next session, you type “draft the release notes for 4.2”. You do not name the skill. The model has been holding only the one-line description in context; it matches, reads the body, then reads your git log. What comes back has the ISO dates, no ticket IDs, and a breaking-changes heading that says None. You did not paste anything. When the date rule changes next quarter, you edit one file and every future session inherits it.
Not thisWhat it is often confused with
- Not a config filethe frontmatter is configuration, but the body is instruction the model acts on. Nothing parses the body into settings; it is read the way a briefing document is read.
- Not a prompt templatethere are no slots, no variable substitution, no render step. The text you write is the text the model sees, unchanged.
- Not a toola tool has an input schema and returns a value to the model. A skill has neither. The model reads a skill; it calls a tool. A skill can tell the model which tools to call.
- Not a plugina plugin is a distribution container that may hold several skills alongside commands, agents, hooks and MCP server definitions. Skills live inside plugins; plugins are not a kind of skill.
- Not CLAUDE.md or AGENTS.mdthose are always-on project memory, loaded whether or not they are relevant. A skill's body is loaded conditionally, which is the entire point of packaging it as one.
LimitsWhen not to reach for it
- The instruction is one-off.If you will say it once, say it. A skill is a fixed authoring cost that pays back over repetitions, and a skill written for a single task is slower than typing the sentence.
- The content changes per query.Skills are static files. If the right answer depends on today's database rows or this week's ticket queue, you want retrieval or a tool call, not a folder that has to be edited to stay true.
- The model needs to act on a live system.A skill can describe an API perfectly and still not be able to reach it. Reaching for an MCP server or a tool definition is the correct move.
- It genuinely must apply on every turn.Coding standards that are never optional belong in the system prompt or in CLAUDE.md. A skill that must always fire is a skill whose conditional loading is pure overhead.
- Your team's tools do not read the format.Cursor, GitHub Copilot and dozens of other clients now load
SKILL.mdfolders, but in a client that does not implement Agent Skills the folder is a file nobody's tooling reads. Check the client first; where it falls short, AGENTS.md or the IDE's own rules format will actually load.
Verified 2026-09-12. Stable — the shape of this is unlikely to move. Provider: Anthropic.