Skip to main content
Guide10 min read·Updated September 21, 2026
🧩

SKILL.md Frontmatter: Every Field Explained (2026)

B

A. Frans

Published September 21, 2026

Claude SkillsSKILL.mdClaude CodeAgent SkillsReference

Most broken skills are broken in the frontmatter. The Markdown body is prose and Claude is forgiving about prose. The YAML block at the top is configuration, it decides whether the skill loads, whether Claude is allowed to invoke it on its own, and which tools run without a permission prompt, and a wrong field there fails quietly.

Here is every field, what it does, and when it is worth setting.

FieldRequiredWhat it controls
nameNoDisplay name. Defaults to the directory name
descriptionRecommendedWhen Claude should reach for this skill
disable-model-invocationNotrue makes it user-only
user-invocableNofalse makes it Claude-only
allowed-toolsNoTools pre-approved for this skill's turn
contextNofork runs it in an isolated subagent
argumentsNoNamed positional arguments
pathsNoGlob patterns limiting when it activates
A skill needs exactly one thing to exist: a SKILL.md file in its own folder. Everything above is optional. The folder name becomes the command name, so .claude/skills/deploy-staging/ gives you /deploy-staging.

description is the field that matters most

If you set nothing else, set this one. The description is how Claude decides whether a skill is relevant to the task in front of it. A vague description means the skill sits there consuming context and never triggers, which is the single most common complaint about skills that "do not work".

Write it as a trigger condition, not a title. "Summarizes uncommitted changes and flags anything risky" tells Claude when to use it. "Git helper" does not.

name is optional and defaults to the directory name. Set it only when you want a display name that differs from the folder.

Controlling who can invoke it

Two fields, and they are easy to mix up because they are opposites.

disable-model-invocation: true means only you can run it, by typing /skill-name. Claude will not decide to invoke it on its own. This is what you want for anything with consequences: a deploy, a release, anything that posts or sends.

---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---

user-invocable: false is the mirror image. Claude can use it, you cannot type it as a command. This suits background knowledge you want applied automatically but never invoked directly, like a house style guide that should shape writing without being a command.

Leave both unset and the skill works either way, which is the right default for most skills.

allowed-tools, and the trap in it

allowed-tools pre-approves specific tool calls for the duration of the skill's turn, so a routine skill stops interrupting you for permission on every step.

---
name: commit-work
description: Stage, commit and describe the current changes
allowed-tools: Bash(git add *) Bash(git commit *)
---

The patterns are narrow on purpose. Bash(git add ) approves git add, not every Bash command. This is a security boundary, and the temptation to widen it to something like Bash() because a prompt keeps appearing is the wrong instinct. If you find yourself reaching for a wildcard, the honest fix is usually to list the two or three commands the skill runs.

context: fork

Setting context: fork runs the skill in an isolated subagent. It gets its own context window, does its work, and returns a result rather than dumping everything it read into your main conversation.

Use it for skills that read a lot and conclude a little: a codebase audit, a research sweep, a review pass across many files. The subagent absorbs the volume and you get the answer.

Do not use it for skills that need to keep editing alongside you in the current conversation, because the isolation that makes it useful also cuts it off from your session's state.

arguments and substitutions

Declare named arguments in frontmatter and reference them in the body:

---
name: fix-issue
arguments: [issue, branch]
---

Fix issue $issue on branch $branch

Running /fix-issue 123 main sets issue to 123 and branch to main.

Several substitutions are available in the body without declaring anything:

  • $ARGUMENTS for everything passed
  • $0, $1, $2 for positional arguments
  • ${CLAUDE_PROJECT_DIR} for the repository root
  • ${CLAUDE_SKILL_DIR} for the skill's own folder
  • ${CLAUDE_SESSION_ID} for the current session

${CLAUDE_SKILL_DIR} is the one worth remembering. It is how a skill references its own helper scripts and reference files without hardcoding a path that only works on your machine.

paths

paths takes glob patterns and limits when the skill is considered relevant. A skill scoped to */.tsx will not clutter Claude's options while you are editing Python. In a repository with many skills this is a cheap way to cut noise.

Injecting live context with a command

