Why custom instructions are foundational

Custom instructions are the highest-leverage customization primitive because they travel with every relevant request. They define your baseline quality bar before any one-off prompt is written.

This post focuses on:

  • Instruction types and precedence
  • File layout and syntax
  • Path-specific targeting with applyTo
  • Patterns from the 9 library instruction examples
  • A step-by-step rollout model

Use cases

  • Developers setting up Copilot for a repository for the first time
  • Maintainers who want consistent code review outcomes
  • Teams that need path-specific guidance without bloating global context

Step 1: Know the instruction types

GitHub Copilot supports three broad instruction scopes on GitHub surfaces:

  1. Personal instructions
  2. Repository custom instructions
  3. Organization custom instructions

Repository instructions can be split further into:

  • Repository-wide file
  • Path-specific instruction files
  • Agent instruction files for agent-oriented workflows

Step 2: Understand precedence and composition

When multiple instruction sets apply, precedence matters.

A practical precedence view:

  1. Personal instructions
  2. Repository instructions
    • Path-specific instruction files
    • Repository-wide instruction file
    • Agent instruction files
  3. Organization instructions

Even with precedence, all relevant instructions may be provided to Copilot. That means conflicts still hurt quality.

Diagram: Precedence stack

+--------------------------------+
| Personal instructions          |
| Highest priority               |
+--------------------------------+
| Repository path-specific files |
| .github/instructions/*.md      |
+--------------------------------+
| Repository-wide instructions   |
| .github/copilot-instructions.md|
+--------------------------------+
| Agent instructions             |
| .github/agents/*.agent.md      |
+--------------------------------+
| Organization instructions      |
| Lowest priority                |
+--------------------------------+

Step 3: Set up repository-wide instructions correctly

Use a single repository-wide file for stable defaults.

Location:

  • .github/copilot-instructions.md

Design principles:

  • Keep statements short and self-contained
  • Prefer broadly applicable engineering rules
  • Avoid task-specific templates in this file

Example repository-wide file

# Project overview

- This repository contains a TypeScript service and React frontend.
- Prefer existing domain patterns before introducing new abstractions.

# Coding conventions

- Use TypeScript for new source files.
- Prefer early returns over deeply nested conditionals.
- Add tests for new behavior and bug fixes.

# Quality checks

- Run lint and tests before finalizing code changes.
- If a command fails, report the failure mode and workaround.

Step 4: Add path-specific instructions for precision

Path-specific files are ideal when different parts of a repo require different standards.

Location pattern:

  • .github/instructions/NAME.instructions.md

Core frontmatter field:

  • applyTo with glob patterns

Optional control:

  • excludeAgent — set to copilot-cloud to prevent this path-specific file from being included when a cloud agent is running, or to copilot-code-review to exclude it from automated code review. Use this when an instruction is author-assistance guidance that would be noisy or contradictory in a code review context.
---
applyTo: "docs/**/*.md"
excludeAgent: "copilot-code-review"
---

When editing documentation:
- Use sentence-case headings.
- Avoid acronyms without definition on first use.
- Link to related docs on first mention.

Example: GitHub Actions path-scoped file

---
applyTo: ".github/workflows/**/*.yml"
---

When editing workflows:
- Pin third-party actions to commit SHAs.
- Set least-privilege permissions for GITHUB_TOKEN.
- Add timeout-minutes to long-running jobs.
- Prefer matrix strategies for multi-runtime testing.

Example: Python tests path-scoped file

---
applyTo: "tests/**/*.py"
---

When writing tests:
- Use pytest fixtures for setup and teardown.
- Follow Arrange, Act, Assert.
- Cover edge cases and failure behavior.
- Mock external dependencies and unstable integrations.

Step 5: Apply the nine library patterns intentionally

The customization library includes nine custom instruction examples. Treat them as pattern modules, not copy-paste artifacts.

Example Primary purpose Where it shines
Your first custom instructions Baseline coding style defaults Team bootstrap
Concept explainer Pedagogical explanations Learning docs and onboarding
Debugging tutor Systematic troubleshooting guidance Incident and bug triage
Code reviewer Security/performance/quality review lens Pre-merge feedback
GitHub Actions helper Workflow security and efficiency CI/CD files
Pull request assistant Structured PR authoring and review style PR consistency
Issue manager Clear bug/feature issue templates Backlog hygiene
Accessibility auditor WCAG-aware generation/testing guidance Frontend templates and audits
Testing automation Focused unit-test generation standards Test-heavy repositories

