Back to blog
Engineering20 min read

GitHub Copilot Custom Instructions (Templates That Work)

Which instruction files GitHub Copilot actually reads in 2026, which surfaces honour which, what applyTo and excludeAgent do, and eight copy-paste templates. Verified against GitHub's docs.

NH
Nafiul Hasan
Founder, Prompt Architects

TL;DR: GitHub Copilot reads four kinds of instruction file: .github/copilot-instructions.md repository-wide, .github/instructions/NAME.instructions.md scoped by an applyTo glob, AGENTS.md, and personal instructions. Which of them apply depends entirely on the surface you are using, and GitHub's own documentation disagrees with itself in two places. Eight copy-paste templates below, plus what to delete.

Most articles about Copilot custom instructions describe a single file at .github/copilot-instructions.md and stop there. That was accurate once. It is now roughly a third of the story, and the missing two thirds are where people get burned: a rule written in the wrong file reaches some Copilot surfaces and not others, silently, with no error.

This is GitHub's feature, not ours. Everything below was read on GitHub's own documentation on August 28, 2026. Where GitHub does not publish something, this post says so rather than filling the gap, and where two GitHub pages disagree, both are quoted.

Which files does GitHub Copilot actually read?

Four kinds, at three levels. GitHub's overview page groups them as personal, repository and organization instructions, and splits the repository level into three separate file types.

LevelFile and locationWhat it is for
Personal (GitHub.com)Set in a popup on the Copilot Chat page, no fileYour own tone, language, examples
Personal (JetBrains)global-copilot-instructions.md in a local Copilot config directoryYour preferences across every workspace
Personal (Copilot CLI)$HOME/.copilot/copilot-instructions.md and $HOME/.copilot/instructions/**/*.instructions.mdUser-level rules across repositories
Repository-wide.github/copilot-instructions.mdEverything true of the whole repo
Path-specific.github/instructions/NAME.instructions.mdRules scoped to a glob
Agent instructionsAGENTS.md anywhere in the repo; CLAUDE.md or GEMINI.md in the rootShared with other coding agents
OrganizationOrganization settings on GitHub.com, no fileOrg-wide language and policy

Three details in that table are worth stating plainly, because they are the ones that get paraphrased into something wrong.

The repository-wide file has not moved. Three separate GitHub documentation pages carry the same sentence word for word: these instructions "are specified in a copilot-instructions.md file in the .github directory of the repository". Every other page that mentions the file names the same path. If a tutorial tells you it belongs in the repo root, it is describing a different tool.

Path-specific files have a strict naming rule. They live "within or below the .github/instructions directory in the repository", and GitHub is explicit that "The file name must end with .instructions.md". A plain .md file dropped in that directory is not a path-specific instructions file.

Organization instructions have an eligibility gate. GitHub states they "can only be set by organization owners for organizations with a Copilot Business or Copilot Enterprise subscription". There is no file for them and no way to version-control them.

Which Copilot surfaces honour which files?

This is the part almost every article gets wrong, and the reason a rule can look ignored when it is simply not being read. GitHub publishes a dedicated reference page for it, and the answer is genuinely uneven.

Surface and featureRepo-widePath-specificAgent instructionsPersonal
GitHub.com, Copilot ChatYesNoNoYes
GitHub.com, cloud agentYesYesAGENTS, CLAUDE, GEMININo
GitHub.com, code reviewYesYesAGENTS.md onlyNo
VS Code, Copilot ChatYesYesAGENTS.md onlyNot listed
VS Code, cloud agentYesYesAGENTS, CLAUDE, GEMININot listed
VS Code, code reviewYesNoNoNot listed
Visual Studio, Copilot ChatYesYesNoNot listed
Visual Studio, code reviewYesNoNoNot listed
JetBrains, Copilot ChatYesYes (disputed)NoYes
JetBrains, cloud agentYesYesAGENTS, CLAUDE, GEMININot listed
JetBrains, code reviewYesYesNoNot listed
Eclipse, Copilot ChatYesNoNoNot listed
Eclipse, cloud agentYesYesAGENTS, CLAUDE, GEMININot listed
Eclipse, code reviewNot supportedNot supportedNot supportedNot supported
Xcode, Copilot ChatYesYes (disputed)NoNot listed
Xcode, cloud agentYesYesAGENTS, CLAUDE, GEMININot listed
Xcode, code reviewYesYesNoNot listed
Copilot CLIYesYesAGENTS, CLAUDE, GEMINIYes

