Module 12

Copilot Skills: How They Work

Developer Tools Git, GitHub & GitHub Copilot

Module 12 — Copilot Skills: How They Work

Goal: Fully understand Copilot Skills — what a SKILL.md file is, what goes in its frontmatter, the directory layout, and — the question everyone asks — how Copilot decides which skill to load and how this keeps the context window from overflowing.

This module directly answers two of your core questions: how do skill files work and how does Copilot decide which skill file to load.


12.1 What a skill is (and why it exists)

A skill is a self-contained folder of expertise that teaches Copilot how to do a specific kind of task — for example “run our database migrations safely,” “generate a component following our design system,” or “do a security review the way our team does.” Each skill is just a folder containing a file called SKILL.md (plus optional helper files).

Why not just put all this in custom instructions (Module 11)? Because instructions are always loaded and so they’re always spending context budget. You can’t put fifty detailed procedures in copilot-instructions.md — it would bloat every request and crowd out your actual code. Skills solve this by being loaded only when relevant. You can install dozens of skills, and Copilot pulls in just the one(s) it needs for the task at hand. As one writer put it: skills aren’t magic — they’re scoped context.

Instructions vs. skills in one line: instructions are always-on rules (small, broad); skills are on-demand procedures (can be large and detailed, loaded only when triggered).


12.2 Anatomy of a SKILL.md file

A SKILL.md is a Markdown file with a YAML frontmatter block at the top (between --- lines) followed by the instructions body.

---
name: database-migrations
description: >
  Create and run database schema migrations for this project.
  Use when the user asks to add, change, or roll back database
  tables, columns, or indexes, or mentions "migration".
license: MIT
allowed-tools: ["run_in_terminal"]
---

# Database Migrations

## When to use this
Use whenever schema changes are needed.

## Steps
1. Create a migration file in `db/migrations/` using `npm run migrate:make <name>`.
2. Write the `up` and `down` functions. Every `up` MUST have a matching `down`.
3. Run `npm run migrate:latest` to apply, and verify with `npm run migrate:status`.
4. Never edit a migration that has already run in production — create a new one.

See [the rollback checklist](./references/rollback.md) for production rollbacks.

The frontmatter fields

FieldRequired?What it does
nameYesA unique identifier. Must be lowercase, words separated by hyphens (e.g. database-migrations).
descriptionYesThe single most important field — it’s what Copilot reads to decide whether to use the skill (see 12.4). Describe what it does and when to use it.
licenseNoLicense for the skill (useful when sharing publicly).
user-invocableNoControls whether a user can invoke the skill directly by name.
disable-model-invocationNoIf set, stops Copilot from auto-selecting the skill on its own (so it only runs when explicitly invoked).
allowed-toolsNoLists tools Copilot may use without asking for confirmation each time while running this skill.

The body (everything after the frontmatter) is the detailed instructions — the actual know-how. Write it like documentation for a competent new hire: clear steps, examples, and any “never do X” warnings.


12.3 The skill directory: more than one file

A skill is a folder, and SKILL.md can point to supporting files that load only when needed:

database-migrations/
├── SKILL.md                 ← required: the entry point
├── references/
│   └── rollback.md          ← extra docs, loaded only if referenced
├── resources/
│   └── migration-template.js ← templates / reusable assets
└── scripts/
    └── verify-schema.sh      ← runnable helper scripts

In SKILL.md you reference these with relative paths, e.g. [the rollback checklist](./references/rollback.md) or run ./scripts/verify-schema.sh. Copilot only pulls a referenced file into context (or runs a script) at the moment it actually needs it. This is the third tier of progressive disclosure, explained next.


12.4 How Copilot decides which skill to load (the key mechanism)

This is the question at the heart of your request. The answer is a three-stage process called progressive disclosure (also called staged loading). The whole point is to avoid stuffing every skill’s full text into the limited context window.

   L1: Discovery      L2: Instructions       L3: Resources
   (name + desc)  ──► (full SKILL.md body) ──► (referenced files / scripts)
   always loaded      loaded if description    loaded only when the body
   for every skill    matches the task         actually references them

Level 1 — Discovery (cheap, always on)

At the start, Copilot loads only the name and description of every available skill — not the bodies. These are tiny, so even with many skills installed, the cost to the context window is small. At this stage the agent essentially holds a menu: “here are the skills I could use, and a one-line description of each.”

