Skip to content

SKILL.md Format

A SKILL.md file defines a Copilot skill. It uses YAML frontmatter for metadata and Markdown for documentation.

SKILL.md
---
name: my-skill-name
description: A concise description of what this skill does.
---
## Usage
Explain when and how to use this skill.
## Examples
- "Example prompt 1"
- "Example prompt 2"
## References
- [Guide](references/guide.md)
- [API docs](references/api.md)
FieldTypeRequiredConstraintsDescription
namestringYesKebab-case, ≤ 64 characters. Only lowercase letters, digits, and hyphens.Unique identifier for the skill
descriptionstringYes≤ 1,024 charactersWhat the skill does
other fieldsanyNoAny additional YAML fields are preserved in frontmatter

Valid names:

  • my-skill
  • code-reviewer-v2
  • a

Invalid names:

  • My_Skill ✘ (uppercase, underscores)
  • my skill ✘ (spaces)
  • MY-SKILL ✘ (uppercase)
  • “ (empty) ✘

Markdown links in the body are parsed as file references:

[Guide](references/guide.md)
[API docs](references/api.md#section)
[External](https://example.com) <!-- ignored: external URL -->

Rules:

  • Relative paths are resolved from the SKILL.md’s directory
  • Fragment anchors (#section) are stripped for file existence checks
  • External URLs (starting with http:// or https://) are ignored
  • Links inside code fences are ignored
  • The valid-refs grader checks that every referenced file exists
  • The orphan-files grader checks that every file in references/ is reachable

A typical skill directory:

my-skill/
├── SKILL.md # Required: skill definition
├── references/ # Optional: supporting files
│ ├── guide.md
│ ├── api-reference.md
│ └── examples/
│ └── usage.py
└── eval.yaml # Optional: evaluation stimuli

The discoverSkills() function (and vally lint) finds skills by recursively searching for SKILL.md files. It excludes:

  • node_modules/ directories
  • Hidden directories (starting with .)
  • Symlinks

When parsed, a SKILL.md becomes a Skill object:

interface Skill {
name: string; // From frontmatter
description: string; // From frontmatter
path?: string; // Filesystem path to SKILL.md
rawContent: string; // Full file content
frontmatter: Record<string, unknown>; // All YAML fields
frontmatterParseError?: string; // Set if YAML was invalid
fileReferences: FileReference[]; // Extracted from markdown links
}
interface FileReference {
raw: string; // Original text from markdown
normalized: string; // After stripping ./ and fragments
segments: string[]; // Path segments
line?: number; // Line number in the file
}

The lint command checks these rules via the spec-compliance grader:

RuleCheck
Name presentname field exists in frontmatter
Name formatMatches /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/
Name length≤ 64 characters
Description presentdescription field exists in frontmatter
Description length≤ 1,024 characters