Follow
← all articles

GitHub Copilot Developer Playbook · Part 1.1

code-agents · 10 min read

Copilot custom instructions - which file actually wins

GitHub.com ranks custom instructions while Copilot CLI combines them. VS Code confirms inline suggestions ignore them; four other IDEs remain unconfirmed.

M

Marcin

Java since 2007, .NET since 2010 · Azure · lately deep in LLMs

I've watched this happen on more than one team: someone adds a repo-wide instruction telling Copilot to always use parameterized queries, never string-concatenated SQL. A few days later, Copilot's code review waves through a PR with a string-concatenated query anyway. The developer's reaction is always some version of "well, that's useless then," but it usually turns out the instruction was living in a path-specific file, and code review was never one of the surfaces reading it in the first place.

Here's the setup: Copilot can be listening to instructions from three different tiers on the same request, personal, repo, and org, and the repo tier turns out to have more than one voice of its own these days, especially now that AGENTS.md has joined the conversation. Picture a meeting where everyone's trying to tell Copilot what to do at once, and depending on which Copilot surface you're using, they're either taking turns in a very specific order, or all shouting at the same time.

Let me introduce the room.

The Two Files Everyone Starts With

Most teams start with one voice in the room: .github/copilot-instructions.md, sitting at the repo root. Plain Markdown, no required format, and it's basically the project's designated spokesperson. Build commands, architecture notes, conventions, anything Copilot should know regardless of what it's working on, goes here.

Here's the spokesperson's actual paperwork, not just the vibe:

