SKILL.md files: the format behind Claude Agent Skills
A deep dive into the SKILL.md format — YAML frontmatter fields, directory layout, bundled scripts, progressive disclosure, and invocation control, with copy-pasteable examples.
An Agent Skill is a folder that teaches an agent how to do one thing well.
The folder’s entry point is a file named SKILL.md: YAML frontmatter that tells
the model when to use the skill, followed by Markdown instructions that tell it
how. Optionally, the folder bundles scripts, templates, and reference docs the
skill can pull in on demand.
This is the format behind Claude’s Agent Skills, and it follows the Agent Skills open standard that works across multiple AI tools. This page is the practical reference. For the big-picture “skills vs. AGENTS.md” framing, start with the overview.
The minimal SKILL.md
Every skill needs exactly one thing: a SKILL.md with a description. Here’s a
complete, working skill:
---
name: api-conventions
description: API design patterns for this codebase. Use when writing or reviewing HTTP endpoints.
---
When writing API endpoints:
- Use RESTful naming conventions
- Return consistent error formats
- Include request validation
That’s it. The description is the single most important line — it’s what stays
in context so the model can decide when the skill is relevant, so write it to
name the trigger (“Use when …”), not just the topic.
Where skills live
A skill is discovered by where its folder sits on disk. The location decides who can use it:
| Location | Path | Applies to |
|---|---|---|
| Enterprise | Managed settings | All users in your organization |
| Personal | ~/.claude/skills/<skill-name>/SKILL.md | All your projects |
| Project | .claude/skills/<skill-name>/SKILL.md | This project only (commit it!) |
| Plugin | <plugin>/skills/<skill-name>/SKILL.md | Wherever the plugin is enabled |
Personal skills travel with you across every repo. Project skills get committed to version control so the whole team (and CI agents) share them. When names clash across levels, the more specific wins: enterprise overrides personal, personal overrides project, and any of them can override a bundled skill of the same name.
In monorepos, skills also load from nested .claude/skills/ directories:
when the agent works on a file in apps/web/, skills defined in
apps/web/.claude/skills/ become available even if the session started at the
repo root.
Directory layout: bundling scripts and resources
The power of the format is that a skill is a folder, not just a file. The
SKILL.md is the required entry point; everything else is optional and loaded
only when the SKILL.md points to it:
my-skill/
├── SKILL.md # required — overview, instructions, and navigation
├── reference.md # detailed docs, loaded only when the body links to it
├── examples.md # example outputs showing the expected format
└── scripts/
└── helper.py # a script the agent executes — never loaded into context
Reference the extra files from SKILL.md so the model knows what each one holds
and when to open it:
## Additional resources
- For the complete API details, see [reference.md](reference.md)
- For usage examples, see [examples.md](examples.md)
This is the mechanism behind progressive disclosure:
a skill can bundle thousands of lines of reference material, and the agent only
reads what the current task requires. Scripts are even cheaper — the agent
runs them and reads the output, never loading the source into context. Keep the
SKILL.md body itself under ~500 lines; push heavy detail into supporting files.
Frontmatter reference
All frontmatter fields are optional; only description is strongly recommended.
The most commonly used ones:
| Field | Purpose |
|---|---|
name | Display name in skill listings. Defaults to the directory name. |
description | What the skill does and when to use it. The model matches against this to decide invocation. |
when_to_use | Extra trigger phrases / example requests, appended to description. |
allowed-tools | Tools the agent may use without asking permission while the skill is active. |
disable-model-invocation | true = only you can invoke it (via /name); the model won’t trigger it automatically. |
user-invocable | false = hide from the / menu; only the model can load it (for background knowledge). |
argument-hint | Autocomplete hint for expected arguments, e.g. [issue-number]. |
context | Set to fork to run the skill in an isolated subagent. |
paths | Glob patterns; the skill auto-activates only when working on matching files. |
Note: some fields (like
allowed-tools,disable-model-invocation, andcontext: fork) are Claude Code extensions on top of the base open standard. The core standard isname+description+ Markdown body; check your tool’s docs for which extensions it supports.
A fuller frontmatter block:
---
name: my-skill
description: What this skill does
disable-model-invocation: true
allowed-tools: Read Grep
---
Your skill instructions here...
Two kinds of skill content
It helps to think about how you want a skill invoked:
Reference skills add knowledge the model applies to your current work —
conventions, style guides, domain facts. These are usually fine to let the model
load automatically. The api-conventions example above is one.
Task skills give step-by-step instructions for an action — deploy, commit,
generate a migration. These often have side effects, so you want to trigger them
yourself with /skill-name rather than let the model decide. Add
disable-model-invocation: true:
---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---
Deploy the application:
1. Run the test suite
2. Build the application
3. Push to the deployment target
4. Verify the deployment succeeded
You don’t want an agent deciding to deploy just because the code “looks ready” —
disable-model-invocation: true keeps the trigger in your hands.
Controlling who invokes a skill
Two frontmatter fields govern invocation, and the combination is worth memorizing:
| Frontmatter | You can invoke | Model can invoke | Description in context? |
|---|---|---|---|
| (default) | Yes | Yes | Yes (full body on invoke) |
disable-model-invocation: true | Yes | No | No |
user-invocable: false | No | Yes | Yes |
- Use
disable-model-invocation: truefor actions with side effects (/commit,/deploy,/send-slack-message). - Use
user-invocable: falsefor background knowledge that isn’t a meaningful command — e.g. alegacy-system-contextskill the model should know about but that you’d never “run.”
Pre-approving tools
allowed-tools grants permission for specific tools while the skill is active,
so the agent doesn’t stop to ask each time. It grants — it doesn’t restrict;
your normal permission settings still govern everything not listed. A commit
skill that can run git without prompting on each command:
---
name: commit
description: Stage and commit the current changes
disable-model-invocation: true
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---
Stage and commit the current changes with a clear, conventional message.
For project skills committed to .claude/skills/, allowed-tools only takes
effect after you accept the workspace-trust prompt — so review third-party
skills before trusting a repo, since a skill can grant itself broad access.
Passing arguments
Arguments typed after the skill name land in the $ARGUMENTS placeholder:
---
name: fix-issue
description: Fix a GitHub issue by number
disable-model-invocation: true
---
Fix GitHub issue $ARGUMENTS following our coding standards.
1. Read the issue description
2. Understand the requirements
3. Implement the fix
4. Write tests
5. Create a commit
Running /fix-issue 123 sends “Fix GitHub issue 123 …”. For positional access,
use $ARGUMENTS[0] (or the shorthand $0), $1, and so on:
---
name: migrate-component
description: Migrate a component from one framework to another
---
Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.
/migrate-component SearchBar React Vue fills in SearchBar, React, and Vue.
Bundling and running a script
This is where skills get genuinely powerful: a skill can bundle a script in any
language and have the agent run it, giving the model capabilities beyond what a
prompt alone can do. The ${CLAUDE_SKILL_DIR} substitution resolves to the
skill’s own folder, so the path works no matter where the skill is installed:
---
name: codebase-visualizer
description: Generate an interactive collapsible tree view of your codebase. Use when exploring a new repo or understanding project structure.
allowed-tools: Bash(python3 *)
---
# Codebase Visualizer
Generate an interactive HTML tree view of the project's file structure.
## Usage
Run the visualization script from the project root:
python3 ${CLAUDE_SKILL_DIR}/scripts/visualize.py .
This creates `codebase-map.html` and opens it in the browser.
with the actual work in scripts/visualize.py. The model orchestrates; the
bundled script does the heavy lifting — and its source never enters the context
window.
Dynamic context injection
A Claude Code extension lets a skill run a shell command before the model sees
the content and splice in the output, so the instructions arrive pre-filled with
live data. The !`command` syntax:
---
name: summarize-changes
description: Summarize uncommitted changes and flag anything risky. Use when the user asks what changed or wants a commit message.
---
## Current changes
!`git diff HEAD`
## Instructions
Summarize the changes above in two or three bullet points, then list any risks
you notice (missing error handling, hardcoded values, tests that need updating).
If the diff is empty, say there are no uncommitted changes.
When this runs, git diff HEAD executes first and its output replaces the
placeholder — so the model receives the actual diff, not the command. This is
preprocessing, not something the model chooses to do.
A note on the skill-content lifecycle
Once a skill is invoked, its rendered SKILL.md enters the conversation and
stays there for the rest of the session — the file isn’t re-read each turn. So
write standing instructions (“throughout this task, do X”), not one-shot steps
that only make sense the moment they load. And keep the body lean: every line is
a recurring token cost for as long as the session lives.
Building and sharing skills
- Project skills: commit
.claude/skills/to version control so the team shares them. - Plugins: put a
skills/directory in a plugin to distribute a bundle of related skills. - Managed: deploy organization-wide through managed settings.
To iterate on quality, treat a skill like code: collect a few realistic prompts, run each with the skill available and again with it disabled, and compare. That tells you both whether the model triggers the skill when it should and whether the output improved.
References
Verified July 2026 against official sources:
- Extend Claude with skills — Claude Code docs (frontmatter table, locations, layout, and examples above are drawn from here)
- Agent Skills overview — Claude platform docs
- Skill authoring best practices — Claude platform docs
- Equipping agents for the real world with Agent Skills — Anthropic
- anthropics/skills on GitHub