Organization instructions are omitted from that table because they are uniform: GitHub's note says they "are currently only supported for Copilot Chat on GitHub.com, Copilot code review on GitHub.com and Copilot cloud agent on GitHub.com". Nowhere else.

Read the first row again, because it is the most consequential one. Copilot Chat on github.com does not read path-specific instructions at all. GitHub says so twice, once as a note on the how-to page: "Currently, on GitHub.com, path-specific custom instructions are only supported for Copilot cloud agent and Copilot code review." So if you moved a rule out of copilot-instructions.md into a scoped file to keep the main file short, you removed it from web chat.

One more asymmetry, before you rely on a review rule. GitHub documents that when reviewing a pull request, Copilot reads repository custom instructions, agent instructions and agent skills "from the head branch (the branch with your changes), not the base branch". So you can test a change to your instructions inside the same pull request that makes it.

Does GitHub Copilot read AGENTS.md?

Yes, on the surfaces marked in the table above, and the discovery rule is different from every other file here. GitHub says you "can create one or more AGENTS.md files, stored anywhere within the repository", and that "the nearest AGENTS.md file in the directory tree will take precedence". That is the only Copilot instruction file with per-directory resolution.

CLAUDE.md and GEMINI.md are supported too, but with a narrower shape. GitHub's wording is that you "can use a single CLAUDE.md or GEMINI.md file stored in the root of the repository" as an alternative. One file, root only. Copilot CLI is the exception: its documentation adds that "Copilot CLI also uses .claude/CLAUDE.md."

Two caveats that matter in practice. First, VS Code ships with a restriction: "Support of AGENTS.md files outside of the workspace root is currently turned off by default", so the nearest-file behaviour is opt-in there. Second, AGENTS.md support is narrower than copilot-instructions.md support across the board. Copilot code review on GitHub.com reads AGENTS.md but not CLAUDE.md or GEMINI.md. Copilot Chat on github.com reads none of the three.

Do not carry conventions across tools on the strength of the filename. Different agents resolve these files differently, and a rule that works in one is not automatically read by another. Our own writeups of the neighbouring systems are separate for exactly that reason: see CLAUDE.md best practices and Cursor rules and prompt templates for what those tools actually do.

What do applyTo and excludeAgent do?

applyTo is the frontmatter key that turns a markdown file into a scoped instruction file. It takes glob syntax, and GitHub documents comma-separated patterns for multiple globs in one value. GitHub's own worked examples are applyTo set to "app/models/**/*.rb" for a single tree, and to "**/*.ts,**/*.tsx" for TypeScript and TSX together.

The glob semantics are documented precisely, and two of them are easy to get backwards. src/*.py matches .py files directly in src but, in GitHub's words, "not src/foo/bar.py". src/**/*.py recurses. If you scope a rule to a directory and it never fires, check whether you wrote one asterisk where you needed two.

excludeAgent is the under-used one, and it is the reason a review-only rule file is possible at all. GitHub documents adding the keyword to the frontmatter block with a value of either code-review or cloud-agent, and states that if it is left out, "both Copilot code review and Copilot cloud agent will use your instructions". So excludeAgent: "cloud-agent" gives you a checklist that shapes pull request review and never lands in the coding agent's context window, and excludeAgent: "code-review" gives you the reverse.

Overlap is additive, not exclusive. GitHub says that if the path you specify matches a file Copilot is working on "and a repository-wide custom instructions file also exists, then the instructions from both files are used". Scoping does not replace your baseline; it adds to it.

Which instructions win when they conflict?

There is a documented answer for GitHub.com and an explicitly undocumented one for the CLI, which is a distinction nobody publishing a precedence diagram seems to have noticed.

On GitHub.com, the order is published. GitHub lists personal instructions highest, then repository instructions split into path-specific and then repository-wide, then agent instructions, then organization instructions last. The framing matters as much as the order: "Personal instructions take the highest priority. Repository instructions come next, and then organization instructions are prioritized last. However, all sets of relevant instructions are provided to Copilot."

