Build Team Coding Standards with GitHub Copilot Instructions
Most teams already have coding standards. They are in a wiki nobody opens, a style guide from two reorganisations ago, and the accumulated knowledge of whoever has been there longest.
Copilot instruction files change what those standards are for. A rule in a wiki
is applied when someone remembers it. A rule in .github/copilot-instructions.md
is applied on every request, by everyone, without anyone remembering anything.
That is a genuine upgrade, and it comes with an obligation. A standard that executes needs to be correct, current and short in a way a wiki page never did — because a wrong rule in a wiki is ignored, and a wrong rule in an instruction file is followed.
Key takeaways
- Standards become configuration rather than documentation. Reviewed like code, versioned like code, deleted like code.
- Repository instructions reach every surface. Anything you cannot afford a colleague to miss goes there, not in a mechanism only three IDEs read.
- Encode the rules a linter cannot check. Anything automated is better enforced by the automation.
- Do not paste a hundred-page style guide. Twelve rules that get followed beat a document that gets averaged.
- Instructions are guidance. For things that must not happen, use enforcement.
The transformation
Two things about that chain matter.
Instructions carry only the durable subset. Not everything a team believes — the part that is stable, checkable, and would otherwise be retyped.
Validation and review are still there. Encoding standards does not remove the need to check output. It removes the need to restate the standards while checking, which is a different and smaller saving than teams sometimes expect.
Structuring it
Three layers, deliberately unequal in importance.
copilot-instructions.md carries what is true everywhere and is read by every
surface. This is where the standards that matter live.
instructions/*.instructions.md carry rules scoped by glob, for conventions
that differ by area.
prompts/*.prompt.md carry repeated tasks. Useful, and narrowest in reach.
| Mechanism | GitHub.com Chat | VS Code | Visual Studio | JetBrains IDEs | Eclipse | Xcode | Copilot CLI | Copilot cloud agent | Copilot code review |
|---|---|---|---|---|---|---|---|---|---|
| Personal instructions | Yes | No | No | Yes | No | No | Yes | No | No |
| Repository-wide instructions | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Path-specific instructions | No | Yes | Yes | Yes | No | Yes | Yes | Yes | Yes |
| Agent instructions (AGENTS.md) | No | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes |
| Organization instructions | Yes | No | No | No | No | No | No | Yes | Yes |
| Prompt filesPublic preview | No | Yes | Yes | Yes | No | No | No | No | No |
The matrix is why the layers are unequal. A rule in the first file reaches everyone. A rule in the third reaches colleagues using three specific IDEs. If your team spans editors — and most do — that difference decides what belongs where.
What to encode
Seven categories cover most of what a team actually needs.
Architecture. Where things go and what must not depend on what. “Business
logic belongs in src/services/. HTTP handlers stay thin. Handlers must not
contain database queries.”
Testing. Which framework, what coverage means here, what tests may not do. “Every behaviour change needs a test covering the failure case. Tests must not require network access.”
Error handling. “Never swallow an exception silently. If an error is caught and not re-raised, log it with context and say why in a comment.”
Dependencies. “Prefer existing dependencies. Explain any addition and wait for agreement.”
Security. “Never hard-code credentials. Validate any input reaching a query, a path, or a subprocess.”
Documentation. “Public functions need a docstring with parameters, return value and exceptions.”
Validation. What must happen before a change is complete, with actual commands.
Rules that work
The difference between a standard that changes behaviour and one that decorates a file is whether it names something concrete.
Works — names a command:
Run `.venv/bin/python -m pytest -q` and report the actual output.Works — names a boundary:
Business logic belongs in src/services/. Handlers must not query the
database directly.Works — names an action for the blocked case:
If a change appears to require a new dependency, stop and explain why
rather than adding one.Does not work:
Write clean, maintainable code.
Follow best practices.
Be careful with database migrations.The test is whether you could check compliance by looking at the output. If you cannot, neither can the model — and the rule is decoration.
Do not paste the style guide
The tempting move — take the existing hundred-page standards document and put it in the file — fails in a specific way.
The file competes for the same room as the code under discussion, and a long one competes with itself as well. Under pressure the early rules survive; the specific ones near the bottom — usually the hard-won ones — go first.
So the file carries the dozen rules that decide most reviews, and points at the rest. Volume is not thoroughness: past a certain length, adding a rule makes the existing ones less likely to be applied.
Prefer the rules a linter cannot check. If Ruff already rejects it, the linter is more reliable and the instruction is a second copy to keep in sync. Write down what tools cannot see: your architecture, your history, and the constraint that is obvious to everyone who has been on the team for a year.
Path-scoped rules
The clearest case for a second file is rules that would otherwise contradict.
---
applyTo: "tests/**/*.py"
---
# Test conventions
- Use pytest, not unittest.
- Cover the failure case, not only the success case.
- No network access. No writes outside tmp_path.
- Tests must be deterministic: no wall-clock time, no unseeded
randomness.
- Prefer real objects over mocks where the real object is cheap.That last rule would be wrong in application code and is right in tests. A single repository file cannot hold both without confusing its reader, including the model.
Which standards survive the translation
Not everything in a style guide belongs in an instruction file, and working out what does is most of the effort.
Rules a tool already enforces should stay with the tool. Line length, import ordering, trailing commas, quote style. A linter checks these deterministically and an instruction file checks them probabilistically. Writing them twice creates a second copy to keep in sync and buys nothing.
Rules that are genuinely about taste rarely survive. “Prefer descriptive variable names” is unfalsifiable and it consumes context on every request. If you cannot describe the failure it prevents, it is not a rule.
Rules with a history translate best. “Do not use the async client for short-lived requests — we hit connection pool exhaustion in March” carries a reason, a symptom, and a constraint. That is exactly the kind of knowledge that lives in people’s heads and disappears when they leave.
Structural rules translate well. Directory responsibilities, layering constraints, what may depend on what. These are checkable by looking at a diff and invisible to most tooling.
Process rules translate partially. “Run the tests before opening a pull request” is a good instruction for an agent and a poor one for a human, who should have CI doing it.
A first file, for a real team
Here is what a working repository file looks like after the pruning described above — a Python service, eleven rules.
# Project conventions
## Architecture
- Business logic belongs in `src/services/`.
- Route handlers in `src/routes/` parse, delegate and serialise. They
must not contain database queries or business rules.
- Anything shared between services goes in `src/common/`, not imported
service-to-service.
## Environment
- Python 3.12, virtual environment at `.venv`.
- Invoke tools as `.venv/bin/python -m <tool>`, never bare.
## Testing
- pytest. Every behaviour change needs a test covering the failure
case, not only the success case.
- Tests must not require network access.
- Do not modify an existing test to make a change pass. Fix the cause,
or stop and explain why the test is wrong.
## Error handling
- Never catch an exception and discard it. If you catch and do not
re-raise, log with context and explain why in a comment.
## Dependencies
- Prefer the standard library. Explain any new dependency and wait for
agreement before adding it.
## Validation
Before considering a change complete:
1. Run `.venv/bin/python -m pytest -q` and report the actual output.
2. Run `.venv/bin/python -m ruff check .` and fix what it reports.Notice what is absent: no formatting rules, because Ruff handles those. No aspirations. No sprint context. Nothing that a linter, a type checker or CI already enforces better.
Governance
Once standards are configuration, they need owning.
Someone is accountable. Not to write everything, but to notice when the file has grown to forty rules and prune it. Shared files with no owner drift toward whatever the most recent contributor preferred.
Changes go through review. A pull request editing
copilot-instructions.md changes how code gets written for everyone. That
deserves at least the scrutiny of a change to CI configuration.
Update in the same pull request as the change. Migrating from pip to uv
means the file changes in that pull request. Treated as follow-up work, it does
not happen, and the file starts lying.
Prune on a schedule. Files grow monotonically unless someone removes things. A rule encoding a convention the team abandoned is actively harmful — it argues confidently for something nobody believes, to whoever is least equipped to know better.
Resolve contradictions deliberately. If a repository rule and a path-scoped rule disagree, the model receives both and reconciles them unpredictably. That is a bug in your configuration, not in Copilot.
Where prompt files fit
The third layer is the one teams reach for first and should reach for last.
A prompt file is invoked, so it only applies when someone remembers. That makes it a poor home for a standard and a good home for a task — the team’s version of a code review, a test-generation request, a pull request description.
The relationship worth getting right: instructions carry the conventions, and prompt files carry tasks that assume those conventions are already in force. Written in that order, prompt files get shorter, because each one holds only what is specific to its job rather than restating your stack every time.
Written in the other order — library first — you end up with six prompt files each repeating the same four rules, and no single place to change them. The prompt library lesson covers this in more depth, including why six files beat sixty.
Testing whether standards took
Instruction files are easy to write and easy to leave unexamined. Three checks.
Ask the model to restate them. If it cannot summarise your rules, they are not loaded, too long, or ambiguous.
Which instruction files are you following, and what do they tell you to do before completing a code task?
Do not change any files.
Test a rule directly. Ask for something the standards forbid — adding a dependency — and see whether it pushes back. Summarising a rule and acting on it are different things.
Watch the corrections. A correction typed twice is a rule you have not written yet. A rule nobody can remember catching anything is one to cut. Both signals arrive free, in the ordinary course of review.
What changes for the team
Encoding standards has second-order effects worth anticipating, because some of them are genuinely good and one of them is a trap.
Onboarding gets faster. A new colleague inherits the team’s conventions from their first request, without having read anything. This is the largest practical benefit and the one people notice first.
Disagreements surface earlier. A rule in a file gets read and objected to. The same rule as tribal knowledge gets discovered in code review, repeatedly, by different people. Moving the argument to a pull request is a real improvement even when the argument is uncomfortable.
Standards become falsifiable. “We use pytest” in a wiki is a claim nobody tests. As an instruction that visibly shapes output, it either works or it does not, and you find out.
Review shifts. Reviewers stop restating conventions and start looking at whether the change is right. That is the shift worth aiming for, and it takes a few weeks to arrive.
The trap: standards that execute can drift from standards people believe. A rule added to the file and never discussed becomes the team’s default behaviour without anyone having agreed to it. That is how a single developer’s preference quietly becomes house style — and it is invisible, because nobody reads the file after the first week.
Multiple repositories
Most of this lesson assumes one repository. Teams with many face a genuine tension.
Duplication is the honest default. Copying the same eight rules into each repository is repetitive and it works. Each repository is self-describing, and divergence where repositories genuinely differ is easy.
Organization instructions handle the truly universal. Security policy, compliance requirements, licence rules — things that are the same everywhere by definition. Their reach is narrower than repository instructions, so they cannot carry everything.
Resist a shared file nobody owns. A generated or synced instruction file across thirty repositories becomes something no team feels responsible for, and it accumulates rules that are wrong for most of them.
The pattern that seems to hold up: organization instructions for policy, repository instructions for how each codebase works, and acceptance that a sentence appearing in six repositories is a smaller problem than a shared file nobody prunes.
Standards are not enforcement
The distinction that matters most in this lesson.
An instruction saying “never commit secrets” makes that less likely. It does not make it impossible, and a team that writes it and considers the problem solved has made an error of category.
Rolling it out
Start from observed corrections, not from the wiki. The rules worth writing first are the ones people are already correcting. Ask colleagues what they keep telling Copilot; those answers are pre-validated and short.
Ship one file. .github/copilot-instructions.md with eight rules, and stop
there for a fortnight. Resist the comprehensive version — it will be too long to
work and too large for anyone to review carefully.
Let it grow from failures. Each rule added because something went wrong is a rule that earns its place. Rules added by imagining what might go wrong mostly do not.
Talk about it once, in context. A review comment saying “I’ve added this to the instructions file so we stop hitting it” does more than an announcement.
Expect disagreement, and welcome it. A colleague objecting to a rule is the system working — the discussion happens once, in a pull request, rather than repeatedly as unexplained behaviour.
Common mistakes
Starting with the comprehensive version. A forty-rule file written in one sitting is too long to work and too large for anyone to review properly. Eight rules, shipped, beat forty drafted.
Encoding what tools already check. Duplicated enforcement that is weaker than the original and now needs maintaining.
Writing aspirations. “Strive for simplicity” costs context on every request and changes nothing.
Putting one person’s preference in a shared file. It becomes house style without a decision, and nobody notices for months.
Forgetting the support matrix. A standard in a mechanism your colleague’s editor does not read was never in force for them, and they will look like they are ignoring it.
Treating instructions as controls. Guidance is not enforcement, and a team that conflates them has a gap where it believes it has a policy.
Never pruning. The single most common failure. Files grow, dilute, and eventually the rules that matter are indistinguishable from the ones that expired.
Standards, and the policies above them
Team standards are conventions a team chooses to follow. Where an organisation needs something enforced rather than agreed — and where the decision involves seats, models, agents, audit or content controls — that is governance rather than convention, and it is configured somewhere else entirely.
Cluster 8 covers the distinction and the controls behind it, including the precedence rules that decide which setting actually applies when two of them disagree.
Cluster 6 complete
That is Cluster 6. Across twelve lessons the argument has been one thing: better Copilot output does not come from longer prompts. It comes from controlling five things deliberately — the prompt, the context it can see, the instructions that persist, the model behind it, and the validation you apply afterwards.
You have the pillar for the model, prompt technique and 100 prompts for the first lever, context engineering for the second, instructions, the file itself, prompt files and libraries for the third, models, choosing one and the comparison for the fourth, and this lesson for making all of it a team’s rather than an individual’s.
Cluster 7 — Copilot Agents, MCP & Agentic Development — is next, covering the cloud agent, custom agents, subagents, MCP servers, and designing multi-step autonomous workflows you can actually trust.
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.