Level 2 — Instructions (loaded on a match)

When you make a request, Copilot compares your prompt (and the task it has inferred) against each skill’s description. If a description matches what you’re trying to do, Copilot then loads that skill’s full SKILL.md body into context — and only then does it have the detailed steps. If nothing matches, no skill body is loaded and no context is wasted.

Level 3 — Resource access (loaded on demand)

As Copilot follows the now-loaded instructions, it reads referenced files (references/, resources/) or runs scripts only when the instructions point to them. A 50-page reference doc costs nothing until the moment it’s actually needed.

So, precisely: Copilot decides which skill to load by matching your request against each skill’s description field. The name and description are the only things visible during selection; the body and resources stay out of context until chosen. This is why writing the description well is the single highest-leverage thing you can do.

When multiple skills match

If several descriptions could fit, Copilot picks the most relevant one — generally the one whose description most specifically matches the task. Vague, overlapping descriptions cause the wrong skill (or no skill) to fire; specific, distinct descriptions make selection reliable.

Two ways a skill gets invoked

  1. Model-invoked (automatic): Copilot selects it based on the description match, as described above. This is the default.
  2. User-invoked (explicit): you can call a skill directly by name (when user-invocable is enabled), forcing its use regardless of the model’s judgment. Setting disable-model-invocation makes a skill only runnable this explicit way.

12.5 Writing a description that triggers reliably

Because the description is the entire basis for selection, treat it as a precision tool:

  • State what it does AND when to use it. “Create and run database migrations. Use when the user mentions migrations, schema changes, or adding/altering tables.” The “use when” part is what matches user phrasing.
  • Include trigger words and synonyms. Users say “migration,” “schema change,” “alter table,” “new column” — cover the phrasings they’ll actually use.
  • Be specific and distinct from your other skills. If two skills sound similar, Copilot may pick wrong. Make each one’s territory unambiguous.
  • Keep it to a few sentences. It’s loaded for every skill at L1, so bloated descriptions tax the context budget across the board.

A good test: read only your descriptions (not the bodies) and ask, “Given a user request, could I pick the right skill from these alone?” If not, neither can Copilot.


12.6 Where skills live and how they’re shared

  • Personal skills live in your user profile/config so they follow you across projects.
  • Project skills live in the repository (committed), so the whole team shares them — typically under a skills directory in .github/ or the repo, depending on the tool.
  • Skills are shareable artifacts. GitHub maintains the community awesome-copilot collection of ready-made skills, instructions, and prompts you can drop in.

Because a skill is just a folder of Markdown (plus optional scripts), it’s version-controlled like any other code, reviewed in PRs, and improved over time — the same discipline as custom instructions.


It’s easy to confuse the customization mechanisms. Quick contrast:

  • Custom instructions (Module 11): always-on, broad rules. Loaded every request.
  • Prompt files (Module 11): reusable commands you invoke to kick off a task.
  • Skills (this module): on-demand expertise auto-selected by description match; can include scripts and references; loaded progressively.
  • MCP servers / tools: connect Copilot to external systems and actions (databases, APIs). Skills tell Copilot how to do something; tools give it capabilities to act. They complement each other (a skill can list allowed-tools).

Try it yourself

  1. Create a folder my-skill/ with a SKILL.md containing name and a sharp description (“Use when the user wants to … ”) plus a few steps in the body.
  2. In an agent-mode session, make a request that matches the description and watch Copilot pull the skill in.
  3. Now make a request that doesn’t match — confirm the skill stays out of the way.
  4. Add a references/notes.md file and link it from SKILL.md; trigger the skill and see the reference load only when reached.
  5. Tighten the description with trigger words and test whether selection becomes more reliable.

Key takeaways

  • A skill is a folder with a SKILL.md (YAML frontmatter + instructions body) and optional references/, resources/, and scripts.
  • Required frontmatter: name (lowercase-hyphenated) and description; optional fields control invocation and allowed tools.
  • Copilot decides which skill to load by matching your request against each skill’s description — the only field visible during selection.
  • Progressive disclosure (L1 name+description → L2 full body on match → L3 resources on demand) keeps many skills from overflowing the context window.
  • A precise, trigger-rich, distinct description is the highest-leverage thing you can write.

Sources

Next: Module 13 — Context & Memory