That last sentence is the one to internalise. Precedence here is not filtering: a lower-priority instruction is not discarded, only ranked. Both sides of a contradiction reach the model, which is why GitHub's advice is prevention rather than resolution: "Whenever possible, try to avoid providing conflicting sets of instructions."

Copilot CLI is different, and says so. Its documentation states that when multiple applicable files exist it combines their instructions, removes duplicate copies of identical files, "but does not define a general precedence order between these files". There is no CLI precedence ladder to reason about. There is only the instruction to avoid conflicts.

So: precedence is surface-specific, and on at least one surface it is undefined. Design your instruction set so that no two files can disagree, and you never need to know which page applies.

Why does a long instructions file make Copilot worse?

Because an always-applied instruction file is not free, and GitHub says exactly why in one sentence: "Because the instructions are sent with every chat message, they should be broadly applicable to most requests you will make in the context of the repository."

Sent with every message. Every line in .github/copilot-instructions.md is charged against every request, including the hundreds it has nothing to do with. Your Terraform naming convention rides along on a CSS question, competing with the actual task for the model's attention. The effect of adding it is not neutral.

GitHub is unusually candid about the failure mode. It warns that some instruction types "may work for a small repository with only a few contributors, but for a large and diverse repository, these may cause problems", and names three: "Requests to refer to external resources when formulating a response", "Instructions to answer in a particular style", and "Requests to always respond with a certain level of detail". Its list of instructions that "may not have the intended results" includes the perfectly reasonable-sounding "Always conform to the coding styles defined in styleguide.md in repo my-org/my-repo when generating code."

Which brings us to the honest core of this whole feature. Custom instructions are context, not enforcement. GitHub puts a note to that effect on every single tab of its overview page: "Due to the non-deterministic nature of AI, Copilot may not always follow your custom instructions in exactly the same way every time they are used." They raise the odds. They do not bind the model. Anyone promising you compliance is selling something, and any percentage attached to that promise is invented, because GitHub publishes no such figure.

The working discipline follows directly:

  1. Short and specific beats long and aspirational. "Use pytest, not unittest" survives. "Write clean, maintainable, idiomatic code" is noise that costs you tokens on every request.
  2. Scope with applyTo instead of growing one giant file — but only after checking the surface table, because on github.com web chat, scoping means the rule disappears.
  3. Delete rules that are not earning their place. An instruction you cannot point at a real pull request for is a rule you are paying for and not using.
  4. Prefer facts over exhortations. GitHub's own structural advice is an overview of the project, the folder structure, the coding standards, and the tools and frameworks in use. Those are things the model cannot guess. Adjectives are things it will ignore.

There is no published budget to work against. GitHub does not publish a character limit, a token limit or a line target for any of these files. The only number it puts in writing is inside the prompt it supplies for auto-generating an instructions file, which caps the result at "no longer than 2 pages" and adds that "Instructions must not be task specific." That is guidance to a generator, not a documented ceiling, and this post is not going to launder it into one.

The templates

Eight files. Replace anything in double braces. Delete every line you cannot justify, then delete two more.

1. Repository-wide baseline — read on every surface that supports custom instructions at all. Keep it to facts about the repo.

# {{PROJECT_NAME}}

{{ONE_SENTENCE_ON_WHAT_THIS_REPO_DOES}}

## Stack
- {{LANGUAGE}} {{VERSION}}, {{FRAMEWORK}} {{VERSION}}
- Package manager: {{PACKAGE_MANAGER}}
- Tests: {{TEST_RUNNER}}
- Lint and format: {{LINTER}}, {{FORMATTER}}

## Layout
- `{{SRC_DIR}}` application code
- `{{TEST_DIR}}` tests, mirroring `{{SRC_DIR}}`
- `{{GENERATED_DIR}}` generated, never edited by hand

## Commands
- Install: `{{INSTALL_CMD}}`
- Build: `{{BUILD_CMD}}`
- Test: `{{TEST_CMD}}`
- Lint: `{{LINT_CMD}}`
Always run `{{INSTALL_CMD}}` before `{{BUILD_CMD}}`.

