copilot-instructions.md: what it is and what to put in it
Fill it in and copy it Open in the editor Opens as copilot-instructions.md, ready to edit. Nothing is uploaded.
The shape of it — edit here, or open the full template
Result
Runs entirely in this tab. Open the full editor to work on a real document.
Fill it in and take it
The whole file is below. Type into the boxes to replace the placeholders, then copy it or save it — nothing is sent anywhere, and there is nothing to sign up for.
<!--
.github/copilot-instructions.md
GitHub Copilot reads this automatically for every request in the repository.
Keep it short — it is prepended to each request, so length costs you on every
single one.
If the repository already has an AGENTS.md, do not copy it here. Point at it:
See AGENTS.md — it is the source of truth for this repository.
-->
# Copilot instructions
## What this project is
One or two sentences. What it does, and who uses it.
## Stack
- TypeScript, strict mode
- React 19, function components only
- Postgres via Drizzle — no raw SQL outside `src/db/`
## Commands
```sh
npm run dev # dev server on :3000
npm test # must pass before committing
npm run lint # eslint + prettier, autofixes
```
## Conventions
- Named exports; no default exports
- Tests live beside the file they test, as `*.test.ts`
- Errors are returned, not thrown, in `src/lib/`
- Every bug fix gets a regression test that fails before the fix
<!-- Be specific rather than emphatic. "Write good tests" is a sentiment;
"every bug fix gets a failing test first" is checkable. -->
## Do not
- Edit anything in `src/generated/` — it is rebuilt by `npm run codegen`
- Add a dependency without asking
- Change the public API in `src/index.ts` without a deprecation path
## Things that will bite you
<!-- The section most worth filling in and most often left empty, because the
traps are obvious to whoever already knows them. -->
- `src/lib/legacy-parser.ts` looks dead. It is load-bearing for two large
customers.
- The dev server proxies `/api` to staging. That data is real.
- Migrations are irreversible in production.
.github/copilot-instructions.md is a Markdown file that GitHub Copilot reads
automatically for every request made in that repository. Commit it and it
applies — there is nothing to switch on.
It holds the things Copilot cannot infer from the code in front of it: which commands to run, which conventions are house style rather than accident, and which directories must not be touched.
Length is a running cost
This is the difference between this file and a README. A README is read once by a person. This one is prepended to every request, so every extra paragraph is paid for continuously and crowds out the code that was actually being asked about.
A page is generous. If it is growing past that, the content probably belongs in documentation the model can be pointed at instead.
If you already have an AGENTS.md, point at it
See AGENTS.md — it is the source of truth for this repository.
Repositories that keep two copies end up with two different answers, and the one being read is rarely the one that was updated. AGENTS.md exists precisely so that this file can be one line long.
Be specific, not emphatic
The rules that get applied unevenly are the vague ones:
- Write clean, maintainable code.
against
- Named exports only. No default exports.
- Errors are returned, not thrown, in src/lib/.
The first is a sentiment and cannot be checked. The second is a rule. The same goes for emphasis — a file where four rules are marked critical reads as a file with no priorities.
Scoping rules to directories
.github/instructions/*.instructions.md files take an applyTo glob in their
front matter, so a rule can apply to src/api/** and nowhere else. Useful in a
monorepo where the frontend and the backend disagree about everything.
Start with the single repository-wide file. Split it when you find yourself writing “in the API package, though”.
The section people skip
“Things that will bite you” is the most valuable heading in any of these files and the one most often left empty, because the traps are invisible to whoever already knows them. The file that looks abandoned and is load-bearing. The dev server that proxies to real data. The migration that cannot be undone.
Every line there is something that would otherwise be discovered the expensive way.
Common questions
- Where does the Copilot instructions file go?
- `.github/copilot-instructions.md` in the repository root. Copilot picks it up automatically once it is committed — there is nothing to enable, and no way to point it at a different path.
- How long should it be?
- Short. The file is prepended to every request in the repository, so length is a cost paid continuously rather than once. A page is generous; several pages start crowding out the thing you actually asked about.
- What if I already have an AGENTS.md?
- Do not duplicate it. Put one line in the Copilot file pointing at AGENTS.md as the source of truth. A copy has to be maintained and will drift; a pointer cannot.
- Can I have different instructions per directory?
- Yes — `.github/instructions/*.instructions.md` files carry an `applyTo` glob in their front matter, so a rule can be scoped to `src/api/**` rather than to everything. The single repository-wide file is the simpler starting point.
- Why are my instructions being ignored?
- Usually because they are vague. "Write clean code" gives nothing to act on, while "named exports only, no default exports" does. Rules that are emphatic rather than specific are the ones that get applied unevenly.