Skip to content

GitHub Copilot Prompt Files

Lesson 7 of 8Intermediate11 min readGitHub Copilot & AI Engineering · GitHub CopilotVerified: GitHub Copilot prompt files documentation and customisation cheat sheet, September 2026

A prompt file is a prompt you wrote once and can run again.

That is genuinely useful for tasks you repeat — generating a test suite, writing a security review, producing release notes — where the good version of the prompt took several attempts to arrive at and you would rather not rediscover it each time.

It is also the Copilot mechanism with the narrowest surface support, which is the first thing to establish before building anything on it.

Prompt files live in .github/prompts/ and are named *.prompt.md. They are Markdown with YAML frontmatter.

.github/prompts/generate-tests.prompt.md
---
description: Generate a pytest suite for a module, following project conventions
model: gpt-5
---
Generate a pytest test suite for the attached module.
Requirements:
- Use pytest with fixtures from `tests/conftest.py`. No unittest classes.
- Cover: the happy path, empty and null inputs, boundary values, and each
error branch that raises.
- Use the `db_session` fixture for anything touching the database.
- Name tests `test_<function>_<condition>`.
- Do not test private functions directly.
For each test, add a one-line comment saying what behaviour it protects.
After generating, list any behaviour you were unable to test and why.

The body is the prompt. The frontmatter carries metadata — a description, and where supported a model to use for this task.

The last two instructions are the interesting ones. Asking for a comment per test makes the output reviewable; asking what it could not test surfaces coverage gaps rather than hiding them.

Prompt files are invoked deliberately — you choose to run one, typically from the chat interface, and attach whatever context the task needs.

That is the defining property and the source of most confusion about them:

LoadedYou decide
InstructionsAlwaysOnce, when you write them
Prompt filesWhen invokedEvery time
SkillsWhen judged relevantThe agent decides

Instructions describe how to work here. Prompt files describe a task to perform. “Use pytest” is an instruction. “Generate a test suite for this module” is a prompt file.

The test: is this a prompt you have written more than twice?

Good candidates:

Test generation, with your conventions baked in.

Security review of a diff, with the categories you care about.

Architecture explanation, in the format your team writes them.

Release note drafting, with your sections and audience.

Migration review, checking the specific things migrations must satisfy in your system.

Onboarding a module — the standard set of questions somebody asks about unfamiliar code.

Poor candidates:

One-off tasks. The prompt file is overhead if you run it once.

Anything that is really a convention. “Always use tabs” is an instruction.

Anything that needs to work outside an IDE. Not supported.

Anything that needs tools or a specific persona. That is a custom agent or a skill.

The same principles as any prompt, made durable.

Be specific about the output format. A prompt file is worth having partly because it produces consistent output. Say what shape you want.

Include your conventions explicitly. Even where repository instructions cover them — a prompt file that stands alone is more portable and less dependent on what else is loaded.

Ask for the gaps. “List what you could not do and why” is the highest-value line in most prompt files. It converts silent incompleteness into a stated limitation.

Ask for citations where the task involves reading. “Name the file for each claim” makes the output checkable.

Keep it focused. A prompt file that does four things does none well. Four files are better than one that branches.

A prompt file produces output that varies between runs, which makes “does it work” a slightly different question from usual.

Run it three times on the same input. The variation between runs tells you how much the file is actually constraining. High variation means the instructions are too loose — the model is filling gaps with its own choices, and those choices differ.

Run it on input it should handle badly. A test-generation prompt given a module with no clear behaviour should say so rather than inventing tests. A review prompt given a clean diff should report nothing rather than manufacturing findings. Both are failure modes worth checking for, and both are common: a prompt asking for findings tends to produce findings.

Have somebody else run it. The author knows what to attach and what the output should look like. A colleague running it cold reveals every assumption the file makes.

Check the negative case explicitly. The instruction “if you find nothing in a category, say so” exists partly to make this testable — you can tell the difference between “checked and clean” and “did not check”.