## Conventions
- {{NAMING_RULE}}
- {{ERROR_HANDLING_RULE}}
- Public functions in `{{SRC_DIR}}` need a docstring; private ones do not.
- Do not add a dependency without saying so in the pull request description.

2. Testing rule — scoped to test files so it costs nothing on the other 90% of requests.

---
applyTo: "{{TEST_GLOB}}"
---

- Use `{{TEST_RUNNER}}`. Do not introduce a second test framework.
- One behaviour per test. Name tests `{{TEST_NAMING_PATTERN}}`.
- Assert on {{WHAT_TO_ASSERT_ON}}, not on log output or call counts.
- Use the existing fixtures in `{{FIXTURES_PATH}}` before writing a new one.
- Network calls are stubbed with `{{STUB_TOOL}}`. Never hit a live service.
- A bug fix comes with a regression test that fails without the fix.
- Do not delete or skip a failing test to make a suite pass.

3. Language or framework scoped — the single most useful file in the set, and the one that earns the bookmark.

---
applyTo: "**/*.ts,**/*.tsx"
---

- TypeScript strict mode is on. Do not use `any`; use `unknown` and narrow.
- Prefer `type` aliases for unions, `interface` for object shapes we extend.
- No default exports in `{{SRC_DIR}}`. Named exports only.
- Data fetching goes through `{{DATA_LAYER_PATH}}`. Do not call `fetch` in a component.
- Validate external input with `{{VALIDATION_LIB}}` at the boundary, then trust it.
- Components are function components. No class components.
- Keep `{{STATE_LIB}}` state serialisable.

Swap the glob for your language: "**/*.py", "**/*.go", "app/models/**/*.rb", "{{MODULE_PATH}}/**". GitHub's comma-separated syntax means one file can cover a whole family.

4. Review-focused, excluded from the coding agent — this is what excludeAgent is for.

---
applyTo: "**"
excludeAgent: "cloud-agent"
---

When reviewing a pull request in this repository:

## Block on
- Hardcoded secrets, tokens or connection strings.
- Unvalidated user input reaching a query, a shell command or a template.
- A schema or migration change without a rollback path.
- A public API or exported signature changing without a note in the description.

## Flag, do not block
- A function over {{MAX_FUNCTION_LINES}} lines.
- A new dependency.
- A `TODO` with no owner or issue link.

## Do not comment on
- Formatting. `{{FORMATTER}}` owns that.
- Anything under `{{GENERATED_DIR}}`.
- Test naming style.

Be specific. Quote the line. If it is a preference and not a defect, say so.

5. Do not touch generated files — narrow, boring, and it pays for itself the first time it works.

---
applyTo: "{{GENERATED_GLOB}}"
---

These files are generated. Do not edit them by hand and do not suggest edits to
them.

- Regenerate with `{{CODEGEN_CMD}}`.
- The source of truth is `{{SCHEMA_OR_SPEC_PATH}}`. Change that instead.
- If a change here seems necessary, say so in the pull request and change the
  generator or its input, not the output.
- Never reformat, re-sort or "clean up" a generated file.

6. Commit and pull request conventions — commit message generation is one of the use cases GitHub names for custom instructions.

---
applyTo: "**"
---

## Commit messages
- Conventional Commits: `type(scope): subject`.
- Allowed types: {{ALLOWED_TYPES}}.
- Subject in the imperative, lowercase, no trailing period, under 72 characters.
- A breaking change gets a `!` after the scope and a `BREAKING CHANGE:` footer.
- Reference the issue as `{{ISSUE_REF_FORMAT}}` in the footer, not the subject.

## Pull request descriptions
- Open with one sentence on what changed and why. No restating the diff.
- List behaviour changes a reviewer cannot see in the diff.
- State how it was tested, with the actual command.
- Call out anything intentionally left out of scope.

Note the caveat this file walks into: on github.com web chat, a path-specific file is not read, so if your team drafts commit messages there, this content belongs in the repository-wide file instead. Our commit message generator covers the format itself in more depth.

7. Personal instructions for Copilot CLI — yours, not the team's, at $HOME/.copilot/copilot-instructions.md.