Location.github/copilot-instructions.md, repository root
FormatMarkdown, natural language. Whitespace between instructions is ignored: write one paragraph, one instruction per line, or blank-line-separated sections, whichever reads best.
ScopeApplies across its supported surfaces (see the full support matrix later in this post, support isn't universal across every IDE and feature)
Consumed byCopilot on GitHub (web), Copilot code review, Copilot Chat (when the repository is attached), Copilot cloud agent, plus VS Code, Visual Studio, JetBrains (preview), Eclipse (preview), Xcode (preview), and Copilot CLI at the IDE/client level

Then there's a second, quieter voice: path-specific instructions, living under .github/instructions/ as *.instructions.md files, each one scoped to a glob pattern:

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

This one doesn't replace the spokesperson. It just leans in and adds a note when the topic matches. Touch a TypeScript file with both a repo-wide file and a matching path-specific file in play, and Copilot hears from both.

It's also got a mute button that's easy to overlook. Add excludeAgent, and this quieter voice can opt itself out of being heard by one specific listener, code review or the cloud agent, without going silent for everyone else in the room:

---
applyTo: "test/**/*.ts"
excludeAgent: "code-review"
---

That's a path-specific file aimed at test-writing conventions: heard by whichever agent is actually writing the tests, invisible to whoever's reviewing the PR afterward. Leave excludeAgent off, and both code review and the cloud agent hear it.

And here's the newcomer: AGENTS.md. If you already use it for other AI tools, good news, Copilot's cloud agent and code review both read it too. It doesn't shove the spokesperson out of the room. It just pulls up a chair, and it's the most junior voice at the table: when GitHub.com has to pick who to trust more, AGENTS.md speaks last, after the spokesperson and after the quieter path-specific voice.

The newcomer doesn't get heard the same way by everyone in the room either, which is easy to miss:

ConsumerRoot AGENTS.mdNested AGENTS.mdAlso reads
Cloud agentYesYes (files nested in subdirectories apply to that part of the project)CLAUDE.md, GEMINI.md, in addition to AGENTS.md
Code reviewYesNot supported (code review reads only the repository-root AGENTS.md)AGENTS.md only

A nested AGENTS.md written for the cloud agent is invisible to code review. A CLAUDE.md or GEMINI.md file that guides the cloud agent has zero effect on code review either. Same room, different hearing.

Surprise #1: Two Completely Different Seating Charts

On GitHub.com, the room has an actual seating chart, and it's strict:

Personal instructions > Repository instructions (path-specific > repo-wide > AGENTS.md) > Organization instructions

Whoever's closest to the front wins when two voices disagree. But, and this matters, nobody gets kicked out of the room for losing. Every applicable source still gets heard. The seating chart just decides who Copilot trusts more when two people are saying different things.

Copilot CLI doesn't bother with a seating chart at all. Everyone just talks, and CLI mashes it together, quietly dropping exact duplicates from a few specific voices, not a blanket cleanup across the whole room. Path-specific instructions don't get that courtesy, for what it's worth. Say the same thing twice there and CLI hears it twice. No hierarchy, no front row, and only a little tidying up. If you've been assuming CLI respects the same "personal beats repo beats org" order as the web experience, I get why, but it doesn't, and it's not being lazy about it. It's a genuinely different room with a different set of house rules.

This is the mix-up I've seen trip people up more than anything else here: you build a mental model on GitHub.com's ranking, then go use CLI, something behaves differently, and your first instinct is "bug." It's not a bug. It's just how that room works. Here are both rooms side by side, for whenever you need to check which one you're standing in:

SurfaceModel
GitHub.comRanked: Personal beats Repository (path-specific beats repo-wide beats agent) beats Organization. Everyone's still heard regardless of rank.
Copilot CLICombined, no ranking. Duplicate copies of identical user-level, repository-wide, and agent instructions get deduplicated. Path-specific duplicates don't.

Surprise #2: Two IDEs Where Even GitHub Isn't Sure Who's Allowed to Talk

Digging into which surfaces actually support path-specific instructions, I found something I wasn't expecting: GitHub's own documentation disagrees with itself. One official reference page says JetBrains and Xcode Chat both support path-specific instructions. Another official page, the IDE setup guide, doesn't mention path-specific support for either one. Not "doesn't support it." Just doesn't bring it up.

I'm not picking a side here, mostly because I can't. If you're on JetBrains or Xcode, treat path-specific instructions as unconfirmed and test it yourself before you trust it in production. Don't be surprised if what you see doesn't match one of the two pages.

Eclipse, meanwhile, is the most confusing case in the whole room, and here the question flips from who's allowed to talk to who's actually listening. Its Chat doesn't let path-specific instructions speak at all, its cloud-agent integration lets everyone in including path-specific, and its code review doesn't let anyone custom-instruct it, full stop. Same IDE, three completely different answers, depending on which feature is doing the listening.

Here's the whole room, seat by seat, so you don't have to take my word for any of it. means supported, means the source explicitly says it isn't, and means the combination just isn't documented either way, treat those two differently, an undocumented gap is not the same claim as a confirmed no:

EnvironmentFeatureRepo-widePath-specific
GitHub.comChat
GitHub.comCloud agent
GitHub.comCode review
VS CodeChat
VS CodeCloud agent
VS CodeCode review
Visual StudioChat
Visual StudioCloud agent
Visual StudioCode review
JetBrainsChatDisputed (one docs page confirms it, the IDE setup guide doesn't mention it)
JetBrainsCloud agent
JetBrainsCode review
XcodeChatDisputed (same source conflict as JetBrains)
XcodeCloud agent
XcodeCode review
EclipseChat
EclipseCloud agent
EclipseCode reviewNot supported at allNot supported at all
Copilot CLI(single surface)

VS Code Finally Answers This One

Here's an update worth knowing about: one IDE has actually gone on record. Chat, code review, and the cloud agent are all in the room and accounted for, but completions' RSVP was a genuine mystery for a while. VS Code's own docs settle it now, for VS Code anyway: custom instructions are not taken into account for inline suggestions as you type in the editor. Completions did show up. They just walked straight past every instruction file without reading it. I haven't checked JetBrains, Xcode, Visual Studio, or Eclipse's own docs for the same claim, so on those, it's still an open question, not a confirmed no and not a confirmed yes. If your mental model includes "my instructions shape every suggestion Copilot gives me, including autocomplete," that's now a confirmed no on VS Code, and still genuinely unchecked everywhere else.

What to Actually Do with This

Four habits, in roughly the order they'd have saved me a confused Slack thread:

  • Write your repo-wide file assuming it's heard broadly, but check the support matrix above before you lean on path-specific instructions in a specific IDE. Coverage isn't even, and the two disputed seats above (JetBrains and Xcode Chat) are worth testing yourself instead of trusting either page blindly.
  • If you're scripting against Copilot CLI, leave your GitHub.com assumptions at the door. CLI combines. It doesn't rank.
  • If you already maintain an AGENTS.md, know that the cloud agent hears nested AGENTS.md files tucked away in subdirectories, but code review only ever listens to the one at the repo root. A nested file quietly steering the cloud agent is invisible to whoever's reviewing your PR.
  • If you want a path-specific file to stay out of code review's hands entirely, that's what excludeAgent: "code-review" is for. Don't reach for a second, more complicated mechanism when this one's built in.

And if you're setting up the spokesperson file for the first time, here's a real shape to steal from rather than staring at a blank page:

# Repository custom instructions

## Project summary
This repository is a TypeScript/Node.js REST API for order management,
built with Express and PostgreSQL (via Prisma). It's deployed as a
container to a Kubernetes cluster.

## Build, test, and validation
- Always run `npm install` before building or running tests — dependencies
  change frequently and stale installs cause confusing failures.
- Build: `npm run build` (runs the TypeScript compiler; must pass with
  zero errors before a PR is opened).
- Unit tests: `npm test`. Integration tests (require a local Postgres,
  started via `docker compose up -d db`): `npm run test:integration`.
- Lint: `npm run lint`. Auto-fixable issues: `npm run lint:fix`.
- A full CI run takes ~4 minutes; integration tests alone take ~90 seconds.

## Project layout
- `src/routes/` — Express route handlers, one file per resource.
- `src/services/` — business logic; route handlers should stay thin and
  delegate here.
- `src/db/` — Prisma schema and generated client.
- `test/unit/` and `test/integration/` — mirror the `src/` structure.

## Environment setup
- Requires Node.js 20+ and Docker (for local Postgres).
- Copy `.env.example` to `.env` before running locally.

## CI/CD
- GitHub Actions workflow at `.github/workflows/ci.yml` runs lint, build,
  and both test suites on every PR.
- Deployment to staging is automatic on merge to `main`; production
  deployment requires a manual approval step.

## Conventions
- Use named exports, not default exports.
- All new endpoints require an integration test.
- Follow existing error-handling patterns in `src/services/errors.ts`
  rather than throwing raw errors.

Not gospel, just a real example of the shape GitHub itself recommends: summary, build and test commands, layout, environment, CI/CD, conventions. Swap the specifics for your own stack and you're most of the way to a working spokesperson.

None of this is exotic. It's the kind of thing that turns into a confused Slack thread, "why is Copilot ignoring my instructions in this one file," if nobody bothers writing it down first.

So I wrote it down. Next time someone on your team swears Copilot's ignoring them, you'll know to ask a better question: not "is it broken," but "who else is in the room."