None of this is elaborate. Three runs and a colleague is twenty minutes, and it is the difference between a prompt file that works for you and one that works.

Worth deciding deliberately, because it determines how much to invest.

If your team is entirely in supported IDEs, prompt files are a good fit and the preview status is the main caveat.

If some work happens in the terminal or on github.com, a prompt file covers part of your workflow and silently does nothing for the rest.

If the capability needs to work for agents, including code review and the cloud agent, the mechanism you want is an agent skill — which has broader support and is loaded when relevant rather than invoked.

A reasonable rule: prompt files for personal and team IDE workflows; skills for anything that needs to work where agents run. The two overlap in what they can express, and differ entirely in where they apply.

Security review of a diff:

.github/prompts/security-review.prompt.md
---
description: Review a diff for the security issues that matter in this codebase
---
Review the attached diff for security issues, in this order:
1. Input reaching a query, command, path or template without going through the
helpers in `security/sanitise.py`.
2. New endpoints without an authorisation decorator.
3. Secrets or credentials in code, config or test fixtures.
4. Logging of request bodies or personal data.
5. New dependencies — name them and say what they are for.
For each finding: the file and line, why it matters here, and a suggested fix.
If you find nothing in a category, say so explicitly rather than omitting it.

Explaining a module:

.github/prompts/explain-module.prompt.md
---
description: Structured explanation of an unfamiliar module
---
Explain the attached module:
- What it is responsible for, in two sentences.
- What calls into it, and what it calls out to.
- The three things a new engineer would most likely get wrong here.
- Anything that looks like a workaround, with the file and line.
For each claim, name the file it comes from. Where you are inferring intent
rather than reading it, say so.

Reviewing a migration:

.github/prompts/review-migration.prompt.md
---
description: Check a database migration against our rules
---
Check the attached migration:
- Is it reversible? Is the `down` operation correct, not just present?
- Does it drop or rename a column that code still references?
- Does it add a NOT NULL column without a default or backfill?
- Does it create an index non-concurrently on a large table?
- Would it lock a table for a meaningful period under production load?
State each check and its result. Do not skip checks that pass.

Drafting release notes:

.github/prompts/release-notes.prompt.md
---
description: Draft customer-facing release notes from a commit range
---
From the attached commit range and pull request list, draft customer-facing
release notes.
- Group into: Breaking changes, New features, Bug fixes, Security.
- Omit anything a user cannot observe — internal refactors, test changes,
build tooling.
- For anything that alters a default, tightens validation or changes an error
type, flag it under Breaking changes for me to confirm.
- Keep it under fifteen bullets. If there are more, tell me what you cut.

The pattern across all four: explicit categories, an explicit request for what was not covered, and a statement of what to do when uncertain rather than a general request for a good job.

A directory of prompt files is a small codebase, with the same failure modes.

They go stale. A test-generation prompt referencing a fixture you renamed produces output that does not run. Nothing tells you — the prompt still executes, it just produces something wrong. Prompts that reference specific files or conventions need the same review as documentation.

They accumulate. Twelve prompt files of which three are used is a directory nobody can navigate, and the three good ones are harder to find. Delete the ones nobody runs.

They duplicate instructions. A prompt file restating every convention from copilot-instructions.md is two places to update. Some restatement is deliberate — it makes the file self-contained — but it should be a choice rather than an accident.

They encode one person’s preferences. A prompt file committed to the repository shapes everyone’s output. That is either useful standardisation or an imposition, and which one it is depends on whether anybody else was asked.

The maintenance that works: review them when the thing they reference changes, and treat the directory as something with an owner. A prompt file is closer to a script than to a note.

Where the IDE supports it, prompt files can take input rather than being entirely fixed — a task parameter supplied at invocation time.

That matters for the difference between a prompt file that works on one thing and one that works on a category. “Generate tests for the attached module” relies on you attaching the right file. A parameterised version can be explicit about what it expects, which makes it more reliable when somebody else runs it.

