Instructions are persistent rules that Copilot follows automatically — either whenever you open a specific file type or when manually referenced. They shape every suggestion without needing to repeat yourself.
Location: templates/instructions/*.instructions.md
There are two modes:
Uses applyTo globs in frontmatter. Whenever you open or edit a matching file, the instruction is silently loaded into context.
---
applyTo: '**/*.ts,**/*.tsx'
---
Rules for TypeScript files...Uses description in frontmatter (no applyTo). Available via # reference in Copilot Chat to pull in when needed.
---
description: 'REST API design conventions'
---
Rules for API design...These activate automatically when you edit matching files:
Applies to: **/*.ex, **/*.exs
Key rules:
- Target Elixir 1.18+ / OTP 27+
- Use pipe operator
|>for data transformations (3+ steps) - Pattern match in function heads rather than
if/caseinside - Use
withfor multi-step operations that may fail - Return
{:ok, value}/{:error, reason}for operations that can fail - Use
@moduledocand@docfor public modules and functions - ExUnit tests: use
describeblocks grouped by function name
Applies to: **/*.ts, **/*.tsx, **/*.mts, **/*.cts
Key rules:
- Target TypeScript 5.7+ with strict mode
- Prefer
interfacefor object shapes,typefor unions/intersections - Use discriminated unions over optional fields for variants
- Prefer
unknownoverany— use type guards to narrow - Use
satisfiesoperator for type checking without widening - Use branded types for domain identifiers
- Use
as constfor literal tuples and config objects - Prefer
Map/Setover plain objects for dynamic keys - Use
using/Symbol.disposefor resource management
Applies to: **/*.tsx, **/*.jsx
Key rules:
- Target React 19+ patterns
- Use
use()for promises and context,useActionState()for forms - Return
ReactNodefrom components (notJSX.Element) - Keep components < 150 LOC — extract custom hooks for logic
- State hierarchy: URL → Server → Global → Local
- Memoize only with measured perf problems
- Every interactive element needs keyboard support
- Images need meaningful
alttext
Applies to: **/*.css, **/*.scss, **/*.module.css, **/*.module.scss
Key rules:
- Use native CSS nesting instead of preprocessor nesting
- Use
oklch()for perceptually uniform colors - Use
@layerfor cascade management - Use container queries
@containerfor component-level responsiveness - Use logical properties (
inline-startoverleft) - Design for dark mode with
prefers-color-scheme - Motion: respect
prefers-reduced-motion - Mobile-first media queries
Applies to: **/Dockerfile*, **/docker-compose*.yml
Key rules:
- Always use multi-stage builds (builder → runner)
- Pin base images with digest or full version tag
- Install only production dependencies in final stage
- Run as non-root user with minimal permissions
- Use
.dockerignore(exclude.git,node_modules, etc.) - Order layers by change frequency (COPY deps → COPY source)
- Use
HEALTHCHECKin production Dockerfiles - Use
COPY --linkfor better layer caching with BuildKit
Applies to: **/*.test.*, **/*.spec.*, **/*_test.*, **/test/**
Key rules:
- Follow Arrange-Act-Assert (Given-When-Then) structure
- One assertion per test (or one logical assertion)
- Test behavior and outcomes, not implementation details
- Use descriptive names:
test "returns error when email is invalid" - Mock at boundaries only (HTTP, database, filesystem)
- Use factories/fixtures over raw data construction
- Async tests: always use explicit assertions for async outcomes
- Coverage: aim for critical paths, not arbitrary percentages
Applies to: **/migrations/**, **/priv/repo/migrations/**
Key rules:
- All migrations must be reversible (include
down/change) - Provide default values for new NOT NULL columns
- Use
CREATE INDEX CONCURRENTLYfor large tables - Separate schema changes from data migrations
- Consider zero-downtime: add columns first, then constraints
- Name constraints explicitly
- Use appropriate PostgreSQL types (
citext,timestamptz,uuid) - Test migrations with representative data volume
Applies to: **/*.md, **/docs/**
Key rules:
- Use active voice by default
- Use "you" for the reader and "we" for the team
- Cut filler: "In order to" → "To", "It should be noted that" → delete
- Remove hedge stacks: "might potentially" → "can"
- Replace vague adjectives with measurables: "fast" → "responds in <100ms"
- Avoid AI-marker phrases: "leverage", "robust", "comprehensive", "seamless"
- One idea per sentence, paragraphs of 3-4 sentences max
- Start sections with what the reader needs to do, not background
Applies to: **/*.py
Key rules:
- Target Python 3.12+
- Use type hints on all function signatures
- Follow PEP 8 with 88-char line length (Black default)
- Prefer f-strings over
.format()or%formatting - Use
pathlib.Pathoveros.path - Use
dataclassesorattrsfor data containers - Use
match/casefor structural pattern matching - Prefer list/dict comprehensions over
map/filter - Use
from __future__ import annotationsfor forward refs
Applies to: **/*.rb, **/Gemfile, **/Rakefile
Key rules:
- Target Ruby 3.3+
- Add
# frozen_string_literal: trueto every file - Use pattern matching (
in/case...in) for complex conditionals - Follow Rails conventions: fat models, skinny controllers
- Use
ActiveRecordscopes over class methods for queries - Prefer
then/and_thenchaining for sequential operations - Use keyword arguments for methods with 3+ parameters
- Guard clauses over nested conditionals
Applies to: **/*.go
Key rules:
- Target Go 1.22+
- Wrap errors with
fmt.Errorf("context: %w", err) - Use table-driven tests with
t.Runsubtests - Use
context.Contextas the first parameter for cancellable operations - Prefer
errors.Is/errors.Asover string comparison - Use goroutines with
errgroupfor structured concurrency - Follow Effective Go naming: short variable names in small scopes
- Use
slogfor structured logging
Applies to: **/*.rs
Key rules:
- Target Rust 2024 edition
- Use
thiserrorfor library errors,anyhowfor application errors - Prefer ownership patterns that avoid
clone()where possible - Avoid
unsafeunless absolutely necessary and document why - Use
#[must_use]on functions that return important values - Use
impl Traitin argument position for flexibility - Prefer iterators over manual loops
- Use
clippywithpedanticlint group enabled
Applies to: **/*.swift
Key rules:
- Target Swift 6+ with strict concurrency checking
- Use structured concurrency (
async let,TaskGroup) over unstructuredTask {} - Prefer
@ObservableoverObservableObject/@Published(Swift 5.9+) - Use SwiftUI patterns: small views,
ViewModifierfor reusable styling - Use
sendingparameter modifier for cross-isolation data - Use
guardfor early returns and precondition checks - Prefer value types (
struct,enum) over reference types (class)
Applies to: **/*.kt, **/*.kts
Key rules:
- Target Kotlin 2.0+
- Use coroutines with structured concurrency (
coroutineScope,supervisorScope) - Use
sealed class/sealed interfacefor restricted hierarchies - Prefer
data classfor DTOs and value objects - Use Compose patterns: stateless composables, state hoisting
- Prefer
whenexpressions overif-elsechains - Use
Resulttype for operations that can fail - Use extension functions to add behavior without inheritance
Applies to: **/*.vue
Key rules:
- Target Vue 3.5+ with Composition API
- Use
<script setup>for all components - Use TypeScript with
defineProps<T>()anddefineEmits<T>() - Use
composables(use-prefixed functions) for reusable logic - Prefer
ref()overreactive()for primitives - Use
computed()for derived state,watch()sparingly - Use
defineModel()for two-way binding - Follow SFC order:
<script setup>,<template>,<style scoped>
Applies to: **/*.graphql, **/*.gql
Key rules:
- Use schema-first design — define types before resolvers
- Use DataLoader for batching and caching N+1 queries
- Use union types for error handling (
type Result = Success | NotFound | ValidationError) - Use persisted queries in production to prevent arbitrary query execution
- Use
IDscalar for node identifiers - Paginate with Relay-style connections (
edges,pageInfo) - Prefer input types for mutations over loose arguments
- Use
@deprecateddirective before removing fields
These are available via # reference in Copilot Chat:
Use when: Designing or implementing REST API endpoints.
Key rules:
- Use plural nouns for resources (
/users,/posts) - HTTP methods: GET (read), POST (create), PUT (full update), PATCH (partial), DELETE
- Status codes: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity, 429 Too Many Requests
- Always return consistent error format with
code,message, anddetails - Use cursor-based pagination for large collections
- Version via URL prefix (
/api/v1/) - Rate limiting headers on all responses
Use when: Building UI components, forms, or interactive elements.
Key rules:
- Target WCAG 2.2 Level AA
- Use semantic HTML elements (
<nav>,<main>,<article>,<button>) - All images need meaningful
alttext (oralt=""for decorative) - All interactive elements must be keyboard-accessible
- Focus must be visible and follow logical order
- Color contrast: 4.5:1 for text, 3:1 for large text and UI components
- ARIA: use only when no native HTML element works
- Forms: associate all inputs with labels, provide error messages
Use when: Creating branches, writing commits, or preparing PRs.
Key rules:
- Branch naming:
feat/,fix/,chore/,docs/,refactor/prefixes - Conventional Commits:
type(scope): subject - Subject: imperative mood, ≤72 chars, no period
- Body: what and why, not how (code explains how)
- Keep commits atomic — one logical change per commit
- Squash WIP commits before merge
- PRs: descriptive title, reference issue with
Closes #N
You open src/components/Button.tsx
→ *.tsx matches react.instructions.md ✅
→ *.tsx matches typescript.instructions.md ✅
→ Both are silently loaded into Copilot's context
→ Every suggestion follows both rule sets
Multiple instructions can stack on the same file. Keep instructions focused (one concern per file) to avoid context bloat.
- Test auto-attach: Open a matching file and ask Copilot Chat "what instructions are active?"
- Reference on-demand: Type
#in Chat, then select the instruction file - Don't overlap: If two instructions conflict on the same glob, one wins unpredictably
- Keep them concise: Instructions share the context window with your code — shorter is better
- Create your own: See Customization for adding custom instructions