GitHub Copilot custom instructions: configuring copilot-instructions.md
Where the file goes, what Copilot does with it, an example for a TypeScript repository, prompt files, and how to generate one from the project itself.
Last reviewed 2026-08-27 · View as Markdown
GitHub Copilot custom instructions are Markdown files committed to a repository
that Copilot reads before it answers a chat request, reviews a pull request or
starts a coding-agent session. The file most people mean is
.github/copilot-instructions.md. This guide covers where it goes, what reads
it, the companion formats, what the documentation says about content and
limits, a complete example for a TypeScript repository, and generating the
file from the project itself.
Where .github/copilot-instructions.md goes and what reads it
The file lives at .github/copilot-instructions.md — inside the .github
directory, not at the repository root. GitHub calls this "repository custom
instructions"; VS Code calls it an "always-on" instruction file. Both mean the
same thing: the whole file is attached to every chat request, whatever files
are open.
Two limits on that are worth knowing before you write a line of it:
- Custom instructions do not affect the grey text that appears as you type. VS Code's documentation is explicit: "Custom instructions are not taken into account for inline suggestions as you type in the editor." They apply to chat, agent sessions and code review.
- Following them is not guaranteed. GitHub's wording: "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."
Support also differs by editor: repository-wide instructions are the widely supported case, while path-specific instruction files are read in fewer places, and JetBrains IDEs and Xcode are documented as reading a single repository-wide file only.
To see what actually loaded in VS Code, right-click in the Chat view and select Diagnostics — the chat customisation diagnostics view lists every loaded instruction file and any errors in them.
Three kinds of instruction can apply to one request: personal, repository and organisation. All relevant sets are provided to Copilot; where they conflict, personal instructions take priority, then repository, then organisation. One detail matters for pull requests: Copilot reads repository instructions from the head branch — the branch with your changes — not the base branch, so a fix to the instructions takes effect on the same pull request that contains it.
Copilot custom instructions for a repository: the three file types
| File | Location | Scope |
|---|---|---|
copilot-instructions.md | .github/ | Every request |
NAME.instructions.md | .github/instructions/, subfolders included | Files matching the applyTo glob in its front matter |
AGENTS.md | Anywhere in the repository; the nearest one up the tree wins | Agents; GitHub also documents CLAUDE.md and GEMINI.md at the repository root |
Path-specific instruction files with applyTo
An instruction file is Markdown with a YAML front matter block. applyTo uses
glob syntax to say which files or directories the instructions apply to —
**/*.ts, src/**/*.py, ** for everything. VS Code treats name,
description and applyTo as optional and shows the description on hover.
GitHub adds excludeAgent, which takes "code-review" or "cloud-agent" to
keep one file away from one of those two.
--- applyTo: "**/*.test.ts" description: "Conventions for Vitest files" --- Use `describe`/`it`, never `test`. Mock only at the network boundary with `msw`; never mock modules under `src/lib`, because the point of those tests is that the real implementation runs.
VS Code searches .github/instructions recursively, so subdirectories are
fine. chat.instructionsFilesLocations adds folders beyond it, and files in
the user-level ~/.copilot/instructions folder follow you across workspaces.
In a monorepo where the checkout sits inside a parent repository,
chat.useCustomizationsInParentRepositories lets VS Code look upwards.
AGENTS.md and CLAUDE.md
VS Code reads AGENTS.md and CLAUDE.md as always-on instructions, behind
chat.useAgentsMdFile and chat.useClaudeMdFile; nested AGENTS.md files in
subfolders sit behind the experimental chat.useNestedAgentsMdFiles. If the
same repository is opened in more than one tool, AGENTS.md is the file they
can share — see the AGENTS.md guide and the
CLAUDE.md guide. A sensible arrangement is one AGENTS.md
carrying the tool-neutral facts, and a short copilot-instructions.md that
points at it plus anything only Copilot needs.
What belongs in the file, and the limits
Neither GitHub's repository-instructions page nor VS Code's custom-instructions page states a byte or character cap. What they do say:
- GitHub's suggested content is a summary of what the repository does; high-level details such as its size, project type, languages, frameworks and target runtimes; the bootstrap, build, test, run and lint steps in the order that makes them succeed; and the major architectural elements with the location of configuration files.
- GitHub's sample prompt for having the cloud agent write the file sets two limitations: instructions "must be no longer than 2 pages" and "must not be task specific". That is guidance inside a suggested prompt rather than an enforced limit, but it is the only size figure GitHub gives.
- VS Code's advice is to keep instructions short and self-contained, include the reasoning behind a rule so the model handles edge cases sensibly, show preferred and avoided patterns as concrete code, and skip conventions a linter or formatter already enforces.
The reason to keep it short is mechanical. The file is attached to every
request, so a 400-line file costs 400 lines of context on a one-line question.
Rules that only concern some files belong in an .instructions.md with an
applyTo; a task belongs in a prompt file.
There is no separate copilot-instructions.md configuration to set. The older
settings-based form — github.copilot.chat.codeGeneration.instructions and its
test-generation counterpart — is deprecated as of VS Code 1.102, and VS Code's
documentation says to use file-based instructions instead.
A GitHub Copilot instructions file template for a TypeScript repository
This copilot-instructions.md example is for a pnpm workspace with a Next.js app and a shared library, on Vitest and ESLint. Replace the specifics; keep the shape.
# Acme monorepo pnpm workspace, TypeScript 5 with `strict` on, ESM only. Two packages: - `packages/web` — Next.js (App Router). Route handlers live in `src/app/api/**/route.ts`; server components by default, `'use client'` only where a hook or a browser API needs it. - `packages/shared` — domain types, the Prisma client and zod schemas. `web` imports from `@acme/shared`; nothing imports from `web`. ## Commands Run from the repository root. - `pnpm install` — Node 22, pnpm 9 (see `packageManager` in package.json) - `pnpm -r build` — builds `shared` first; `web` needs its output - `pnpm -r test` — Vitest; `pnpm --filter web test -- path/to/file` for one file - `pnpm -r lint` and `pnpm -r typecheck` — both must pass before a PR - `pnpm --filter shared prisma migrate dev` — after any edit to `schema.prisma` CI runs the same four commands in `.github/workflows/ci.yml`. ## Conventions - Validate every request body with a zod schema from `@acme/shared`; route handlers return `NextResponse.json` with an explicit status. - Errors are thrown as `AppError` (`packages/shared/src/errors.ts`) with a code, so the error middleware can map them to a status. Do not throw a bare string or a generic `Error` in library code. - No default exports outside `page.tsx`, `layout.tsx` and `route.ts`. - Database access only through `packages/shared/src/db/*`; components never import the Prisma client directly. - Tests sit beside the code as `*.test.ts`. ## Trust these instructions They are maintained with the code. Search the repository only when something here is missing or is contradicted by what you find.
That is about forty lines. It states the commands, names the files that exemplify a pattern, and gives a reason where a rule is not obvious. It does not say "write clean code".
Copilot prompt files: reusable requests in *.prompt.md
Copilot prompt files are saved chat requests rather than standing rules. They
use the .prompt.md extension, live in .github/prompts in the workspace or
in your VS Code profile, and take extra folders from
chat.promptFilesLocations. Run one by typing / and its name in the Chat
view, with Chat: Run Prompt from the Command Palette, or with the play
button in the editor title bar when the file is open.
| Front matter key | Effect |
|---|---|
name | The name typed after / in chat |
description | A short description of the prompt |
argument-hint | Hint text shown in the chat input field |
agent | Which agent runs it: ask, agent, plan, or a custom agent's name |
model | The language model used when running the prompt |
tools | Tool or tool-set names available to it |
The body can use ${selection}, ${input:variableName} and
${input:variableName:placeholder}, reference a tool as #tool:<tool-name>,
and link to other workspace files with relative Markdown links — which is how
a prompt reuses an instruction file instead of duplicating it.
--- name: add-route description: Add a validated Next.js route handler with a test agent: agent tools: ['edit', 'search', 'runCommands'] --- Add a route handler for ${input:route:e.g. /api/customers} in `packages/web`. Follow [the API conventions](../instructions/api.instructions.md). Create the zod schema in `packages/shared`, the handler, and a Vitest file beside it, then run the new test and fix failures before reporting back.
Custom agents are the third companion format: .agent.md files in
.github/agents (or ~/.copilot/agents), with name, description, tools
and model among the front matter keys and a body that is prepended to your
prompt when you pick that agent from the dropdown in the Chat view. VS Code's
documentation notes these "were previously known as custom chat modes" and
says to rename an existing .chatmode.md file to .agent.md.
Ways to generate copilot-instructions.md from the project itself
In VS Code, /init in chat analyses the workspace and writes always-on
instructions, and /create-instruction writes a targeted instruction file. On
GitHub, open the coding agent at github.com/copilot/agents, select the
repository and submit GitHub's suggested prompt; the agent opens a draft pull
request with the file. Writing it by hand still produces the shortest file.
The VS Code extension has a fourth: Autoplans: Generate Copilot
Configuration, in the Command Palette, on the right-click menu of a project
in the Projects & Tasks tree, and as a button in the @autoplans chat
participant. It is also registered as a language-model tool,
autoplans_generate_copilot_config (referenced in a prompt as
#generateCopilotConfig), so agent mode can invoke it; the tool takes no
input.
What it does, from the extension source:
- Picks a project. Invoked from the tree, it is the project you clicked.
From the palette it reads
package.json(name,description), then the first#heading and the first paragraph after it inREADME.mdand.autoplans/README.md, and matches that name against your Autoplans projects — an exact match, or either name containing the other — falling back to your first project, or to a local placeholder if you have none or the request fails. - Reads what is already there. The first 2,000 characters of each of
.github/copilot-instructions.md,AGENT.md,AGENTS.md,CLAUDE.md,.cursorrules,.windsurfrules,.clinerulesandREADME.md, where they exist. - Asks a Copilot model to write the file. It requests a model in the
gpt-4ofamily through VS Code's Language Model API and sends those excerpts with a prompt asking for 20–50 lines of project-specific, discoverable patterns, merged with the existing content rather than replacing it. The prompt also requires a "Task Management with Autoplans" section listing the extension's language-model tools (autoplans_list_tasks,autoplans_update_taskand the rest) and the rule to check assigned tasks before starting and to move status frompendingtoin_progresstocompleted. If no such model is available, or the request fails, it writes a fixed template with the same Autoplans section and headings left for you to fill in. - Writes two files.
.github/copilot-instructions.mdand.github/chatmodes/Autoplanner.chatmode.md, a planning chat mode listing the same tools. Both are written without a confirmation prompt and overwrite whatever is there; the folders are created if missing. Nothing is pushed to GitHub. Under Autoplans: Sync Project to Repository, both "Push to GitHub" and "Both" are labelled "Coming Soon", and the GitHub half of each only shows a message — but "Both" writes the same local files first, overwriting them the same way.
Two consequences follow. Commit before you run it, so the diff shows what the
model did to a file you had already written. And since VS Code now stores
custom agents as .github/agents/*.agent.md and asks you to rename
.chatmode.md files, rename the generated chat-mode file before relying on
it — and read both files as you would any generated code.
The generated file carries an Autoplans section because the same extension
registers those tools with the editor, so an agent session that reads "check
autoplans_list_tasks before starting" can actually do it. The instructions
file then stays short: the plan lives in the backlog rather than in Markdown,
and the agent reads current task status instead of whatever was true on the
day the file was written — the failure mode described in
context rot. The
VS Code documentation covers the tools; to reach the same
backlog over MCP instead, see
VS Code and Copilot MCP setup.