Step 6: Design instructions for signal, not verbosity

A strong instruction statement is:

  • Specific
  • Observable
  • Actionable
  • Low ambiguity

Weak statement:

  • Write clean code.

Strong statement:

  • For new API handlers, validate all external inputs and return structured error objects with stable error codes.

Use explicit outcomes where possible.

Before and after: seeing instruction impact

This comparison shows what changes when a custom instruction is active.

Prompt (no instruction active):

Add a handler for POST /users.

Typical response without instructions:

app.post('/users', async (req, res) => {
  const user = await db.createUser(req.body);
  res.json(user);
});

No input validation, no error handling, no test suggestion.

With this instruction in .github/copilot-instructions.md:

- Validate all external inputs in API handlers before processing.
- Return structured error objects: `{ error: string, code: string }`.
- Add or suggest tests for new behavior.

Typical response with instructions:

app.post('/users', async (req, res) => {
  const { name, email } = req.body;
  if (!name || !email) {
    return res.status(400).json({ error: 'Missing required fields', code: 'VALIDATION_ERROR' });
  }
  try {
    const user = await db.createUser({ name, email });
    res.status(201).json(user);
  } catch (err) {
    res.status(500).json({ error: 'User creation failed', code: 'DB_ERROR' });
  }
});

// Suggested test:
// POST /users with missing email should return 400 VALIDATION_ERROR

The instruction moved the response from a skeleton to a review-ready draft. That is the leverage point.

Step 7: Validate with an A/B prompt loop

A lightweight validation routine:

  1. Pick a representative prompt, for example, create a handler and tests.
  2. Run once with no custom instructions.
  3. Run again with current instructions.
  4. Score quality on consistency, correctness, and review readiness.
  5. Tighten wording where behavior was ambiguous.

Step 8: Watch critical caveats

Important operational caveats from official docs:

  • Copilot is non-deterministic; instructions increase consistency but do not guarantee identical outputs.
  • For Copilot code review, only the first 4,000 characters of an instruction file are considered.
  • In PR review scenarios on GitHub, instruction resolution uses the base branch context.
  • On GitHub.com, path-specific instructions are currently supported for Copilot cloud agent and Copilot code review.
  • Path-specific support varies by surface overall; validate support for your target workflow.

Step 9: End-to-end example

This example is intentionally small and fully runnable.

Goal

Apply strict guidance only to workflow files and tests, while keeping general repo defaults concise.

Files to create

  1. .github/copilot-instructions.md
# Repository defaults

- Use existing project patterns before introducing new abstractions.
- Add tests for new behavior and bug fixes.
- Explain tradeoffs when suggesting non-trivial changes.
  1. .github/instructions/workflows.instructions.md
---
applyTo: ".github/workflows/**/*.yml"
---

When editing workflows:
- Pin third-party actions to immutable SHAs.
- Set least-privilege permissions.
- Add timeout-minutes to long-running jobs.
  1. .github/instructions/tests.instructions.md
---
applyTo: "tests/**/*.py"
---

When writing tests:
- Use Arrange, Act, Assert.
- Cover edge and failure cases.
- Mock unstable external dependencies.

Verification walkthrough

  1. Ask Copilot to update a workflow file and verify that SHA pinning and timeout guidance appears.
  2. Ask Copilot to generate a test under tests/ and verify AAA structure and failure coverage.
  3. Ask for a regular source-code refactor and confirm workflow/test-specific rules do not leak unnecessarily.

What success looks like

  • General rules apply everywhere.
  • Path-specific guidance activates only when matching files are in scope.
  • Output quality improves without overwhelming context.

Key takeaways

  • Custom instructions are your always-on quality baseline.
  • Keep repository-wide instructions concise; use path-specific files for precision.
  • Resolve conflicts across personal, repository, and organization scopes early.
  • Design statements as testable engineering constraints, not style slogans.
  • Validate instruction effectiveness with repeatable before/after tasks.


References