A SKILL.md file is a folder's worth of instructions wrapped around a few lines of YAML. It is small enough that most people manage to overthink it anyway. So here is the skill.md template you came for, up top, before any theory. Copy it, change two fields, and you have a valid Agent Skill that Claude Code, the Claude apps, Codex, Cursor, and Gemini CLI can all load.
---
name: commit-helper
description: Generate clear git commit messages from staged changes. Use when the user asks for help writing a commit message or reviewing staged diffs.
---
# Commit helper
Write commit messages in the format `type(scope): summary`, then a blank line, then a short body explaining why the change was made.
## Steps
1. Read the staged diff.
2. Pick one type: feat, fix, chore, docs, refactor, test.
3. Write a summary under 60 characters.
4. Add a one or two line body that explains intent, not the diff.
## Avoid
Do not restate the diff line by line. Do not invent a scope that is not in the changed paths.
That is a complete skill. Frontmatter, a title, two H2 sections. Nothing else is required.
What the SKILL.md template frontmatter rules actually are
The file must start with a SKILL.md YAML frontmatter block fenced by --- on its own line above and below. No comment before it, no heading, no leading blank line. The triple-dash block is the first thing in the file or the skill does not register. Every rule that follows is a skill md frontmatter rule, and if this opening block is malformed none of them get a chance to matter.
Inside that block, two fields are required and the Agent Skills spec is strict about both:
name has a 64-character ceiling, accepts only lowercase letters, numbers, and hyphens, carries no XML tags, and cannot use the reserved words "anthropic" or "claude". So commit-helper passes, while Claude_Commit_Helper packs two violations into one string (a reserved word and underscores).
description must be non-empty and stay under 1024 characters. That is the whole hard limit. Everything past it is craft, and the craft is where skills succeed or quietly never fire.
The description is the only part of your skill that lives in the model's context at all times. At startup, Anthropic loads the name and description from every installed skill, and nothing else, into the system prompt. Claude reads the body of SKILL.md only after the description has convinced it the skill is relevant. So a vague description is what separates a skill that triggers from one that sits on disk forever. Write it in third person, say plainly what the skill does, and name the situations that should pull it in. "Generate clear git commit messages from staged changes. Use when the user asks for help writing a commit message" beats "Helps with git" by a mile. I go deeper on this in how to write a SKILL.md description, because it is the line in the file that carries the most weight.
A richer skill md example with a bundled file
The minimal version covers most cases. Once your instructions grow past a screen, or you have a long reference you would rather not keep in context every time, you split it out. Here is a skill md example that keeps the body short and points to a bundled file for the heavy material:
---
name: api-error-codes
description: Look up internal API error codes and the correct retry behavior. Use when the user hits an HTTP error from the billing or auth service and needs the documented response.
---
# API error codes
Resolve error codes for the billing and auth services and tell the user the right retry strategy.
## How to respond
1. Find the code the user reported.
2. Check the reference table below for its meaning and retry rule.
3. If the code is not listed, say so. Do not guess.
## Reference
The full code table is in [error-codes.md](error-codes.md). Read it before answering any lookup.
error-codes.md sits in the same folder as SKILL.md. The model loads it only when this skill runs, so a 400-line table costs zero context until someone actually asks about an error code. Keep references one level deep. SKILL.md points to a file, and that file should not point to another, because once you build a chain Claude tends to skim it instead of reading the whole thing.
The folder ends up looking like this:
api-error-codes/
├── SKILL.md
└── error-codes.md
That is the entire structure for a two-file skill. If you want the full layout with scripts/ and nested reference/ directories, I wrote that up separately in the Claude skill folder structure guide.
The optional field most people ask about
The two required fields are the whole spec. On top of that, Claude Code adds a handful of optional extensions, and the one worth knowing is allowed-tools, which pre-approves specific tools so the skill runs without stopping to ask permission each time:
---
name: commit
description: Stage and commit the current changes.
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---
You only need this when your skill runs shell commands or other tools and you are tired of approving each one. A plain instruction-only skill never touches it. Full rules for the field, including how it behaves in a project's .claude/skills/ directory, are in the allowed-tools guide.
After you have the file
You have a valid skill md file template filled in. The same skill md template works across tools, so a Claude skill md template you write once will run in Codex, Cursor, and Gemini CLI without changes. One step left: put it where the tool can see it. For Claude Code that means ~/.claude/skills/<skill-name>/SKILL.md for a personal skill or .claude/skills/<skill-name>/SKILL.md for one scoped to a single project. The exact path varies by tool, so I keep the install steps for each one in how to install a Claude skill.
Here is the part nobody likes admitting. A template is just a blank with the structure already drawn in, and the two fields you fill, the name and especially the description, are the two that decide whether the skill ever runs. Anyone can get the YAML right in a minute. Writing a description that triggers on the right requests and stays quiet on the wrong ones takes actual judgment, and you usually do not find out you got it wrong until the skill silently fails to fire three weeks later.
That gap is why Knack exists. You answer a short interview about what the skill should do and when it should fire, and it writes a filled, valid SKILL.md, frontmatter and body and all, with a description built to trigger. I think the format itself is simple enough to hand-write. It is the judgment going into the blanks that I would rather hand off.
So take the template at the top, change the name and description, drop it in your skills folder, and run it. If it fires when you expect it to, you are done.