The general principle is worth applying regardless of the mechanism: state what the prompt expects to be given. A prompt file beginning “given the attached diff” tells the next person what to attach; one that assumes context produces confusing results when the assumption does not hold.

The support for parameterisation differs by IDE and is evolving, which is a reason to keep prompt files simple. A file that depends on an advanced feature works for the person who wrote it and fails quietly for a colleague on a different editor.

Concretely, in a day’s work.

Before opening a pull request. The security review prompt on your own diff, before anybody else sees it. This is self-review with a consistent checklist rather than whatever you remember to look for.

When picking up unfamiliar code. The explain-module prompt, which produces the same structured answer every time and is therefore comparable across modules.

When a specific kind of change appears. The migration prompt when there is a migration; the dependency prompt when a manifest changed. These are the ones worth having because the checks are easy to forget and specific to the situation.

At release time. The release-notes prompt, as a first draft. See AI-generated release notes for what to do with it.

What they do not fit: anything continuous. A check that should run on every change is a lint rule, a test, or a code review instruction — all of which run without anyone remembering to invoke them.

That is the honest limit of the mechanism. A prompt file requires a human to decide to run it, which means its coverage is exactly as good as the habit around it.

Assuming they work everywhere. IDE-only, and in preview.

Using one where an instruction belongs. A convention that should always apply is an instruction.

Using one where a skill belongs. If it needs to work for agents or in the CLI, it is a skill.

Writing them speculatively. Write the file after the third time you type the prompt.

Making one do four things. Four focused files beat one that branches.

Omitting the output format. Consistency is half the reason to have the file.

Not asking what was missed. Silent incompleteness reads as completeness.

The underrated benefit, and the argument for committing them rather than keeping them personal.

A well-written prompt file is a checklist somebody thought about carefully, expressed in a form that gets applied consistently. The migration review example above is not really a prompt — it is the list of things that have gone wrong with migrations in this system, written down.

That has value independent of the AI:

It is documentation of what matters. A new engineer reading review-migration.prompt.md learns five real constraints faster than from any onboarding document, because each one exists for a reason.

It survives the person. The engineer who knows that non-concurrent index creation locks the orders table will eventually leave. The prompt file does not.

It is reviewable. A pull request adding a check to a review prompt is a conversation about whether that check is right, which is a better conversation than the one that happens after the incident.

It converges practice. Everybody running the same review prompt applies the same criteria, which is consistency that is otherwise hard to achieve.

The corollary is that the prompt files worth writing are the ones encoding hard-won specific knowledge, not the ones encoding general good practice. A file saying “check for SQL injection” is generic. A file saying “check that input reaching a query goes through security/sanitise.py, which is the only place parameterisation is guaranteed” is knowledge.

A prompt file is a saved prompt with a name. Instructions say how to work in this repository; a prompt file says do this particular job, the way we do it — and you decide when to run it.

  • Prompt files live in .github/prompts/*.prompt.md with YAML frontmatter
  • They are in public preview and work in VS Code, Visual Studio and JetBrains only
  • They do not work on github.com or in Copilot CLI
  • Instructions are always on; prompt files are invoked; skills load when judged relevant
  • Write one after the third time you have typed the prompt, not before
  • Specify the output format, and ask explicitly for what could not be covered
  • Skills are the mechanism when the capability must work where agents run
  • Four focused prompt files beat one that branches

Use a repository open in a supported IDE.

  1. Do a task ad hoc — generating tests for a module. Note what you had to add to the prompt to get a usable result.

  2. Write those additions into .github/prompts/generate-tests.prompt.md.

  3. Run it on a different module. Predict: does the output need the same corrections?

  4. Add “list anything you could not test and why” and run again. Predict: does it surface a real gap?

  5. Try invoking the prompt file from Copilot CLI. Predict: what happens?

  6. Move one rule from the prompt file into .github/copilot-instructions.md. Ask a normal chat question that would exercise it. Predict: which mechanism was the right home for that rule?

AI-assisted engineering learning pathEleven lessons on getting value from Copilot and agents without giving up review discipline.