- Show the command before running it. Do not chain destructive commands.
- Explain in {{LANGUAGE_PREFERENCE}}. Keep prose short; put detail in code.
- When you are uncertain, say which part you are uncertain about.
- Do not rewrite code I did not ask you to touch.
- Prefer the smallest diff that solves the problem.
- If a task needs more than {{MAX_FILES}} files changed, propose a plan first.

8. AGENTS.md, for the directory it sits in — the only Copilot instruction file with nearest-wins resolution.

# {{DIRECTORY_NAME}}

{{WHAT_THIS_DIRECTORY_IS}}

- Entry point: `{{ENTRY_FILE}}`
- Owns: {{RESPONSIBILITIES}}
- Does not own: {{NON_RESPONSIBILITIES}}
- Run just this area's tests with `{{SCOPED_TEST_CMD}}`.
- {{ONE_NON_OBVIOUS_CONSTRAINT_THAT_KEEPS_BITING_PEOPLE}}

If you keep a CLAUDE.md for another tool, remember what GitHub actually supports: a single file in the repository root, on the surfaces that support agent instructions, with Copilot CLI additionally reading .claude/CLAUDE.md. It is not a drop-in replacement for AGENTS.md, and the two are not interchangeable across tools.

How do you know the instructions were actually used?

By checking the references on the response, which is the only verification GitHub documents. On GitHub.com it says that whenever repository custom instructions are used, "the instructions file is added as a reference for the response that's generated", and tells you to expand the reference list at the top of a chat response and check whether the .github/copilot-instructions.md file is listed. The IDE pages describe the same check in the Chat view's References list.

Copilot CLI gives you a better tool. Its documentation says to "Use the /instructions command to view the instruction files discovered for the current session and enable or disable individual files." That is a real discovery listing, and it is the fastest way to find out that a file you thought was loading is not.

Two operational notes. In the CLI, edits are not live: "Changes you make to custom instructions files are not immediately available for use in active CLI sessions", so resume or start a new session after editing. And in VS Code, instruction files can be switched off entirely under a "Code Generation: Use Instruction Files" setting that is enabled by default. If a colleague's Copilot ignores the file that works for you, check that first.

A reference showing up tells you the file reached the request. It does not tell you the model followed it. Only the first of those has a documented answer.

What should you delete?

Run this pass quarterly. Ten minutes, and it is the highest-value maintenance an instruction set gets.

  • Anything with no falsifiable content. "Write clean code", "follow best practices", "be thorough". These cost tokens on every request and change nothing.
  • Anything the linter already enforces. If {{FORMATTER}} rewrites it on save, the model does not need to be told.
  • Anything pointing at an external document. GitHub explicitly lists requests to refer to external resources among the instructions that may cause problems in a large repository.
  • Style directives about the response itself. Same list, same warning.
  • Rules for a framework you migrated off. Stale instructions are worse than no instructions, because they actively steer the model wrong.
  • Duplicates between copilot-instructions.md and AGENTS.md. Both are sent on surfaces that read both. Pick one home per rule.

The test for keeping a rule: can you name a pull request where its absence caused a problem? If not, delete it and see whether anything breaks. Nothing usually does.

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.

Create An Account

None of this is a Prompt Architects feature, and we are not going to pretend otherwise. We do not ship a GitHub Copilot extension, we do not generate .instructions.md files, and GitHub Copilot is not one of the clients we publish setup steps for on our MCP page — those are Claude Desktop, Claude.ai, Cursor, Claude Code, Codex and Codex CLI. That page does also describe the connector as working in any other MCP-aware client, and GitHub's cheat sheet marks MCP servers as supported on every Copilot surface, but we publish no tested Copilot setup steps, so treat that combination as untested rather than supported. What we do is the layer next to this one: writing and storing the reusable prompt templates you paste into a chat, rather than the always-on file that sits underneath them. If you want the same treatment for a different tool, we have written up Claude project instructions and prompting for a genuinely useful code review elsewhere.

Start with one file. Put facts in it, not adjectives. Add a scoped file only when you can name the glob and the surface it needs to reach. Then leave it alone until something breaks, and when it does, check the references before you rewrite the rule.

Frequently asked questions

Free Chrome Extension

Stop rewriting prompts. Start shipping.

Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.

Create An Account