learn.aathan.in

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:

LocationPathApplies to
EnterpriseManaged settingsAll users in your organization
Personal~/.claude/skills/<skill-name>/SKILL.mdAll your projects
Project.claude/skills/<skill-name>/SKILL.mdThis project only (commit it!)
Plugin<plugin>/skills/<skill-name>/SKILL.mdWherever 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:

FieldPurpose
nameDisplay name in skill listings. Defaults to the directory name.
descriptionWhat the skill does and when to use it. The model matches against this to decide invocation.
when_to_useExtra trigger phrases / example requests, appended to description.
allowed-toolsTools the agent may use without asking permission while the skill is active.
disable-model-invocationtrue = only you can invoke it (via /name); the model won’t trigger it automatically.
user-invocablefalse = hide from the / menu; only the model can load it (for background knowledge).
argument-hintAutocomplete hint for expected arguments, e.g. [issue-number].
contextSet to fork to run the skill in an isolated subagent.
pathsGlob patterns; the skill auto-activates only when working on matching files.

Note: some fields (like allowed-tools, disable-model-invocation, and context: fork) are Claude Code extensions on top of the base open standard. The core standard is name + 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:

FrontmatterYou can invokeModel can invokeDescription in context?
(default)YesYesYes (full body on invoke)
disable-model-invocation: trueYesNoNo
user-invocable: falseNoYesYes
  • Use disable-model-invocation: true for actions with side effects (/commit, /deploy, /send-slack-message).
  • Use user-invocable: false for background knowledge that isn’t a meaningful command — e.g. a legacy-system-context skill 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: