Understanding Copilot's configuration evolution is a great start to understand how Github innovates in this field:
Historical Timeline
2021-2023: No Project-Level Configuration
- Only user-level and workspace settings
- No way to share coding standards via files
- Each developer manually configured preferences
August 2024: Experimental Instructions
- Introduced
github.copilot.chat.experimental.codeGeneration.instructions - JSON-based configuration in VS Code settings
- Limited to code generation, not all Copilot features
October 2024: Official File-Based Instructions
-
.github/copilot-instructions.mdenabled by default - Markdown format for natural language instructions
- Repository-wide context for all Copilot features
March 2025: Personal Instructions (GA)
- User-level instructions in GitHub profile
- Global preferences across all projects
July 2025: Path-Specific Instructions
-
.github/instructions/*.instructions.mdfiles - Scope rules to specific directories or file patterns
- YAML frontmatter for path matching
Why Copilot Lagged Behind Competitors
GitHub Copilot initially focused on:
- Inline autocomplete (fast, lightweight)
- Individual developer productivity (not team standards)
- Cross-IDE compatibility (minimal per-IDE configuration)
- GitHub ecosystem integration (rather than IDE-specific features)
Advanced customization was reserved for Copilot Enterprise ($39/month) through "coding guidelines" in private preview. Only in late 2024 did GitHub democratize project-level instructions across all tiers.
Current Architecture (2025)
GitHub Copilot now uses a four-tier instruction system:
Priority Order (Highest to Lowest):
1. Personal Instructions (user profile)
2. Repository Instructions (.github/copilot-instructions.md)
3. Path-Specific Instructions (.github/instructions/*.instructions.md)
4. Organization Instructions (Copilot Business/Enterprise)
Official Configuration Methods
Supported Files and Locations
| File | Location | Format | Tier | Auto-Load | Since |
|---|---|---|---|---|---|
copilot-instructions.md |
.github/ |
Markdown | Free+ | ✅ Yes | Oct 2024 |
*.instructions.md |
.github/instructions/ |
Markdown + YAML | Free+ | ✅ Yes | Jul 2025 |
| Personal Instructions | GitHub Settings | Web UI | Free+ | ✅ Yes | Mar 2025 |
| Organization Guidelines | Admin Console | Web UI | Business/Enterprise | ✅ Yes | 2024 |
What Gets Loaded
VS Code:
- All four instruction tiers
- Workspace settings (
.vscode/settings.json) - Model configuration from VS Code settings
JetBrains IDEs:
- All four instruction tiers
- IDE settings (per-project and global)
- Plugin configuration
GitHub.com:
- Repository instructions
- Organization guidelines
- Personal instructions
- Used in Pull Request reviews, Copilot Chat
GitHub Desktop:
- ❌ No instruction file support
- Only organization guidelines (if Enterprise)
GitHub CLI:
- Repository instructions (if in git repo)
- Personal instructions
- Organization guidelines
Repository-Level Instructions
File: .github/copilot-instructions.md
Purpose: Project-wide coding standards, architecture context, and team conventions.
Visibility: All team members, automatically loaded in all Copilot surfaces.
When to Use:
- Project-specific coding standards
- Tech stack and architecture documentation
- Team conventions and patterns
- Testing requirements
- Deployment procedures
Creating Your First Instructions File
Step 1: Create the File
# Navigate to repository root
cd my-project
# Create .github directory if it doesn't exist
mkdir -p .github
# Create instructions file
touch .github/copilot-instructions.md
Step 2: Basic Structure
# GitHub Copilot Instructions
**Project**: [Your Project Name]
**Last Updated**: 2025-11-29
---
## Project Overview
[One-paragraph description of what this project does]
---
## Technology Stack
- **Language**: TypeScript 5.4
- **Framework**: Next.js 15 (App Router)
- **Database**: PostgreSQL 16
- **ORM**: Drizzle ORM
---
## Coding Standards
### TypeScript
- Use strict mode
- Explicit return types on all functions
- No `any` types
### React
- Functional components only
- Server Components by default
- Add `'use client'` only when needed
---
## Testing Requirements
- Unit tests: Vitest
- E2E tests: Playwright
- Minimum 80% coverage
---
## Important Notes
- Use `pnpm` (NOT npm or yarn)
- All commits follow Conventional Commits format
- Environment variables in `.env.local` (never commit secrets)
Step 3: Commit and Push
git add .github/copilot-instructions.md
git commit -m "docs: add GitHub Copilot instructions"
git push origin main
Step 4: Verify Loading
Open any file in your project and ask Copilot Chat:
What are the coding standards for this project?
Copilot should reference your instructions.
Comprehensive Template
# GitHub Copilot Instructions
**Project**: E-Commerce Platform
**Version**: 2.0.0
**Last Updated**: 2025-11-29
**Maintainers**: @frontend-team, @backend-team
---
## Project Context
### Overview
Full-stack e-commerce platform built with Next.js and PostgreSQL.
Supports multi-tenant SaaS model with row-level security.
### Goals
- Handle 10,000 concurrent users
- Sub-100ms API response times
- 99.9% uptime SLA
### Non-Goals
- Mobile app (separate repo)
- Legacy PHP admin panel (deprecated)
---
## Technology Stack
### Frontend
- **Framework**: Next.js 15.1 (App Router, NOT Pages Router)
- **Language**: TypeScript 5.4 (strict mode)
- **Styling**: Tailwind CSS 4.0
- **Components**: shadcn/ui + Radix UI
- **State Management**:
- Server State: TanStack Query v5
- Client State: Zustand 4.5
- Forms: React Hook Form + Zod
### Backend
- **Runtime**: Node.js 20.11 LTS
- **API**: tRPC 11 (type-safe)
- **Database**: PostgreSQL 16
- **ORM**: Drizzle ORM 0.35
- **Auth**: NextAuth.js v5
### DevOps
- **Monorepo**: Turborepo 2.0
- **Package Manager**: pnpm 9.0 (**CRITICAL**: Never use npm/yarn)
- **Testing**: Vitest 2.0, Playwright 1.45
- **CI/CD**: GitHub Actions
- **Hosting**: Vercel (production), Railway (staging)
---
## Project Structure
apps/
web/ # Next.js frontend
app/ # App Router pages
components/ # React components
lib/ # Client utilities
packages/
ui/ # Shared component library
database/ # Drizzle schema
types/ # Shared TypeScript types
config/ # ESLint, TS configs
**Key Directories**:
- `apps/web/app/`: Routes using App Router (NOT Pages Router)
- `apps/web/components/ui/`: shadcn/ui primitives
- `packages/database/`: Drizzle schema definitions
---
## Coding Standards
### Universal Principles
1. **Type Safety First**: TypeScript strict mode, no `any`
2. **Error Handling**: Never swallow errors silently
3. **Testing**: 80% coverage minimum
4. **Documentation**: JSDoc for all public APIs
### TypeScript Rules
#### Explicit Return Types
typescript
// ✅ CORRECT
export function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
// ❌ WRONG
export function calculateTotal(items: Item[]) {
return items.reduce((sum, item) => sum + item.price, 0);
}
#### Error Handling Pattern
typescript
// ✅ REQUIRED: Result type
type Result =
| { success: true; data: T }
| { success: false; error: string };
async function fetchUser(id: string): Promise> {
try {
const user = await db.query.users.findFirst({
where: eq(users.id, id)
});
if (!user) {
return { success: false, error: 'User not found' };
}
return { success: true, data: user };
} catch (error) {
logger.error('fetchUser failed', { id, error });
return { success: false, error: 'Database error' };
}
}
#### Avoid `any`
typescript
// ✅ Use unknown + type guards
function processData(data: unknown) {
if (typeof data === 'object' && data !== null && 'id' in data) {
return data.id; // Type-safe
}
throw new Error('Invalid data');
}
// ❌ Never use any
function processData(data: any) {
return data.id; // No type safety
}
### React Patterns
#### Server vs Client Components
tsx
// ✅ Server Component (default - no directive)
async function UserProfilePage({ params }: { params: { id: string } }) {
const user = await db.query.users.findFirst({
where: eq(users.id, params.id)
});
return ;
}
// ✅ Client Component (only when needed)
'use client';
import { useState } from 'react';
export function InteractiveCounter() {
const [count, setCount] = useState(0);
return setCount(count + 1)}>{count};
}
**Add `'use client'` only when**:
- Using hooks (useState, useEffect, useContext)
- Event handlers (onClick, onChange)
- Browser APIs (window, localStorage)
#### Component Size Limits
- Maximum 200 lines per component
- Extract sub-components if exceeded
- Use composition over props drilling
### Import Organization
typescript
// 1. External dependencies
import { useState, useEffect } from 'react';
import { z } from 'zod';
// 2. Internal packages
import { Button } from '@repo/ui';
import { User } from '@repo/types';
// 3. Application modules
import { trpc } from '@/lib/trpc/client';
import { cn } from '@/lib/utils';
// 4. Relative imports
import { UserCard } from './UserCard';
// 5. Styles
import './styles.css';
---
## Testing Standards
### Coverage Requirements
- **Unit Tests**: 80% minimum (business logic)
- **Integration Tests**: 70% minimum (API endpoints)
- **E2E Tests**: Critical user flows only
### Test Structure (AAA Pattern)
typescript
describe('UserService', () => {
it('should create user with valid data', async () => {
// ARRANGE
const userData = { email: 'test@example.com', name: 'Test' };
// ACT
const result = await service.createUser(userData);
// ASSERT
expect(result.success).toBe(true);
expect(result.data).toMatchObject(userData);
});
});
### Commands
bash
pnpm test # Run unit tests
pnpm test:watch # Watch mode
pnpm test:coverage # Coverage report
pnpm test:e2e # E2E tests
---
## API Patterns
### tRPC Procedure Template
typescript
export const userRouter = createTRPCRouter({
getById: publicProcedure
.input(z.object({ id: z.string().uuid() }))
.query(async ({ input, ctx }) => {
const user = await ctx.db.query.users.findFirst({
where: eq(users.id, input.id)
});
if (!user) {
throw new TRPCError({
code: 'NOT_FOUND',
message: 'User not found',
});
}
return user;
}),
});
### Response Format
All endpoints return:
typescript
{
success: boolean;
data: T | null;
error: string | null;
}
---
## Common Pitfalls
### Hot Reload with tRPC
**Symptom**: Router changes don't reflect
**Solution**: Restart dev server when adding/removing procedures
### Server Component Hydration
**Symptom**: "Text content did not match" errors
**Solution**: Ensure all async operations are awaited
### Environment Variables
**Symptom**: `process.env.NEXT_PUBLIC_VAR` undefined
**Solution**: All client vars MUST have `NEXT_PUBLIC_` prefix
bash
.env.local
NEXT_PUBLIC_API_URL=https://api.example.com # ✅ Client-accessible
DATABASE_URL=postgresql://... # ❌ Server-only
---
## Security Requirements
### Never Commit
- API keys, tokens, secrets
- Database credentials
- Private keys or certificates
### Input Validation
typescript
// ✅ ALWAYS validate with Zod
const UserSchema = z.object({
email: z.string().email(),
password: z.string().min(12),
});
const user = UserSchema.parse(untrustedData);
### SQL Injection Prevention
typescript
// ✅ Parameterized queries (Drizzle ORM)
const users = await db.query.users.findMany({
where: eq(users.email, email) // Safe
});
// ❌ String concatenation
const query = SELECT * FROM users WHERE email = '${email}'; // Vulnerable!
---
## Git Workflow
### Branch Naming
- `feat/feature-name` - New features
- `fix/bug-description` - Bug fixes
- `docs/what-changed` - Documentation
- `refactor/what-improved` - Code improvements
### Commit Format
Follow Conventional Commits:
feat(auth): add password reset flow
fix(api): handle null user in profile endpoint
docs(readme): update installation steps
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
### Pull Requests
- Require 1 approval
- All CI checks must pass
- Squash merge to main
---
## Deployment Checklist
Before deploying:
- [ ] All tests pass (`pnpm test`)
- [ ] TypeScript check passes (`pnpm type-check`)
- [ ] Linter passes (`pnpm lint --max-warnings 0`)
- [ ] Build succeeds (`pnpm build`)
- [ ] Environment variables configured
- [ ] Database migrations applied
- [ ] Secrets rotated if compromised
---
## Common Commands
### Development
bash
pnpm dev # Start dev server
pnpm build # Production build
pnpm lint # Run ESLint
pnpm type-check # TypeScript validation
pnpm format # Prettier formatting
### Database
bash
pnpm db:push # Push schema to database
pnpm db:studio # Open Drizzle Studio
pnpm db:generate # Generate migrations
pnpm db:migrate # Apply migrations
---
## Additional Resources
- **Architecture**: `docs/architecture.md`
- **API Reference**: `docs/api-reference.md`
- **Database Schema**: `packages/database/schema.ts`
- **Deployment**: `docs/deployment.md`
---
## Working with GitHub Copilot
### In VS Code
- Use **Copilot Chat** (Ctrl+I) for questions
- Use **Inline Suggestions** (Tab) for autocomplete
- Use **Slash Commands**: `/explain`, `/fix`, `/test`
### In JetBrains
- Open **Copilot Chat** (Alt+\)
- Use inline completions (Tab)
- Right-click for context actions
### On GitHub.com
- Use **Copilot Chat** in Pull Requests
- Ask for code review feedback
- Generate commit messages
---
## Maintenance
Update this file when:
- Tech stack changes (framework upgrades, new libraries)
- Coding patterns evolve (new best practices discovered)
- Team conventions change (new git workflow, testing strategy)
**Process**: Create PR, require 1 approval, update date.
---
*This file configures GitHub Copilot for all team members. Treat it as living documentation.*
Character Limits and Optimization
No Hard Limits: GitHub Copilot doesn't enforce character limits like Windsurf (6,000 chars) or enforce specific lengths.
Practical Limits:
- Recommended: 2,000-5,000 words (8-20 KB)
- Maximum effective: ~50 KB (beyond this, context dilution occurs)
- Minimum useful: 500 words (basic standards)
Token Usage:
- Instructions compete for context window space
- More concise = more room for actual code context
- Use bullet points and tables over prose
Path-Specific Instructions
File: .github/instructions/*.instructions.md
Purpose: Apply rules only to specific directories or file patterns.
Use Cases:
- Different standards for frontend vs backend
- Language-specific conventions
- Test-specific patterns
- Directory-level overrides
YAML Frontmatter Syntax
---
applyTo: "pattern"
---
# Instructions content
Supported Patterns:
-
File extensions:
**/*.ts,**/*.tsx -
Directories:
src/**,tests/** -
Specific files:
src/index.ts -
Multiple patterns:
**/*.{ts,tsx,js,jsx}
Creating Path-Specific Instructions
Step 1: Create Directory Structure
mkdir -p .github/instructions
# Create instruction files
touch .github/instructions/typescript.instructions.md
touch .github/instructions/tests.instructions.md
touch .github/instructions/frontend.instructions.md
Step 2: TypeScript-Specific Rules
---
applyTo: "**/*.{ts,tsx}"
---
# TypeScript Standards
## Type Safety
### Explicit Return Types
All functions must have explicit return types:
typescript
function calculate(x: number): number {
return x * 2;
}
### No Any Types
Use `unknown` instead:
typescript
// ✅ Correct
function process(data: unknown) {
if (typeof data === 'string') {
return data.toUpperCase();
}
}
// ❌ Wrong
function process(data: any) {
return data.toUpperCase();
}
## Async Patterns
Always use async/await:
typescript
// ✅ Correct
async function fetchData() {
const response = await fetch(url);
return response.json();
}
// ❌ Wrong
function fetchData() {
return fetch(url).then(r => r.json());
}
Step 3: Test-Specific Rules
---
applyTo: "**/*.{test,spec}.{ts,tsx,js,jsx}"
---
# Testing Standards
## Test Structure
Use AAA pattern (Arrange, Act, Assert):
typescript
describe('calculateTotal', () => {
it('should sum item prices', () => {
// Arrange
const items = [{ price: 10 }, { price: 20 }];
// Act
const total = calculateTotal(items);
// Assert
expect(total).toBe(30);
});
});
## Coverage Requirements
- Every public function needs tests
- Test happy path + error cases + edge cases
- Mock external dependencies
## Naming Convention
describe('[Component/Function Name]', () => {
it('should [expected behavior] when [condition]', () => {
// Test
});
});
Step 4: Frontend-Specific Rules
---
applyTo: "src/components/**/*.{tsx,jsx}"
---
# React Component Standards
## Component Structure
Use functional components with TypeScript:
tsx
interface Props {
user: User;
onEdit: (id: string) => void;
}
export function UserCard({ user, onEdit }: Props) {
return (
{user.name}
onEdit(user.id)}>Edit
);
}
## Size Limits
- Maximum 200 lines per component
- Extract sub-components if exceeded
## State Management
| Use Case | Solution |
|----------|----------|
| Server data | TanStack Query |
| Form state | React Hook Form |
| Local UI state | useState |
| Global state | Zustand |
Complete Example Structure
my-project/
├── .github/
│ ├── copilot-instructions.md # Repository-wide rules
│ └── instructions/
│ ├── typescript.instructions.md # applyTo: **/*.{ts,tsx}
│ ├── javascript.instructions.md # applyTo: **/*.{js,jsx}
│ ├── tests.instructions.md # applyTo: **/*.test.*
│ ├── frontend.instructions.md # applyTo: src/components/**
│ ├── backend.instructions.md # applyTo: src/api/**
│ └── database.instructions.md # applyTo: **/schema.ts
└── src/
Advanced Pattern Matching
Exclude Patterns (Negative Lookahead):
---
applyTo: "src/**/*.ts,!src/**/*.test.ts"
---
# Production TypeScript (excluding tests)
Multiple Directories:
---
applyTo: "{src,lib,packages}/**/*.tsx"
---
# React Components Across Multiple Directories
Specific File Names:
---
applyTo: "**/schema.ts"
---
# Database Schema Files
Organization-Level Instructions
Copilot Business/Enterprise Feature
Access: Admin Console → Copilot → Policies → Coding Guidelines
Character Limit: 609 characters (very restrictive)
Purpose:
- Company-wide security policies
- Compliance requirements (SOC2, HIPAA, GDPR)
- Universal coding standards
- Technology restrictions
What to Include (Given 609 Char Limit)
Option 1: Security-Focused
Security Requirements:
- No hardcoded secrets/API keys
- Validate all user inputs (use Zod)
- Parameterized SQL queries only
- HTTPS for all external calls
- Log security events to SIEM
Compliance:
- GDPR: Personal data must be encrypted at rest
- SOC2: Audit logging required for data access
Option 2: Standards-Focused
Company Standards:
- TypeScript for all new code
- Test coverage >80%
- Conventional Commits format
- Branch protection: require reviews
- No GPL-licensed dependencies
Contact: security@company.com for exceptions
Option 3: Technology Restrictions
Approved Technologies:
- Languages: TypeScript, Python, Go
- Databases: PostgreSQL, MongoDB
- Cloud: AWS only (no GCP/Azure)
- Auth: Okta integration required
Prohibited:
- Eval functions
- Deprecated libraries (see wiki)
Setting Organization Instructions
Step 1: Navigate to Admin Console
https://github.com/organizations/YOUR_ORG/settings/copilot/policies/coding_guidelines
Step 2: Enable Coding Guidelines
- Toggle "Enable coding guidelines" to ON
Step 3: Enter Guidelines (609 char limit)
Company-Wide Standards:
1. TypeScript strict mode
2. No secrets in code
3. Test coverage >80%
4. Conventional Commits
5. Zod for validation
6. PostgreSQL only
Security:
- Validate inputs
- Parameterized queries
- HTTPS only
- Audit logging
Contact: dev-standards@company.com
Step 4: Save and Deploy
- Changes propagate to all organization members within 15 minutes
Best Practices for 609 Character Limit
Do:
- ✅ Focus on security and compliance (non-negotiable items)
- ✅ Use abbreviations and bullet points
- ✅ Reference external documentation URL
- ✅ Prioritize the most critical 5-7 rules
Don't:
- ❌ Try to fit complete coding standards (use repository instructions)
- ❌ Include examples (no space)
- ❌ Duplicate what's in repository instructions
- ❌ Use prose (wastes characters)
Combining Organization + Repository Instructions
Organization Instructions (609 chars):
Security (REQUIRED):
- No secrets in code
- Input validation (Zod)
- SQL: parameterized only
- Audit logging
Standards:
- TypeScript strict mode
- >80% test coverage
- Conventional Commits
Tech Stack:
- PostgreSQL only
- AWS only
See: wiki.company.com/standards
Repository Instructions (in .github/copilot-instructions.md):
# Project-Specific Instructions
## Organization Standards
This project follows company-wide standards:
- See: wiki.company.com/standards
- Contact: dev-standards@company.com
## Project-Specific Rules
[Detailed project rules here...]
Personal Instructions
User-Level Global Configuration
Location: GitHub Account Settings → Copilot → Preferences
Purpose: Your personal coding preferences that apply across ALL projects.
Use Cases:
- Response style preferences
- Language preferences (e.g., British vs American English)
- Explanation verbosity
- Code comment style
- Personal shortcuts or patterns
Setting Personal Instructions
Step 1: Navigate to Settings
https://github.com/settings/copilot
Step 2: Scroll to "Preferences"
Step 3: Enter Your Instructions
Response Style:
- Be concise and direct
- Provide code examples with explanations
- Highlight breaking changes or gotchas
Code Preferences:
- Prefer modern ES2022+ syntax
- Use descriptive variable names
- Favor explicit over clever
Comments:
- JSDoc for all public functions
- Inline comments for complex logic
- No obvious comments
Testing:
- I prefer integration tests over unit tests
- Always show test examples
Step 4: Save
Personal vs Repository Instructions
Personal Instructions (highest priority):
- Response format and style
- Your preferred patterns (across all projects)
- Communication preferences
Repository Instructions (team standards):
- Project-specific tech stack
- Team coding conventions
- Architecture patterns
Example Interaction:
// Repository says: "Use Zustand for state"
// Personal says: "Always explain why a pattern was chosen"
// Copilot response:
// "I'm using Zustand for global state management (as specified in
// project standards) because it provides a simple, hook-based API
// with minimal boilerplate compared to Redux."
Effective Personal Instructions
# My Copilot Preferences
## Communication Style
- Concise explanations (no fluff)
- Code-first (show, don't tell)
- Warn about performance implications
## Code Style
- Modern syntax (async/await, optional chaining, nullish coalescing)
- Destructuring where readable
- Explicit types in TypeScript
## Testing Philosophy
- Integration tests preferred
- Mock external services
- Real database in test env (not mocks)
## Git
- Conventional Commits format
- Prefix: feat|fix|docs|refactor|test
## When I Say "Improve"
Check for:
1. Type safety
2. Error handling
3. Performance (O(n) complexity)
4. Security (input validation)
Workspace Settings Configuration
.vscode/settings.json
Purpose: Project-specific VS Code configuration (not strictly Copilot instructions, but affects behavior).
Location: .vscode/settings.json in project root
What to Configure:
- Model selection
- Context token budget
- Enable/disable features per language
Basic Configuration
{
// Copilot enable/disable per language
"github.copilot.enable": {
"*": true,
"plaintext": false,
"markdown": false
},
// Context tokens for chat
"github.copilot.chat.experimental.contextTokensBudget": 40000,
// Inline suggestions
"github.copilot.inlineSuggest.enable": true,
// Editor integration
"editor.inlineSuggest.enabled": true,
"editor.quickSuggestions": {
"comments": false,
"strings": false,
"other": true
}
}
Advanced Configuration
{
// Language-specific Copilot settings
"github.copilot.enable": {
"*": true,
"yaml": false,
"markdown": false,
"plaintext": false
},
// Chat context configuration
"github.copilot.chat.experimental.contextTokensBudget": 40000,
"github.copilot.chat.experimental.maxReferences": 30,
// Code generation preferences
"github.copilot.chat.experimental.codeGeneration.instructions": [
{
"text": "Always use TypeScript strict mode"
},
{
"text": "Prefer functional programming patterns"
}
],
// Inline suggestions
"github.copilot.inlineSuggest.enable": true,
"github.copilot.advanced": {
"inlineSuggestCount": 3,
"top_p": 1,
"temperature": 0.1,
"listCount": 10
},
// Editor behavior
"editor.inlineSuggest.enabled": true,
"editor.inlineSuggest.showToolbar": "onHover",
"editor.quickSuggestions": {
"other": true,
"comments": false,
"strings": false
},
// Language-specific overrides
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
}
}
Deprecated Settings (Pre-October 2024)
Don't Use (replaced by .github/copilot-instructions.md):
{
// ❌ DEPRECATED - Use .github/copilot-instructions.md instead
"github.copilot.chat.experimental.codeGeneration.instructions": [
{ "text": "Use TypeScript" },
{ "file": "docs/standards.md" }
]
}
Workspace vs User Settings
User Settings (~/.config/Code/User/settings.json):
- Personal Copilot preferences
- Applies to all projects
- Not version controlled
Workspace Settings (.vscode/settings.json):
- Project-specific configuration
- Version controlled (commit to git)
- Shared with team
Best Practice: Use workspace settings for team-wide configurations, user settings for personal preferences.
Instruction Hierarchy and Precedence
Priority Order (Highest to Lowest)
1. Personal Instructions (GitHub Settings)
↓ (overrides)
2. Repository Instructions (.github/copilot-instructions.md)
↓ (overrides)
3. Path-Specific Instructions (.github/instructions/*.instructions.md)
↓ (overrides)
4. Organization Instructions (Admin Console)
↓ (overrides)
5. Default Copilot Behavior
How Conflicts are Resolved
Scenario 1: Conflicting State Management
Personal Instructions: "I prefer Redux for state management"
Repository Instructions: "Use Zustand for global state"
Result: Copilot uses Zustand (repository wins for team standards) but may explain both options and why Zustand was chosen for this project.
Scenario 2: Comment Style
Personal Instructions: "Minimal comments, self-documenting code"
Repository Instructions: "JSDoc required for all public functions"
Result: Copilot adds JSDoc (repository wins) but keeps comments concise per your preference.
Scenario 3: Security Policy
Organization Instructions: "No console.log in production code"
Repository Instructions: [No mention of logging]
Personal Instructions: [No mention of logging]
Result: Copilot avoids console.log (organization policy enforced).
Testing Priority
Create a test file:
# Create test
mkdir -p src/test
cat > src/test/priority-test.ts << 'EOF'
// Test GitHub Copilot instruction priority
// Ask Copilot to generate a state management solution
EOF
Ask Copilot:
Generate a global state store for user authentication.
Observe:
- Which state management library does it choose?
- Does it follow personal or repository conventions?
- Are organization security policies applied?
VS Code Integration
Installation and Setup
Step 1: Install Extension
- Open VS Code
- Navigate to Extensions (Ctrl+Shift+X)
- Search "GitHub Copilot"
- Click "Install"
- Restart VS Code
Step 2: Sign In
- Click Copilot icon in bottom status bar
- Sign in with GitHub account
- Authorize VS Code
Step 3: Verify Instructions Loaded
- Open any file in your project
- Open Copilot Chat (Ctrl+I)
- Ask: "What coding standards apply to this project?"
- Copilot should reference
.github/copilot-instructions.md
Using Copilot with Instructions
Inline Suggestions:
// Start typing, Copilot suggests following project rules
async function fetchUser
// Copilot suggests: (id: string): Promise<Result<User>> {
Copilot Chat:
You: Generate error handling for API call
Copilot: I'll use the Result<T> pattern from project standards:
[Generates code following .github/copilot-instructions.md]
Slash Commands:
-
/explain- Explain code (uses context) -
/fix- Fix problems (follows standards) -
/test- Generate tests (follows test patterns) -
/doc- Add documentation (follows doc style)
Keyboard Shortcuts
| Action | Windows/Linux | macOS |
|---|---|---|
| Accept suggestion | Tab | Tab |
| Reject suggestion | Esc | Esc |
| Next suggestion | Alt+] | Option+] |
| Previous suggestion | Alt+[ | Option+[ |
| Open Chat | Ctrl+I | Cmd+I |
| Inline Chat | Ctrl+I (in editor) | Cmd+I |
Workspace Commands
Open Command Palette (Ctrl+Shift+P):
GitHub Copilot: Open Completions PanelGitHub Copilot: Toggle Copilot CompletionsGitHub Copilot: Send Feedback
Troubleshooting in VS Code
Instructions Not Loading:
# Check file exists
ls -la .github/copilot-instructions.md
# Verify format (valid Markdown)
cat .github/copilot-instructions.md
# Restart VS Code
# Cmd+Shift+P → "Developer: Reload Window"
Check Copilot Status:
- Click Copilot icon in status bar
- Should show "✓ Ready"
- If error, click to see details
JetBrains IDEs Integration
Supported IDEs
- IntelliJ IDEA (Ultimate, Community)
- PyCharm (Professional, Community)
- WebStorm
- PhpStorm
- Rider
- GoLand
- RubyMine
- CLion
- DataGrip
Installation
Step 1: Install Plugin
- Open IDE → Settings/Preferences
- Navigate to Plugins
- Search "GitHub Copilot"
- Click "Install"
- Restart IDE
Step 2: Sign In
- Settings → Tools → GitHub Copilot
- Click "Sign In"
- Authorize in browser
- Return to IDE
Step 3: Verify
- Open any file
- Start typing
- Copilot suggestions should appear
Using Instructions in JetBrains
Automatic Loading:
-
.github/copilot-instructions.mdloaded automatically - Path-specific instructions apply based on file location
- Organization guidelines enforced
Copilot Chat:
- Right-click in editor → "Copilot Chat"
- Or use shortcut: *Alt+* (Windows/Linux), *⌥* (Mac)
- Ask questions referencing project context
Inline Suggestions:
// Start typing
fun fetchUser
// Copilot suggests based on project Kotlin standards
Configuration in JetBrains
Settings → Tools → GitHub Copilot:
☑ Enable GitHub Copilot
☐ Show completions automatically
☑ Enable Copilot Chat
☑ Include project context in chat
Context:
☑ Repository instructions (.github/copilot-instructions.md)
☑ Organization guidelines
☑ Personal instructions
Languages:
☑ Kotlin
☑ Java
☑ Python
☐ XML
☐ Properties files
JetBrains-Specific Features
Intention Actions:
- Press Alt+Enter on any code
- Select "Ask Copilot"
- Choose action (Explain, Fix, Generate Test, etc.)
Code Generation Templates:
- Copilot respects JetBrains Live Templates
- Combines project instructions + IDE templates
Language-Specific Integration:
- Java: Understands Spring Boot, Maven, Gradle from instructions
- Kotlin: Applies Kotlin idioms + project standards
- Python: Respects virtual env, follows PEP 8 + custom rules
Troubleshooting in JetBrains
Instructions Not Working:
- Invalidate Caches: File → Invalidate Caches → Invalidate and Restart
- Verify plugin updated: Settings → Plugins → GitHub Copilot → Check for Updates
- Re-index project: File → Invalidate Caches → Clear File System Cache
Chat Context Issues:
- Settings → Tools → GitHub Copilot
- Ensure "Include project context" enabled
- Restart IDE
GitHub.com Web Integration
Pull Request Reviews
Using Copilot in PRs:
- Open any Pull Request
- Click "Copilot" icon in comment toolbar
- Ask for code review:
Review this code for:
- Standards compliance (check .github/copilot-instructions.md)
- Security issues
- Performance problems
Copilot will:
- Reference repository instructions
- Check organization policies
- Provide inline suggestions
Copilot Chat on GitHub.com
Access:
- Navigate to repository
- Click "Copilot Chat" button (top-right, next to search)
- Chat opens in sidebar
Example Usage:
You: What are the coding standards for this project?
Copilot: Based on .github/copilot-instructions.md, this project uses:
- TypeScript 5.4 (strict mode)
- Next.js 15 (App Router)
- Drizzle ORM for database
- Result<T> pattern for error handling
Commit Message Generation
In Commit UI:
- Stage changes
- Click Copilot icon in commit message box
- Copilot generates message following Conventional Commits (if specified in instructions)
Example:
feat(auth): add password reset flow
- Implements email-based password reset
- Uses NextAuth.js v5
- Follows Result<T> error pattern from project standards
Repository Q&A
Ask Copilot about your repo:
You: How is authentication implemented?
Copilot: [Scans codebase + reads .github/copilot-instructions.md]
Authentication uses NextAuth.js v5 as specified in the project standards...
Limitations on GitHub.com
- ❌ No inline code completions (web editor limitation)
- ✅ Full chat functionality
- ✅ Pull request reviews
- ✅ Commit message generation
- ✅ Repository Q&A
GitHub Desktop and CLI
GitHub Desktop
Current Status (as of November 2025):
- ❌ No support for
.github/copilot-instructions.md - ❌ No Copilot integration at all
- ⚠️ Organization guidelines MAY apply if Enterprise (unconfirmed)
Recommendation: Use VS Code, JetBrains, or GitHub.com for Copilot features.
GitHub CLI (gh command)
Copilot in CLI:
# Install GitHub CLI
brew install gh # macOS
# or download from: https://cli.github.com
# Install Copilot extension
gh extension install github/gh-copilot
# Use Copilot
gh copilot suggest "how to undo last commit"
gh copilot explain "git rebase -i HEAD~3"
Instructions Support:
- ✅ Reads
.github/copilot-instructions.md(if in git repo) - ✅ Applies organization guidelines
- ✅ Uses personal instructions
Example with Project Context:
# Navigate to project
cd my-project
# Ask project-specific question
gh copilot suggest "generate user authentication endpoint"
# Copilot response:
# [Uses context from .github/copilot-instructions.md]
# "Based on your project standards (tRPC + NextAuth.js):"
# [Generates code following project patterns]
Production-Ready Examples
Example 1: React + TypeScript SaaS
# GitHub Copilot Instructions - SaaS Platform
**Project**: Multi-tenant SaaS Platform
**Stack**: Next.js 15, TypeScript, PostgreSQL
**Last Updated**: 2025-11-29
---
## Core Standards
- TypeScript strict mode (no `any`)
- Server Components by default
- Result<T> for error handling
- 85% test coverage minimum
---
## Tech Stack
- Next.js 15 (App Router)
- TypeScript 5.4
- Tailwind CSS 4.0
- Drizzle ORM + PostgreSQL 16
- NextAuth.js v5
- tRPC 11
---
## Multi-Tenancy
### Critical Rule
Every database query MUST filter by `orgId`:
typescript
// ✅ CORRECT
const projects = await db.query.projects.findMany({
where: eq(projects.orgId, user.orgId)
});
// ❌ SECURITY RISK - Leaks data across organizations
const projects = await db.query.projects.findMany();
### Row-Level Security
All tables have RLS enabled. Double-check in code anyway.
---
## Authentication
- JWTs in HttpOnly cookies (NEVER localStorage)
- Access tokens: 15min expiry
- Refresh tokens: 7 days, rotated on use
---
## API Design
### tRPC Pattern
typescript
export const router = createTRPCRouter({
list: protectedProcedure
.query(async ({ ctx }) => {
return await ctx.db.query.items.findMany({
where: eq(items.orgId, ctx.user.orgId)
});
}),
});
### Response Format
typescript
{
success: boolean;
data: T | null;
error: string | null;
}
---
## Testing
- Unit: Vitest
- E2E: Playwright
- Mock Strategy: MSW for external APIs, real DB for data layer
---
## Security Checklist
- [ ] OrgId filter on all queries
- [ ] Input validation (Zod)
- [ ] No secrets in code
- [ ] Rate limiting on public endpoints
Example 2: Python FastAPI Microservice
# GitHub Copilot Instructions - API Service
**Project**: User Management Microservice
**Stack**: Python, FastAPI, PostgreSQL
---
## Standards
- Python 3.12+
- Type hints on ALL function arguments and return values
- PEP 8 style guide
- Async/await for all I/O operations
---
## Architecture
### Hexagonal Architecture
app/
api/ # Primary adapters (routers)
core/ # Core logic (config, exceptions)
domain/ # Domain models and services
infrastructure/ # Secondary adapters (DB, external APIs)
### Dependency Injection
Use FastAPI dependencies for all services:
python
@router.get("/users/{id}")
async def get_user(
id: str,
service: UserService = Depends(get_user_service)
):
return await service.get_user(id)
---
## Database Patterns
### SQLAlchemy + AsyncPG
python
✅ CORRECT - Async session
async with AsyncSession(engine) as session:
result = await session.execute(select(User))
return result.scalars().all()
❌ WRONG - Sync session
with Session(engine) as session:
# Will block event loop!
### Pydantic Models
- Use Pydantic V2 (`model_validate`, not `parse_obj`)
- Strict types where possible
- Config: `from_attributes = True` (was `orm_mode`)
---
## Testing
- Pytest with `pytest-asyncio`
- Coverage > 90%
- Fixtures in `conftest.py`
Best Practices
1. Keep Instructions Concise
Copilot has a limited context window (64k tokens). Verbose instructions push relevant code out of context.
Bad:
We believe that type safety is very important because it helps prevent runtime errors and makes the code easier to maintain. Therefore, we would like you to please try to use TypeScript's strict mode whenever possible and avoid using the 'any' type unless absolutely necessary.
Good:
- TypeScript strict mode REQUIRED
- NO `any` types (use `unknown` + type guards)
2. Use Examples
Examples are more effective than descriptions.
Bad:
Use the repository pattern for data access.
Good:
## Repository Pattern
typescript
class UserRepository {
constructor(private db: Database) {}
async findById(id: string): Promise {
return this.db.users.findFirst({ where: { id } });
}
}
3. Regular Updates
Update instructions when:
- Tech stack changes (e.g., upgrading Next.js 14 → 15)
- New patterns are adopted
- Common mistakes are identified
- Team conventions evolve
Schedule: Review monthly or quarterly.
4. Avoid Conflicts
Ensure your instruction layers don't contradict:
- Repo: "Use tabs"
- Personal: "Use spaces"
- Org: "Use EditorConfig"
Result: Confusion and inconsistent suggestions.
5. Test Your Rules
- Create a test file
- Ask Copilot to generate code
- Verify it follows your rules
- Adjust instructions if needed
Limitations and Workarounds
Context Window (64k Tokens)
Problem: Copilot can't "read" your entire codebase at once. It sees:
- Current file (cursor position)
- Open tabs (recent context)
copilot-instructions.md- Snippets from other files (via retrieval)
Impact: Complex refactoring across 50+ files is unreliable.
Workaround:
- Keep files small (<300 lines)
- Open relevant files in tabs before asking complex questions
- Use explicit imports so Copilot can trace dependencies
Multi-File Awareness
Problem: Copilot struggles to understand deep relationships between distant files.
Impact: "Refactor this API and update all consumers" often misses some usages.
Workaround:
- Do it in steps: "Refactor the API", then "Update consumer A", then "Update consumer B"
- Use "Copilot Workspace" (if available) for multi-file tasks
Instruction Adherence
Problem: Copilot sometimes ignores instructions, especially negative ones ("Don't do X").
Impact: Generated code might contain forbidden patterns.
Workaround:
- Use strong language: "REQUIRED", "MANDATORY", "NEVER"
- Provide correct examples (positive reinforcement works better than negative)
- Use
path-specific instructionsfor strict enforcement in critical areas
Migration from Other Tools
From Cursor (.cursorrules)
Process:
- Copy
.cursorrulescontent to.github/copilot-instructions.md - Remove Cursor-specific syntax (e.g.,
@filereferences if used in rules) - Convert YAML frontmatter (if using
.mdcformat) to standard Markdown headers - Simplify glob patterns (Copilot uses
.github/instructions/for path-specifics)
Example Conversion:
Cursor (.cursor/rules/typescript.mdc):
---
description: TypeScript rules
globs: ["**/*.ts"]
---
Use strict mode.
Copilot (.github/instructions/typescript.instructions.md):
---
applyTo: "**/*.ts"
---
Use strict mode.
From Windsurf (.windsurfrules)
Process:
- Extract rules from
.windsurfrulesor.windsurf/rules/*.md - Combine universal rules into
.github/copilot-instructions.md - Move file-specific rules to
.github/instructions/*.instructions.md - Remove Windsurf-specific activation modes (Copilot manages context automatically)
From Aider (CONVENTIONS.md)
Process:
- Copy
CONVENTIONS.mdcontent to.github/copilot-instructions.md - Copilot will automatically read it (no config file needed)
Troubleshooting
Instructions Not Loading
Symptom: Copilot ignores your rules.
Checks:
-
File location: Must be exactly
.github/copilot-instructions.md(case-sensitive) -
Root directory:
.github/must be in the project root (where.git/is) - VS Code reload: Restart VS Code to refresh context
- Format: Ensure valid Markdown syntax
- Token limit: Is the file too large? (>50KB)
"I don't see that file"
Symptom: Copilot Chat says it can't access the instructions file.
Explanation: Copilot treats instructions as system prompt context, not necessarily as a file in the file explorer.
Test: Instead of "read the instructions file", ask "what are the project coding standards?". If it answers correctly, the instructions are loaded.
Conflicting Behavior
Symptom: Copilot alternates between two styles.
Cause: Conflict between:
- Repository instructions vs Personal instructions
- Instructions vs Existing Code patterns (Copilot mimics existing code)
Fix:
- Align instructions
- Refactor existing code to match new standards (Copilot learns from context)
- Use stronger language ("ALWAYS use X, never Y")
Conclusion
GitHub Copilot's instruction system has matured into a powerful, tiered configuration engine. By leveraging Repository Instructions for team standards, Path-Specific Instructions for granular control, and Personal Instructions for developer preferences, teams can achieve high consistency and productivity.
Key Takeaway: Treat your .github/copilot-instructions.md as a first-class artifact of your codebase—version it, review it, and keep it updated as your project evolves.
Top comments (0)