A skill body can run a shell command before Claude reads it, using the ` !command syntax:

---
description: Analyze the current pull request
---

## Pull request diff
!`gh pr diff`

## Your task
Summarize the changes above and flag anything risky.

The command runs once when the skill is invoked and its output replaces the placeholder. This turns a static instruction file into something that arrives already holding the current state, which is usually the difference between a skill that is useful and one that asks you to paste things in.

Where the file goes

ScopePath
Personal, all your projects~/.claude/skills/<name>/SKILL.md
Project, shared with the team.claude/skills/<name>/SKILL.md
Nested, a subdirectory and below<subdir>/.claude/skills/<name>/SKILL.md
Project skills get committed, which is the point of them. Personal skills stay on your machine.

In a monorepo, names can clash without breaking anything. A root deploy and a nested apps/web/deploy both load, with the nested one qualified as /apps/web:deploy.

A minimal skill is small:

mkdir -p ~/.claude/skills/summarize-changes

Then a SKILL.md with a description and instructions. That is the whole setup. Supporting files, reference documents and scripts can sit beside it in the same folder and be referenced from the body.

Turning one off without deleting it

You can override visibility in .claude/settings.local.json rather than removing the folder:

{
  "skillOverrides": {
    "deploy": "off",
    "legacy-context": "name-only"
  }
}

"off" hides it. "name-only" keeps the name available but drops the description from context, which trims tokens for a skill you rarely need while leaving it reachable.

Putting it together

A skill using several fields at once, to show how they interact:

---
name: release-notes
description: Draft release notes from the commits since the last tag
disable-model-invocation: true
allowed-tools: Bash(git log *) Bash(git tag *)
arguments: [tag]
---

## Commits since $tag
!`git log $tag..HEAD --oneline`

Draft release notes grouped by user-visible change, fix and internal work.
Skip anything that only touches tests or formatting.

Read in order: only you can run it, because releases have consequences. It may read git history without asking permission, and nothing else. It takes a tag as an argument. It arrives with the commit log already in hand, so the first thing Claude does is write, not gather.

Four mistakes that cost an afternoon

Editing the wrong copy. A skill in ~/.claude/skills/ and one with the same name in the project's .claude/skills/ are different files. Changing one and testing the other produces a convincing illusion that your edits do nothing.

Misspelling a field. Unknown keys are ignored rather than rejected, so allowed_tools with an underscore, or disable_model_invocation, fails silently and leaves you staring at a permission prompt that should have gone away. The field names use hyphens.

A description written for humans. "Deployment helper for the staging environment" reads well and gives Claude nothing to match against. State the trigger: "Deploys the current branch to staging and runs smoke tests."

Wildcarding allowed-tools to stop the prompts. It works and it removes the boundary. List the specific commands instead.

The order I would set these in

Start with description, and spend real effort on it, because it decides whether anything else you wrote gets used. Add disable-model-invocation: true to anything with consequences. Add allowed-tools when permission prompts get tedious, keeping the patterns narrow. Reach for context: fork only when a skill reads far more than it reports. Leave the rest alone until you have a reason.

For the surrounding workflow, see our guides on why a skill is not triggering, on updating, disabling and removing skills, and on versioning your own skills. The skill-creator skill scaffolds the structure if you would rather not start from an empty file.

FAQ

Which SKILL.md frontmatter fields are required? None. A SKILL.md with a Markdown body will load. In practice description is close to mandatory, because without a good one Claude has no basis for deciding when the skill applies.

What is the difference between disable-model-invocation and user-invocable? They are opposites. disable-model-invocation: true means only you can run it as a command. user-invocable: false means only Claude can invoke it and you cannot type it. Most skills should set neither.

Does allowed-tools skip permission prompts entirely? It pre-approves the specific patterns you list, for that skill's turn only. Bash(git add *) approves git add and nothing else. Keep the patterns narrow, since this is a security boundary rather than a convenience setting.

When should a skill use context: fork? When it reads a lot and reports a little, such as an audit or a research pass. The isolated subagent keeps that volume out of your main context. Avoid it for skills that need to keep working alongside you in the current conversation.

How do I reference a script that lives next to my SKILL.md? Use ${CLAUDE_SKILL_DIR}`, which resolves to the skill's own folder. Hardcoded absolute paths break for everyone else on the team.

Why is my skill loading but never triggering? Almost always the description. Rewrite it to state the condition under which the skill should be used, in the words someone would use for the task, rather than naming the skill.

Share this article

📬

Get More AI Tool Guides

New comparisons and guides every week. Join thousands of professionals staying ahead of the AI curve.