GitHub Copilot reads AGENTS.md, root and nested, in the CLI, in VS Code and in the cloud agent. That covers the instructions. A generated repo adds the four things AGENTS.md can't carry: custom agents, hooks, a plugin and MCP servers.
Below: each file, what Copilot does with it, and the real version from a generated Next.js repo.
What Copilot reads
| File | What it is |
|---|---|
AGENTS.md, root and nested | Instructions |
.github/copilot-instructions.md, .github/instructions/*.instructions.md | Copilot's own instruction files |
.claude/rules/ | Claude Code's rules. Copilot reads them too |
.agents/skills/, .claude/skills/, .github/skills/ | Skills |
.github/agents/*.agent.md, .claude/agents/ | Custom agents |
.github/hooks/*.json, .claude/settings.json | Hooks. The Claude file in the CLI and VS Code |
.github/copilot/settings.json | Plugins, through enabledPlugins |
.mcp.json | MCP servers |
Instructions: AGENTS.md, not copilot-instructions.md
Copilot CLI looks for AGENTS.md at the repo root, in your working folder, in the folders between them, and in folders on the path to a file. When several instruction files apply, it combines them.
So a generated repo ships no .github/copilot-instructions.md. AGENTS.md already reaches Copilot, and every other agent too. There's a second reason. Zed reads one instruction file: the first match from a list where .github/copilot-instructions.md comes before AGENTS.md. Ship both, and Zed never sees AGENTS.md.
Folder rules sit in nested AGENTS.md files, like this one in src/app/api/webhooks/stripe/:
# src/app/api/webhooks/stripe
Rules for files under `src/app/api/webhooks/stripe`. The root `AGENTS.md` and every
`AGENTS.md` between it and this folder apply here too.
## Verify every Stripe webhook, keep every handler idempotent
Applies to: `src/app/api/webhooks/stripe/**`, `src/lib/billing/provider.ts`, `src/lib/billing/webhook.ts`
Source: `stripe`
First 9 of 72 lines of src/app/api/webhooks/stripe/AGENTS.md.
One cost to know. Copilot also reads .claude/rules/. When Claude Code is picked too, a scoped rule reaches Copilot twice: once from the nested AGENTS.md, once from .claude/rules/. That costs tokens, not correctness. Without Claude Code, the generator writes .github/instructions/<id>.instructions.md with applyTo globs instead, for any rule that didn't fit in its AGENTS.md.
The full AGENTS.md walkthrough: AGENTS.md examples.
Custom agents: .github/agents/*.agent.md
A custom agent is a markdown file with an .agent.md extension in .github/agents/. The frontmatter sets its name, description and tools. The body is its prompt. Copilot can pick one on its own when a task fits the description. Here is the top of the generated PR reviewer:
---
description: Reviews a diff against this repo's rules before it becomes a PR. Convention-aware, blocking on correctness and security, advisory on taste.
name: pr-reviewer
tools:
- read
- search
- execute
---
You are the PR reviewer for this repository. You review a change *against the
rules this repo has already written down*, not against your own preferences.
A reviewer who invents new standards mid-review is worse than no reviewer.
First 12 of 89 lines of .github/agents/pr-reviewer.agent.md.
tools lists read, search and execute, and no edit. The reviewer can run checks, but it can't change code. The repo ships 7 custom agents. Copilot also reads .claude/agents/. Personal agents go in ~/.copilot/agents/.
Hooks: .github/hooks/agentic-guards.json
Copilot loads hooks from every .github/hooks/*.json file. A preToolUse hook can deny a tool call before it runs. This is the generated file:
{
"version": 1,
"hooks": {
"postToolUse": [
{
"type": "command",
"bash": "bun .agents/hooks/run.mjs auto-lint --from copilot",
"powershell": "bun .agents/hooks/run.mjs auto-lint --from copilot",
"cwd": ".",
"matcher": "create|edit",
"timeoutSec": 60
},
{
"type": "command",
"bash": "bun .agents/hooks/run.mjs enforce-doc-meta --from copilot",
"powershell": "bun .agents/hooks/run.mjs enforce-doc-meta --from copilot",
"cwd": ".",
"matcher": "create|edit",
"timeoutSec": 60
},
{
"type": "command",
"bash": "bun .agents/hooks/run.mjs env-leak-detector-write --from copilot",
"powershell": "bun .agents/hooks/run.mjs env-leak-detector-write --from copilot",
"cwd": ".",
"matcher": "create|edit",
"timeoutSec": 60
}
],
"preToolUse": [
{
"type": "command",
"bash": "bun .agents/hooks/run.mjs block-destructive --from copilot",
"powershell": "bun .agents/hooks/run.mjs block-destructive --from copilot",
"cwd": ".",
"matcher": "bash|powershell",
"timeoutSec": 60
},
{
"type": "command",
"bash": "bun .agents/hooks/run.mjs enforce-typecheck --from copilot",
"powershell": "bun .agents/hooks/run.mjs enforce-typecheck --from copilot",
"cwd": ".",
"matcher": "bash|powershell",
"timeoutSec": 60
},
{
"type": "command",
"bash": "bun .agents/hooks/run.mjs env-leak-detector --from copilot",
"powershell": "bun .agents/hooks/run.mjs env-leak-detector --from copilot",
"cwd": ".",
"matcher": "bash|grep|powershell|view",
"timeoutSec": 60
},
{
"type": "command",
"bash": "bun .agents/hooks/run.mjs guard-neon-sql --from copilot",
"powershell": "bun .agents/hooks/run.mjs guard-neon-sql --from copilot",
"cwd": ".",
"matcher": "bash|powershell",
"timeoutSec": 60
}
]
}
}
.github/hooks/agentic-guards.json, as generated.
How it works:
- A command per shell.
bashandpowershellhold the same command for each shell. - Copilot's tool names. Matchers use
bash,powershell,view,grep,createandedit. - One launcher. Each hook runs
.agents/hooks/run.mjs <guard> --from copilot. It turns Copilot's payload into the format the guards speak, and answers withpermissionDecision: "deny"and a reason when a guard blocks. - It never fails closed. In Copilot, any non-zero exit from a
preToolUsehook denies the call, a crash included, not only exit 2. A broken guard would lock you out of every tool. So the launcher always exits cleanly, and lets the call through with a warning when a guard can't run.
Copilot also reads Claude Code's hooks from .claude/settings.json, in the CLI and VS Code. The launcher sees Copilot's payload there and steps aside, so each guard runs once.
Two limits outside Claude Code: a rewrite becomes a block that names the command to run instead, and hiding a secret in command output doesn't happen. The check before the command is what stops a leak. More: guard hooks in every agent.
The plugin: .github/copilot/settings.json
Copilot turns on the plugins listed under enabledPlugins in .github/copilot/settings.json. The generated file adds the Compound Engineering plugin, pinned to a release tag:
{
"extraKnownMarketplaces": {
"compound-engineering-plugin": {
"source": {
"source": "github",
"repo": "EveryInc/compound-engineering-plugin",
"ref": "compound-engineering-v3.28.2"
}
}
},
"enabledPlugins": {
"compound-engineering@compound-engineering-plugin": true
}
}
.github/copilot/settings.json, as generated.
Copilot offers it the first time you trust the folder. To install it by hand:
copilot plugin marketplace add EveryInc/compound-engineering-plugin
copilot plugin install compound-engineering@compound-engineering-plugin
It adds /ce-brainstorm, /ce-plan, /ce-work, /ce-code-review and /ce-compound.
MCP: .mcp.json
Copilot CLI reads the root .mcp.json in a trusted folder. It's the same format Claude Code uses, so one file serves both. Every tool is on by default:
{
"mcpServers": {
"better-auth": {
"type": "http",
"url": "https://mcp.better-auth.com/mcp"
},
"neon": {
"type": "http",
"url": "https://mcp.neon.tech/mcp?readonly=true"
},
"posthog": {
"type": "http",
"url": "https://mcp.posthog.com/mcp?readonly=true"
},
"sentry": {
"type": "http",
"url": "https://mcp.sentry.dev/mcp"
},
"stripe": {
"type": "http",
"url": "https://mcp.stripe.com"
}
}
}
.mcp.json, as generated.
Start each server from the MCP list in Copilot CLI or VS Code, and sign in to the remote ones. Neon and PostHog connect read-only. Copilot never reads .env.local, so a server that needs a key reads it from your environment.
Skills
Copilot reads Agent Skills from .agents/skills/, .claude/skills/ and .github/skills/. Run one as /name. The generated repo ships 29 skills, all in .agents/skills/. On a fresh clone, start with /setup. More: Agent Skills in every agent.
Copilot setup checklist
- Open the repo in Copilot CLI or VS Code, and trust the folder. Copilot skips a repo's own hooks, MCP servers or custom agents until you do.
- Run
/setup. It fills.env.localand connects the services, after you say yes. - Start each MCP server and sign in.
- Accept the Compound Engineering plugin, or install it with the two commands above.
- Run
bun run verify:hooks. It replays every guard in Copilot's own payload format.
Get a Copilot-ready Next.js repo
Pick your stack at /build. GitHub Copilot is one of 10 agents, all on by default. You get AGENTS.md and its nested files, .agents/ with every skill and guard, and .github/ with custom agents, hooks and the plugin. The same repo works in Claude Code, Codex, Cursor and the rest. $99 once, with lifetime updates. What each agent gets: the agentic layer.
Other agents: Codex setup, Claude Code setup, Cursor rules.
FAQ
Does GitHub Copilot read AGENTS.md?
Yes, root and nested, in the CLI, VS Code and the cloud agent. When an AGENTS.md and a .github/copilot-instructions.md both exist, Copilot uses both.
Do I need a copilot-instructions.md file?
No. AGENTS.md covers Copilot and most other agents. A .github/copilot-instructions.md also hides AGENTS.md from Zed, which reads only the first file it finds.
Where do Copilot custom agents go?
In .github/agents/, one <name>.agent.md file each, with a description and a tools list in the frontmatter. Personal agents go in ~/.copilot/agents/. Copilot also reads .claude/agents/.
Does GitHub Copilot support hooks?
Yes. Hooks live in .github/hooks/*.json. A preToolUse hook can deny a call with permissionDecision: "deny" or with any non-zero exit. Copilot CLI and VS Code also read hooks from .claude/settings.json.
Does Copilot read .mcp.json?
Copilot CLI reads the root .mcp.json in a trusted folder, in the same format Claude Code uses, with every tool on by default.
Why does Copilot deny every tool call?
Usually a broken preToolUse hook. Copilot treats a non-zero exit as a deny, so a hook that crashes on every call blocks every call. Pipe a sample payload into the hook by hand and check its exit code.
Sources
Tool behavior is from the official docs, checked on October 8, 2026. Tools change. The docs win.
Keep reading
- CLAUDE.md template for Next.js, with real examplesA CLAUDE.md template for Next.js you can copy, where the file goes, what belongs in it, and how a repo shared with other agents loads AGENTS.md instead.
- AGENTS.md examples, from a real Next.js repoWhat AGENTS.md is, a template to copy, real root and nested files from a generated Next.js repo, and how Codex, Cursor, Copilot and Claude Code load them.
- CLAUDE.md vs AGENTS.md: which one you needCLAUDE.md is Claude Code's file. AGENTS.md is the one Codex, Cursor, Copilot and most other agents read. Who reads what, and how to keep both in sync.
- Cursor rules for Next.js, with real .mdc examplesHow Cursor rules work: the .mdc format, globs, alwaysApply and the four rule types, when a nested AGENTS.md is enough, and real Next.js rules to copy.