GitHub Copilot Prompt Files Tutorial
A prompt file is a task you have written down: a Markdown file containing a prompt you invoke deliberately, rather than a rule that applies automatically.
If instructions are “always do it this way”, a prompt file is “here is how we do this particular job”.
Key takeaways
- Location:
.github/prompts/*.prompt.md. The double extension is required. - Documented frontmatter keys:
description,agent,model,tools. All optional; do not invent others. - Three IDEs. Plan for colleagues who cannot use them.
- A prompt file is invoked, not automatic. That is the whole distinction from instructions.
- Version-controlled and reviewable, which is most of the value for a team.
Where they live
.github/prompts/, with the .prompt.md extension. A file named tests.md in
that directory is not a prompt file, and neither is one at .vscode/prompts/ —
both fail silently rather than reporting anything, which makes a wrong path an
annoying thing to debug.
Support, precisely
| Mechanism | GitHub.com Chat | VS Code | Visual Studio | JetBrains IDEs | Eclipse | Xcode | Copilot CLI | Copilot cloud agent | Copilot code review |
|---|---|---|---|---|---|---|---|---|---|
| Repository-wide instructions | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Prompt filesPublic preview | No | Yes | Yes | Yes | No | No | No | No | No |
The contrast is the useful part. Repository instructions reach all nine surfaces; prompt files reach three.
The file format
Markdown with optional YAML frontmatter.
---
description: Generate unit tests for the selected code
---
Generate tests for the selected code.
Requirements:
- Cover normal behaviour, boundary conditions, and expected failures.
- Follow the existing test conventions in this repository.
- Assert specific values or exception types, not just that something
was returned.
- Do not change production code unless it is required to make an
existing bug explicit — and say so if you do.
After writing the tests, tell me which one would fail first if the
implementation were subtly wrong.The body is the prompt. Everything you know about writing good prompts applies: state the goal, the constraints, and what should come back.
The frontmatter keys
Four keys are documented:
| Key | Purpose |
|---|---|
description | What the prompt does. Shown when choosing it. |
agent | Which agent the prompt runs against. |
model | Pin a specific model for this task. |
tools | Restrict which tools the prompt may use. |
All are optional. description is worth always setting — it is what you see when
choosing between prompts, and an unlabelled list of filenames is not a library.
Writing your first one
Pick something you already do repeatedly. The test is whether you have typed substantially the same prompt three times — before that, you do not yet know what the prompt should say, and writing it early means writing a guess.
Good first candidates: generating tests, reviewing a diff for a specific concern, writing a docstring in your house style, drafting a pull request description.
Create .github/prompts/review-security.prompt.md:
---
description: Review changes for security problems
---
Review the current changes for security problems only.
Look for:
- User input reaching a query, a file path, a subprocess, or a
deserialiser without validation
- Credentials or tokens in source, configuration, or test fixtures
- Authentication or authorisation checks that are missing or happen
after a side effect
- Unsafe defaults: permissive CORS, disabled verification, debug mode
For each finding give the file, the line, what an attacker could do,
and how confident you are.
Separate what you verified by reading the code from what you are
inferring from a pattern.
If you find nothing, say so plainly. Do not manufacture findings.Two things in that are worth copying into any prompt file you write.
“Separate verified from inferred.” Pattern-matched findings and confirmed findings look identical in output unless you ask for the distinction.
“If you find nothing, say so.” Without it, a review prompt tends to produce marginal findings rather than reporting that things look fine — because reporting nothing feels like failing the task.
Invoking one
Prompt files are triggered manually. In the supported IDEs, that is through the chat interface’s prompt selector — the exact affordance differs between VS Code, Visual Studio and JetBrains, and JetBrains additionally offers an Agent Customizations editor for managing customizations in one place.
The important conceptual point is the trigger. Instructions apply because they exist; prompt files apply because you asked. That difference is what makes them suitable for tasks that would be wrong to apply automatically — and it is also why a prompt file that nobody invokes has no effect at all, which is a failure mode instructions do not share.
Four more worked examples
The security review above is one shape. Here are four others, each showing a different technique worth stealing.
Generating tests, with a self-check
---
description: Generate tests for the selected code
---
Generate tests for the selected code, following the conventions in
this repository's existing tests.
Cover: a typical valid input, an empty value, a boundary value, an
invalid type, and the failure mode most likely in production.
Assert specific values or exception types, not merely that something
was returned.
Then, for each test you wrote, tell me what change to the
implementation would make it fail. If a test would still pass with
the logic inverted, say so — that test is not testing anything.The final paragraph is the technique. Generated tests frequently assert that the implementation is the implementation, and that defect is invisible in coverage numbers. Asking the model to check its own work catches a useful fraction of it.
A pull request description
---
description: Draft a pull request description from the current branch
---
Write a pull request description for the changes on this branch.
Cover: what problem this solves, the approach taken, anything a
reviewer should look at particularly carefully, and how it was
tested.
Then tell me which part of this diff you found hardest to reason
about — that is where a human reviewer is most likely to skim.
Be honest about anything incomplete. Do not describe work that is
not in the diff.“Which part was hardest” is a signal you cannot easily get another way, and it is a good predictor of where defects survive review.
Documenting in a house style
---
description: Document a function in this project's style
---
Write a docstring for the selected function.
Format: a one-line summary, a blank line, an `Args:` section with
one line per parameter, a `Returns:` section, and a `Raises:`
section listing each exception and the condition that triggers it.
Document what the code actually does. If the behaviour differs from
what the function name implies, say so rather than documenting the
intent.The last instruction turns documentation writing into a review, which regularly finds real bugs.
Pinning a model for a heavy task
---
description: Deep review of a complex change
model: Claude Opus 4.8
---
Review this change carefully for correctness.
Work through the logic step by step rather than pattern-matching.
Consider what happens at boundaries, under concurrency, and when
inputs are absent rather than merely wrong.
State your reasoning before your conclusions.Pinning a model in frontmatter is worth doing only when the task genuinely benefits from it — a reasoning-heavy review, for instance. Pinning for routine work costs flexibility and ages badly, since models retire and a prompt file naming a retired model will need editing.
Prompt file, instruction, or agent?
Three mechanisms, and the choice is about when it applies and whether the model can decline.
| Mechanism | Applies | Can the model ignore it? |
|---|---|---|
| Instructions | Automatically, in scope | Yes — it is guidance |
| Prompt file | When invoked | Yes — it is a prompt |
| Custom agent | When selected | Tool restrictions: no |
A rule that must hold on every request is an instruction. A task you repeat is a prompt file. A role that must be unable to do something is a custom agent, because only a tool restriction is enforced rather than requested.
The commonest mistake is putting a task in an instruction file, where it applies to every request forever. The second commonest is writing a prompt file for something that should always happen, which then only happens when someone remembers to invoke it.
The invocation model, and why it matters
The distinction between automatic and invoked is not a technicality; it changes what belongs in each.
Something that applies automatically must be true in every situation the scope covers. That is a demanding requirement, and it is why good instruction files are short — most rules that seem universal turn out to have exceptions, and a rule with exceptions applied universally causes friction.
Something invoked has no such constraint. A prompt file can be aggressive, specific, and appropriate only in narrow circumstances, because it only runs when someone decided those circumstances apply. “Review this exclusively for concurrency bugs and ignore everything else” is a terrible instruction and an excellent prompt file.
That freedom is the real argument for prompt files. It lets you write the focused, opinionated version of a task that you would never impose on every request — and focused prompts produce better output than general ones, which is the finding underneath most of this cluster.
Designing prompt files that stay useful
Give each file one job. A prompt file that reviews security, writes tests and updates documentation is a general-purpose prompt with extra steps. Narrow files produce predictable output, which is what makes them reusable.
Name them for the task. generate-tests beats helper. The filename is half
the discoverability.
Say what “done” looks like. Specify the output format — what a finding contains, how confidence is expressed, what to do when there is nothing to report.
Keep them short. The same context arguments apply as for instructions. A 600-word prompt file competes with the code it is meant to be reasoning about.
Do not encode secrets or environment specifics. These files are committed and readable by everyone with repository access, and they are included in context when invoked. Policy belongs in them; credentials and internal hostnames do not.
A small starting library
Six files cover most of what a team repeats:
That is deliberately small, and the restraint is the point rather than a limitation of the example. The prompt library lesson covers growing this into something a team maintains — and argues that six good files beat sixty, for reasons that are mostly about discoverability.
Why write them down at all
A reasonable objection: if a prompt file is just a prompt, why not keep prompts in a note and paste them?
Four reasons, and they are all about the team rather than about you.
Review. A prompt in your notes is your opinion. A prompt in the repository went through a pull request, which means someone else read it and agreed. For anything that shapes how code gets written, that difference matters — a review prompt that misses a whole category of problem is worth catching before it becomes the team’s default check.
History. When a prompt file improves, the improvement is a commit with a reason attached. Six months later you can see why the security review prompt gained a clause about deserialisation, which is usually because something got through.
Consistency. Two developers using the same prompt produce comparably-shaped output. Two developers with their own remembered version of a prompt produce output that differs in ways nobody can account for.
Discoverability. A new colleague can read .github/prompts/ and see how the
team works. They cannot read your notes.
None of this is unique to prompt files — the same argument applies to instruction files, and to anything else that encodes how a team operates. It is simply unusually visible here, because prompts feel personal in a way that configuration does not.
The maintenance question
Written-down prompts rot in the same way instructions do, and slightly faster, because they encode assumptions about tooling.
A prompt file that says “run pytest and report the output” survives a migration
from pip to uv without noticing. One that names .venv/bin/python -m pytest
does not, and it will fail quietly by producing a suggestion nobody can run.
Three habits keep a small library healthy.
Update prompt files in the same pull request as the change that broke them. This is the same rule as for instructions and it fails in the same way when treated as follow-up work.
Delete aggressively. A prompt file nobody has invoked in three months is either undiscoverable or unnecessary. Both are solved by removing it — and if it turns out to have been useful, git remembers.
Notice when someone works around one. If a colleague habitually types their own version of a prompt you have a file for, the file is wrong. That is useful feedback and it arrives for free.
What prompt files cannot do
Being clear about the boundaries prevents disappointment.
They do not apply automatically. If something must happen on every request, a prompt file is the wrong mechanism no matter how well written. That is what instructions are for.
They do not restrict what the model can do. The tools key limits which tools
a prompt may use, which is genuinely useful, but the prompt body remains a
request. “Do not modify production code” in a prompt file is advice, not a
guarantee — the enforcement version is
a custom agent with a restricted tool list.
They do not travel to unsupported surfaces. Three IDEs. A colleague on the CLI gets nothing from your library, which is worth knowing before you invest a week in one.
They are not templates with variables in the programming sense. Whatever
placeholder convention you adopt — [BRACKETS] in this cluster’s
100-prompt reference — is a note to the
human, not syntax the system substitutes.
Preview status, and what it means for you
Being in public preview has three practical consequences.
The syntax may change. Frontmatter keys could be added, renamed, or given new meanings. This is why the four documented keys are worth sticking to.
Support may widen or narrow. Three IDEs today. That number has more room to grow than shrink, but neither is promised.
Anything you build carries maintenance. Not a reason to avoid prompt files — a reason to keep the preview-dependent part small enough that losing it would be an inconvenience rather than a rebuild.
The hedge that works: put the rules you cannot do without in repository instructions, which are GA and universally supported, and use prompt files for the convenience layer on top. If prompt files changed tomorrow, your standards would survive.
Rolling them out to a team
A prompt library that one person wrote and nobody else uses is a common outcome, and it is avoidable.
Start from observed repetition, not from imagination. The prompts worth writing down are the ones people are already typing. Ask colleagues what they find themselves asking Copilot repeatedly; the answers are your first three files.
Introduce them where the work happens. A prompt file for pull request descriptions is discovered when someone is writing a pull request description, not when they read a wiki page about the prompt library. Mentioning it in a review comment once is worth more than announcing it.
Accept that adoption is partial. Three IDEs, and within those, people who prefer their own phrasing. That is fine. The library does not need universal adoption to be worth having — it needs to be better than nothing for the people who use it.
Watch for the file that becomes policy by accident. A review prompt everyone runs becomes, in practice, the team’s definition of what gets reviewed. That is a reasonable outcome and it should be a deliberate one: the moment a prompt file is load-bearing, it deserves the same scrutiny as a linting rule.
Frequently asked questions
Do prompt files replace instructions? No, and they are not competing. One applies automatically and one is invoked. Most teams want both, and the rules that matter belong in instructions because those work everywhere.
Can a prompt file reference another one? Nothing documented supports that. Keep each file self-contained.
Do they work with the coding agent? Not per current documentation — the three supported surfaces are VS Code, Visual Studio and JetBrains.
Should I pin a model in every file? No. Pin one where the task genuinely needs a particular capability, and leave the rest flexible. A pinned model is a maintenance obligation, because models retire.
What happens if the frontmatter is wrong? An unrecognised key is ignored rather than reported, which means a misconfigured file looks fine. This is the strongest argument for using only the four documented keys.
Next
Building a prompt library turns these files into something a team owns and reviews. Custom instructions covers the always-on counterpart, and 100 prompts is a source of material — anything there you reach for weekly is a prompt file waiting to be written.
Put this into practice
8-minute exercise
Turn a repeated request into a prompt file
- Think of a request you have typed more than twice this month.
- Write it as a prompt file, with the constraints you always end up adding afterwards.
- Invoke it on a file it has never seen.
How you know it worked The output already includes the constraints you would have had to ask for. If you still had to follow up, the missing constraint belongs in the file.
Sources
Every version-sensitive claim on this page was checked against first-party documentation. Only sources actually used are listed.
Your progress
Saved in this browser only. No account, no server, and nothing leaves your device. Clearing site data resets it.Sync across devices if you want it everywhere.
Saved in this browser and synced to your account, so it follows you between devices. Manage or delete it.
Was this lesson helpful?
We record which lesson you rated and whether it helped. Nothing identifies you — no account, no cookie, no session.