How to Structure Content for GitHub Copilot Instruction Files
How to Structure Content for GitHub Copilot Instruction Files
Instruction files (.instructions.md) are a powerful way to provide context-specific guidelines that automatically apply to files matching specific patterns.
Unlike prompt files (which are invoked on-demand) or agent files (which define persistent personas), instruction files work silently in the background, influencing Copilot’s behavior whenever you work with matching files.
This article explores how to structure instruction files effectively, understanding their limitations, and avoiding common pitfalls that can lead to unwanted bias, confusion, or distraction.
Table of Contents
🎯 Understanding Instruction Files
What Are Instruction Files?
Instruction files define coding standards, best practices, and contextual rules that automatically apply when working with specific files or file types. They’re stored in .github/instructions/ (workspace-level) or your VS Code user profile (user-level) and use glob patterns to determine when they activate.
Key Characteristics
| Aspect | Description |
|---|---|
| Extension | .instructions.md |
| Activation | Automatic based on applyTo pattern |
| Scope | File/directory-specific or project-wide |
| Visibility | Silent - not shown in chat but applied to context |
| Priority | Combined with other instructions (no specific order guaranteed) |
| Tool Control | None (relies on agent/prompt tool configuration) |
When to Use Instruction Files
✅ Use instruction files for:
- Coding standards - Language-specific conventions (e.g., Python PEP 8, C# naming conventions)
- Framework guidelines - React component patterns, API design rules
- Security requirements - Authentication checks, input validation rules
- Documentation standards - Comment styles, README requirements
- Build/test patterns - Test file structure, CI/CD requirements
❌ Don’t use instruction files for:
- Task-specific workflows - Use prompt files instead (e.g., “generate component with tests”)
- One-time operations - Use chat commands or inline chat
- Persona definition - Use agent files instead (e.g., “security reviewer” role)
- Complex multi-step processes - Use prompts or agents with workflow capabilities
📋 Instruction File Structure
File Format
Instruction files are Markdown documents with an optional YAML frontmatter header:
---
description: "Brief description of these instructions"
name: "Display name (defaults to filename)"
applyTo: "**/*.ts,**/*.tsx"
excludeAgent: "code-review" # Optional: exclude from specific agents
---
# Instruction Body
Your coding standards and guidelines in Markdown format.YAML Frontmatter Fields
Required Fields
None - all frontmatter is optional, but applyTo is highly recommended.
Optional Fields
| Field | Type | Description | Example |
|---|---|---|---|
description |
String | Brief description shown in UI | "TypeScript coding standards" |
name |
String | Display name (defaults to filename without extension) | "React Guidelines" |
applyTo |
String | Glob pattern(s) for file matching | "**/*.py" or "**/*.ts,**/*.tsx" |
excludeAgent |
String | Exclude from specific agents: "code-review" or "coding-agent" |
"code-review" |
ApplyTo Pattern Examples
| Pattern | Matches | Example Files |
|---|---|---|
**/*.py |
All Python files recursively | src/main.py, tests/test_api.py |
**/*.ts,**/*.tsx |
All TypeScript files | components/Button.tsx, utils/helpers.ts |
src/**/*.js |
JavaScript files under src/ | src/app.js, src/utils/format.js |
**/test_*.py |
Python test files anywhere | tests/test_user.py, src/tests/test_api.py |
docs/**/*.md |
Markdown files under docs/ | docs/README.md, docs/api/endpoints.md |
** |
All files (use sparingly) | Everything in workspace |
⚠️ Important: If applyTo is omitted, instructions are not applied automatically - you must attach them manually to chat requests.
Body Content
The instruction body contains your guidelines in Markdown format. This is where you define:
- Coding standards: Naming conventions, formatting rules, code organization
- Best practices: Security patterns, performance considerations, error handling
- Framework-specific rules: Component structure, API design, testing patterns
- Tool usage: Reference specific tools using
#tool:<tool-name>syntax
Example structure:
---
applyTo: "**/*.tsx"
---
# React Component Guidelines
## Naming Conventions
- Use PascalCase for component names
- Use camelCase for props and handlers
- Prefix boolean props with `is`, `has`, or `should`
## Component Structure
- Functional components with TypeScript
- Props interface defined before component
- Hooks at the top of component body
## Example
```tsx
interface ButtonProps {
label: string;
onClick: () => void;
isDisabled?: boolean;
}
export const Button: React.FC<ButtonProps> = ({ label, onClick, isDisabled = false }) => {
return <button onClick={onClick} disabled={isDisabled}>{label}</button>;
};Tool References
Use #tool:codebase to find similar components before creating new ones.
# ✍️ Writing Effective Instructions
## Core Principles
### 1. Be Specific and Concise
<mark>**Each instruction should be a single, clear statement**</mark>. Avoid vague guidelines that can be interpreted multiple ways.
**❌ Vague:**
```markdown
Write good code that follows best practices.
✅ Specific:
- Use descriptive variable names (minimum 3 characters, except loop counters)
- Always include error handling for async operations
- Add JSDoc comments for all exported functions2. Focus on “How”, Not “Why”
Instructions should guide behavior, not explain rationale (unless the explanation is necessary for correct implementation).
❌ Too much explanation:
We use dependency injection because it makes code more testable and follows
SOLID principles. Dependency injection allows for better separation of concerns
and makes mocking easier during unit testing...✅ Actionable guidance:
- Inject dependencies through constructor parameters
- Use interfaces for all injectable dependencies
- Register services in the DI container, not in constructors3. Use Examples
Examples demonstrate correct usage and help Copilot understand the pattern you want.
## Error Handling Pattern
All API functions must include try-catch with proper error logging:
```typescript
async function fetchUser(id: string): Promise<User> {
try {
const response = await api.get(`/users/${id}`);
return response.data;
} catch (error) {
logger.error('Failed to fetch user', { userId: id, error });
throw new AppError('User fetch failed', { cause: error });
}
}
### 4. Organize by Topic
<mark>Group related guidelines under clear headings</mark>. This improves readability and helps Copilot apply relevant rules.
```markdown
## Naming Conventions
- Classes: PascalCase
- Variables/Functions: camelCase
- Constants: UPPER_SNAKE_CASE
## File Organization
- One component per file
- Co-locate tests with source: `Button.tsx` + `Button.test.tsx`
- Keep utility functions in `utils/` directory
## Security
- Never commit secrets or API keys
- Sanitize all user input before database operations
- Use parameterized queries for SQL
5. Reference Tools When Appropriate
Use the #tool:<tool-name> syntax to guide Copilot to use specific capabilities:
## Before Creating New Components
Use #tool:codebase to search for similar existing components.
Use #tool:search to find component usage patterns.Content Length Guidelines
Keep instruction files focused and concise. While there’s no hard token limit for individual instruction files, remember:
- VS Code combines multiple instruction files when they match the current context
- Instructions are added to every relevant chat request, consuming context window space
- Long instructions dilute important guidelines by burying key points in detail
Recommended lengths:
| Scope | Recommended Length | Example |
|---|---|---|
| Single language/framework | 100-300 lines | Python PEP 8 guidelines |
| Project-wide general rules | 50-150 lines | Company coding standards |
| Specific feature/pattern | 30-100 lines | API error handling pattern |
⚠️ If instructions exceed 500 lines, consider splitting into multiple files with more specific applyTo patterns.
⚠️ Critical Limitations and Boundaries
Understanding what instruction files cannot do is just as important as knowing what they can do.
Technical Limitations
1. No Guaranteed Order
When multiple instruction files match the current context, VS Code combines them but no specific order is guaranteed. This means:
❌ Don’t write instructions that depend on order:
<!-- file: base-rules.instructions.md -->
Use the error handling pattern defined earlier.
<!-- file: api-rules.instructions.md -->
Here's the error handling pattern: [pattern details]✅ Make each file self-contained:
<!-- file: base-rules.instructions.md -->
General coding rules...
<!-- file: api-rules.instructions.md -->
API Error Handling Pattern:
[complete pattern with examples]2. Conflicts Are Non-Deterministic
If multiple instruction files provide conflicting guidance, Copilot’s choice is non-deterministic. Avoid potential conflicts between instructions.
❌ Conflicting instructions:
<!-- file: python-naming.instructions.md -->
Use snake_case for all function names.
<!-- file: api-naming.instructions.md -->
Use camelCase for API endpoint handlers.✅ Resolve conflicts explicitly:
<!-- file: python-naming.instructions.md -->
applyTo: "**/*.py"
---
Use snake_case for function names, EXCEPT API handlers (use camelCase for those).
<!-- file: api-naming.instructions.md -->
applyTo: "**/api/**/*.py"
---
API endpoint handlers use camelCase to match JavaScript frontend conventions.3. Instructions Are Always Applied (When Pattern Matches)
Instructions cannot be toggled on/off for specific chat requests. If the applyTo pattern matches the current file, the instructions are included.
This means:
- ❌ Can’t temporarily disable instructions for experimentation
- ❌ Can’t choose between different instruction “profiles”
- ✅ Use more specific
applyTopatterns to control when instructions apply - ✅ Use
excludeAgentto exclude instructions from specific agents
4. No Tool Control
Instruction files cannot specify which tools are available (unlike prompts and agents). They rely on:
- Default tools available to the current agent
- Tool configuration in prompt files (if used)
- Tool configuration in agent files (if active)
5. Silent Application
Instructions are not visible in chat - they’re silently added to the context. This can lead to:
- ❌ Users unaware why Copilot generates code a certain way
- ❌ Debugging confusion when unexpected patterns appear
- ✅ Check References list in chat to see which instruction files were applied
Context Window Limitations
Every instruction file consumes part of the LLM’s context window. Be mindful of cumulative impact:
Context consumption example:
| File | Lines | Tokens (approx) | Pattern |
|---|---|---|---|
general-rules.instructions.md |
150 | ~600 | ** (all files) |
python-pep8.instructions.md |
200 | ~800 | **/*.py |
react-patterns.instructions.md |
180 | ~720 | **/*.tsx |
api-security.instructions.md |
120 | ~480 | **/api/**/* |
| Total (for a React + Python project) | 650 | ~2600 |
If you’re working on a .tsx file in the api/ directory, all four files could apply simultaneously, consuming ~2600 tokens before your actual prompt.
Best practices to manage context:
- Use specific patterns - Don’t use
**unless absolutely necessary - Split by scope - Multiple focused files > one massive file
- Avoid duplication - Don’t repeat guidelines across files
- Review regularly - Remove outdated or unused instructions
🚫 Common Pitfalls and How to Avoid Them
Pitfall 1: Instructions Too Broad
Problem: Using applyTo: "**" causes instructions to apply to every file, even when inappropriate.
❌ Bad example:
---
applyTo: "**"
---
Always use async/await for asynchronous operations.
Always include unit tests.This applies to configuration files, READMEs, scripts, etc., causing confusion.
✅ Solution: Be specific:
---
applyTo: "src/**/*.ts,src/**/*.tsx"
---
For TypeScript source files:
- Use async/await for asynchronous operations
- Include unit tests in co-located `.test.ts` filesPitfall 2: Conflicting Instructions
Problem: Multiple instruction files give contradictory guidance for the same situation.
❌ Bad example:
<!-- python-general.instructions.md -->
Use single quotes for strings.
<!-- python-api.instructions.md -->
Use double quotes for strings to match JSON conventions.✅ Solution: Resolve explicitly or use hierarchy:
<!-- python-general.instructions.md -->
applyTo: "**/*.py"
---
Use single quotes for strings, EXCEPT in API modules (use double quotes).
<!-- python-api.instructions.md -->
applyTo: "**/api/**/*.py"
---
API modules use double quotes for strings (matches JSON conventions).Pitfall 3: Instructions Too Detailed
Problem: Overly verbose instructions consume context and dilute important rules.
❌ Bad example:
When writing functions in Python, you should always think about readability
because code is read more often than written. PEP 8 recommends...
[500 lines of explanations and history]✅ Solution: Concise, actionable rules:
## Function Guidelines (PEP 8)
- Lowercase with underscores: `calculate_total()`
- Max line length: 79 characters
- Docstrings for all public functions
- Type hints for parameters and return valuesPitfall 4: Implicit Dependencies
Problem: Instructions reference concepts defined in other instruction files without repeating necessary context.
❌ Bad example:
<!-- file: advanced-patterns.instructions.md -->
Use the Repository Pattern defined in our base architecture.If the base architecture file doesn’t apply to the current file, this instruction is confusing.
✅ Solution: Self-contained instructions:
<!-- file: advanced-patterns.instructions.md -->
Repository Pattern:
- All database access through repository interfaces
- Repository implementations in `repositories/` directory
- Example: `UserRepository` interface + `PostgresUserRepository` implementationPitfall 5: Instructions as Documentation
Problem: Using instruction files to document how things work rather than guide how to code.
❌ Bad example:
Our application uses a three-tier architecture. The presentation layer handles
HTTP requests, the business logic layer processes data, and the data access
layer interacts with databases. This pattern was chosen because...✅ Solution: Focus on actionable guidance:
## Three-Tier Architecture Rules
- Controllers (presentation): Handle HTTP, no business logic
- Services (business logic): Pure functions, no database access
- Repositories (data access): Database operations only
Place files: `controllers/`, `services/`, `repositories/`Pitfall 6: Overuse of Global Instructions
Problem: Repository-wide instructions (.github/copilot-instructions.md) become too large and apply to inappropriate contexts.
❌ Bad example:
<!-- .github/copilot-instructions.md - 2000 lines -->
Python rules...
JavaScript rules...
React patterns...
API security...
Database patterns...
[everything for every technology]✅ Solution: Split into specific instruction files:
.github/
copilot-instructions.md # General project info (100 lines)
instructions/
python-standards.instructions.md # applyTo: "**/*.py"
react-patterns.instructions.md # applyTo: "**/*.tsx"
api-security.instructions.md # applyTo: "**/api/**/*"
database-patterns.instructions.md # applyTo: "**/repositories/**/*"
🎨 Advanced Patterns
Pattern 1: Layered Instructions
Use multiple instruction files with increasingly specific patterns to create a hierarchy:
.github/instructions/
general-code-quality.instructions.md # applyTo: "**"
backend-python.instructions.md # applyTo: "backend/**/*.py"
backend-api-endpoints.instructions.md # applyTo: "backend/api/**/*.py"
backend-api-auth.instructions.md # applyTo: "backend/api/auth/**/*.py"
Each layer adds more specific guidance without duplicating rules from broader layers.
Pattern 2: Exclude Patterns for Edge Cases
Use multiple files with complementary patterns and excludeAgent to handle special cases:
<!-- standard-review.instructions.md -->
---
applyTo: "src/**/*.py"
excludeAgent: "code-review" # Don't apply to manual reviews
---
Automated code standards (for coding agent only)...<!-- manual-review-guidelines.instructions.md -->
---
applyTo: "src/**/*.py"
excludeAgent: "coding-agent" # Don't apply to coding agent
---
Human reviewer guidelines (for code review only)...Pattern 3: Technology-Specific Instructions
Organize by technology stack with precise glob patterns:
.github/instructions/
frontend/
react-components.instructions.md # applyTo: "src/components/**/*.tsx"
react-hooks.instructions.md # applyTo: "src/hooks/**/*.ts"
react-context.instructions.md # applyTo: "src/contexts/**/*.tsx"
backend/
api-routes.instructions.md # applyTo: "api/routes/**/*.py"
database-models.instructions.md # applyTo: "api/models/**/*.py"
background-jobs.instructions.md # applyTo: "api/jobs/**/*.py"
Pattern 4: Test-Specific Instructions
Separate instructions for source vs. test files:
<!-- source-code.instructions.md -->
---
applyTo: "src/**/*.ts"
---
Production code guidelines...<!-- test-code.instructions.md -->
---
applyTo: "**/*.test.ts,**/*.spec.ts"
---
Test code guidelines:
- Use descriptive test names: `test('should calculate total when given valid items', ...)`
- Follow AAA pattern: Arrange, Act, Assert
- Mock external dependenciesPattern 5: Tool-Driven Instructions
Guide Copilot to use specific tools for certain operations:
---
applyTo: "src/**/*.tsx"
---
# React Component Guidelines
## Before Creating New Components
Use #tool:codebase to search for similar components:
1. Check if component already exists
2. Find reusable patterns in existing components
3. Ensure naming consistency with existing components
## Before Modifying Components
Use #tool:usages to check component usage:
- Verify changes won't break existing uses
- Consider creating new component for breaking changes🧪 Testing and Validation
How to Test Instruction Files
Instructions are invisible, making testing indirect. Here’s how to validate them:
1. Check the References List
When using Copilot Chat in VS Code, expand the References list at the top of responses. Instruction files that matched your current file will be listed.

2. Test with Specific File Types
- Open a file that should match your
applyTopattern - Ask Copilot to generate code relevant to your instructions
- Check if generated code follows your guidelines
Example test:
<!-- File: .github/instructions/python-naming.instructions.md -->
---
applyTo: "**/*.py"
---
Always use snake_case for function names and variables.Test: Open a .py file, ask Copilot: “Create a function that calculates total price with tax”
Expected: Function named calculate_total_price_with_tax, not calculateTotalPriceWithTax
3. Test with Conflicting Instructions
Deliberately create overlapping patterns to verify Copilot handles them gracefully:
<!-- test-conflict-1.instructions.md -->
---
applyTo: "test/**/*.py"
---
Prefix test functions with `test_`<!-- test-conflict-2.instructions.md -->
---
applyTo: "**/*.py"
---
Use descriptive function namesOpen test/test_user.py, ask for a test. Verify both instructions are honored: test_user_authentication_succeeds_with_valid_credentials()
4. Verify excludeAgent Works
<!-- coding-agent-only.instructions.md -->
---
applyTo: "**/*.py"
excludeAgent: "code-review"
---
[specific guidelines]Test by:
- Using Copilot coding agent (should apply instructions)
- Using Copilot code review (should NOT apply instructions)
Validation Checklist
Before committing instruction files, verify:
💡 Decision Framework
Use this flowchart to decide whether to use instruction files or alternatives:
START: Need to provide guidance to Copilot?
│
├─ Is this guidance specific to certain file types/locations?
│ │
│ YES─ Will this guidance be used repeatedly?
│ │ │
│ │ YES─ Is the guidance < 500 lines?
│ │ │ │
│ │ │ YES─ ✅ USE INSTRUCTION FILE
│ │ │ │
│ │ │ NO─ ⚠️ SPLIT INTO MULTIPLE INSTRUCTION FILES
│ │ │
│ │ NO─ Is this a one-time task?
│ │ │
│ │ YES─ ✅ USE PROMPT FILE or INLINE CHAT
│ │ │
│ │ NO─ ✅ USE PROMPT FILE (reusable task)
│ │
│ NO─ Is this defining a persona or role?
│ │
│ YES─ ✅ USE AGENT FILE
│ │
│ NO─ Is this general project info?
│ │
│ YES─ ✅ USE .github/copilot-instructions.md
│ │
│ NO─ ❓ RECONSIDER: Maybe not needed?
Quick Reference Table
| Need | Solution | File Type |
|---|---|---|
| TypeScript coding standards | Instruction file | typescript-standards.instructions.md |
| Generate React form component | Prompt file | create-react-form.prompt.md |
| Security reviewer persona | Agent file | security-reviewer.agent.md |
| General project architecture | Repository instructions | .github/copilot-instructions.md |
| One-time code refactoring | Chat command | Inline chat or /explain, /fix commands |
| Multi-step workflow | Agent file or Prompt file | Depends on reusability |
🎯 Conclusion
Instruction files are a powerful but subtle tool for shaping Copilot’s behavior. When used correctly, they ensure consistent coding standards across your project without manual intervention. When used poorly, they consume context, create confusion, and introduce unpredictable behavior.
Key takeaways:
- Be specific with
applyTopatterns - Avoid broad patterns like** - Keep instructions concise and actionable - Focus on “how”, not “why”
- Avoid conflicts between instruction files - Make each file self-contained
- Test with actual file types - Verify instructions apply correctly
- Monitor context consumption - Multiple files add up quickly
- Use the right tool for the job - Instructions aren’t always the answer
By following these guidelines, you’ll create instruction files that enhance Copilot’s effectiveness without introducing unwanted side effects.
📚 References
Official Documentation
GitHub: Adding Repository Custom Instructions [📘 Official]
Official GitHub documentation for creating repository-level custom instructions including .github/copilot-instructions.md and path-specific .instructions.md files. Covers frontmatter syntax, glob patterns, and the excludeAgent property. Essential reference for understanding how GitHub interprets instruction files across different platforms (VS Code, Visual Studio, GitHub.com).
VS Code: Use Custom Instructions [📘 Official]
Microsoft’s official documentation for custom instructions in VS Code. Explains the three types of instruction files (.github/copilot-instructions.md, .instructions.md, and AGENTS.md), how they’re combined, and provides examples of effective instruction structures. Includes details on user-scope vs. workspace-scope instructions and Settings Sync.
VS Code: Copilot Customization Overview [📘 Official]
Comprehensive overview of all Copilot customization options in VS Code, including instructions, prompts, and agents. Explains how different customization types work together and when to use each. Critical for understanding the broader context of instruction files within the customization ecosystem.
Best Practices and Community Resources
GitHub Blog: How to Use GitHub Copilot - Tips, Tricks, and Best Practices [📗 Verified Community]
GitHub’s official blog post on maximizing Copilot effectiveness through context management. While focused on general Copilot usage, provides crucial insights on how context (including instructions) impacts suggestion quality. Explains the “context, context, context” principle that applies to instruction file design.
Awesome GitHub Copilot Repository [📗 Verified Community]
Community-curated collection of Copilot customizations including example instruction files. Browse the /instructions directory for real-world examples across different languages and frameworks. Demonstrates practical patterns for instruction file organization and content structure.
GitHub Blog: Prompting with GitHub Copilot [📗 Verified Community]
Official guide to prompt engineering with Copilot. While focused on prompts, the principles of clarity, specificity, and context apply equally to instruction files. Essential reading for understanding how to write effective guidance for LLMs.