Customizing GitHub Copilot in VS Code

by Sloth255
GitHub CopilotVS CodeAIProductivityMCP

Customizing GitHub Copilot in VS Code

Introduction

While vibe coding with GitHub Copilot, you may often encounter inconveniences. For example, the following situations can occur:

  • Coding convention mismatches
// Code generated by Copilot
function getUserData(id) {  // ❌ No types despite TypeScript being required
  return fetch('/api/users/' + id)  // ❌ Template literals should be used
}

// Correct code following team conventions
async function getUserData(id: string): Promise<UserData> {
  return await fetch(`/api/users/${id}`)
}
  • Repeating the same explanations over and over
Developer: "Create a React component"
GitHub Copilot: "Generated a class component"
Developer: "No, use a functional component, with TypeScript, and type definitions for props..."

# For the next component too...
Developer: "Create another component..."
GitHub Copilot: "Here's a class component..."
Developer: "I said functional component!"
  • Lack of project-specific knowledge
Developer: "Help me implement user authentication"
Copilot: "I'll suggest a general implementation using JWT"
Developer: "We're using Auth0..."
Copilot: "Got it. Let me implement Auth0..."
Developer: "And we have an internal authentication flow..."

GitHub Copilot is an excellent coding assistant, but with default settings, it doesn't fully adapt to your team's development style or project-specific requirements.

In this article, I'll introduce GitHub Copilot customization features in VS Code, covering Custom Instructions, Prompt Files, Custom Agents, Agent Skills, and MCP Server integration, with practical sample code.

The examples provided are referenced from: https://code.visualstudio.com/docs/copilot/customization/overview


Overview of Customization

GitHub Copilot in VS Code provides six major customization methods:

Customization Method Primary Use Characteristics & Scope
Custom Instructions Define coding standards and development guidelines All chat requests or specific file types
Agent Skills Teach specialized workflows and capabilities Define reusable expertise (shareable across agents)
Prompt Files Reusable task-specific prompts On-demand execution
Custom Agents Role-specific assistants Applied when chat mode is selected
Language Models Task-optimized AI model selection Switch via model picker
MCP Servers Integration with external services & tools Available in agent mode

1. Custom Instructions - Unifying Coding Conventions

Basic Setup

Custom Instructions is a feature that defines Copilot's behavior policies for the entire project or specific file types.

Settings Applied to the Entire Workspace

.github/copilot-instructions.md

# Project-wide Coding Guidelines

## Code Style
- Use semantic HTML5 elements (header, main, section, article)
- Prioritize modern JavaScript features (const/let, arrow functions, template literals)
- Always include TypeScript type definitions

## Naming Conventions
- Component names, interfaces, type aliases: PascalCase
- Variables, functions, methods: camelCase
- Private class members: underscore prefix (_)
- Constants: ALL_CAPS

## Code Quality
- Use meaningful variable and function names
- Add comments for complex logic
- Implement error handling for user inputs and API calls
- Prefer async/await over callbacks

## Security
- Never hardcode sensitive information
- Always validate input values
- Use placeholders to prevent SQL injection

Language-specific and Framework-specific Settings

For specific file patterns, specify applyTo in the frontmatter.

.github/instructions/react.instructions.md

---
applyTo: "**/*.tsx"
---

# React Development Guidelines

- Prioritize functional components over class components
- Leverage custom hooks to separate state management logic
- Always define props with TypeScript interfaces
- Use Tailwind CSS utility classes for styling
- Memoize with React.memo when necessary

.github/instructions/backend.instructions.md

---
applyTo: "src/server/**/*.ts"
---

# Backend Development Guidelines

- Place controllers in `src/controllers/`
- Place service logic in `src/services/`
- Implement data access using the repository pattern
- Load environment variables from `.env`
- Centralize error handling with middleware
- Use Winston for logging

Enabling the Settings

  1. Enable Chat > Use Instruction Files in VS Code settings
  2. Or add to settings.json:
{
  "github.copilot.chat.codeGeneration.useInstructionFiles": true
}

Auto-generation Feature

VS Code can analyze your workspace and auto-generate appropriate instruction files:

  1. Click the gear icon in the chat view
  2. Select "Generate Chat Instructions"
  3. Review and edit the generated file

2. Prompt Files - Reusable Task Templates

Prompt Files allow you to template frequently executed development tasks and share them across the team.

Sample 1: React Component Generation

.github/prompts/create-react-component.prompt.md

---
agent: 'agent'
model: 'GPT-4o'
tools: ['search/codebase']
description: 'Generate a React component'
---

Generate a React component with the following requirements:

Component name: ${input:componentName:Enter component name}
Props: ${input:props:Enter props comma-separated (e.g., title, onClick, isDisabled)}

## Generation Rules
- Implement in TypeScript
- Use functional components
- Define props with an interface
- Style with Tailwind CSS
- Manage state with React Hooks as needed
- Document props with JSDoc comments

Sample 2: API Route Generation

.github/prompts/create-api-route.prompt.md

---
agent: 'agent'
description: 'Generate a RESTful API route'
---

Generate a CRUD API for the following entity:

Entity name: ${input:entity:Entity name}
Fields: ${input:fields:Specify fields comma-separated}

## Implementation Requirements
- Use Express.js
- Implement in TypeScript
- Place router in `src/routes/`
- Place controller in `src/controllers/`
- Use express-validator for validation
- Implement proper error handling
- Use standard JSON response format

Sample 3: Test Case Generation

.github/prompts/generate-tests.prompt.md

---
agent: 'agent'
tools: ['search/codebase']
description: 'Auto-generate unit tests'
---

Selected code: ${selection}

Generate comprehensive unit tests for the above code.

## Test Requirements
- Use Jest
- Maximize test coverage
- Cover both normal and error cases
- Consider edge cases
- Use mocks and stubs appropriately
- Write descriptive describe/it statements for each test case

Sample 4: Code Review

.github/prompts/code-review.prompt.md

---
agent: 'agent'
description: 'Conduct a code review'
---

Selected code: ${selection}

Conduct a code review from the following perspectives:

## Review Perspectives
1. **Security**: Presence of vulnerabilities
2. **Performance**: Optimization opportunities
3. **Code Quality**: Readability, maintainability
4. **Error Handling**: Proper exception handling
5. **Testability**: Ease of testing
6. **Coding Standards**: Compliance with project conventions

Provide improvement suggestions with specific code examples.

How to Use Prompt Files

  1. From Command Palette: Chat: Run Prompt → Select prompt
  2. In Chat Input: Execute with slash commands like /create-react-component
  3. From Editor: Open a .prompt.md file and click the play button in the title bar

3. Agent Skills - Portable AI Function Extensions

Agent Skills are an open standard that can be commonly used across VS Code, GitHub Copilot CLI, and Copilot coding agent.

Agent Skills Structure

.github/skills/
├── webapp-testing/
│   ├── SKILL.md
│   └── example-test.spec.ts
└── github-actions-debugging/
    ├── SKILL.md
    └── troubleshooting-guide.md

Sample 1: Playwright Test Generation

.github/skills/webapp-testing/SKILL.md

---
name: webapp-testing
description: Generate E2E tests using Playwright. Use this when you need to test user interactions.
---

# Web Application Testing with Playwright

This skill supports the generation of end-to-end (E2E) tests using Playwright.

## Test Generation Rules

1. **Selector Priority**: 
   - Prioritize `getByRole`
   - Next, `getByLabel`
   - As a last resort, `getByTestId`

2. **Test Structure**:
   - Each test should be independently executable
   - Implement proper setup/teardown
   - Write clear assertions

3. **Best Practices**:
   - Use Page Object Model pattern
   - Waits are executed implicitly
   - Take screenshots only on failure

## Template Example

Generate tests based on the following example-test.spec.ts.

```typescript
import { test, expect } from '@playwright/test';

test('user can log in successfully', async ({ page }) => {
  await page.goto('/login');
  
  await page.getByRole('textbox', { name: 'Email' }).fill('user@test.com');
  await page.getByRole('textbox', { name: 'Password' }).fill('password123');
  await page.getByRole('button', { name: 'Sign in' }).click();
  
  await expect(page).toHaveURL('/dashboard');
  await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();
});

`.github/skills/webapp-testing/example-test.spec.ts`

```typescript
import { test, expect } from '@playwright/test';

test('user can add item to cart', async ({ page }) => {
  await page.goto('/products');
  
  const product = page.getByRole('article').filter({ hasText: 'Product Name' });
  await product.getByRole('button', { name: 'Add to Cart' }).click();
  
  await expect(page.getByRole('status', { name: 'Cart' })).toContainText('1 item');
});

test('user can complete checkout', async ({ page }) => {
  await page.goto('/cart');
  
  await page.getByRole('button', { name: 'Checkout' }).click();
  await page.getByRole('textbox', { name: 'Card Number' }).fill('4242424242424242');
  await page.getByRole('button', { name: 'Place Order' }).click();
  
  await expect(page.getByRole('heading')).toContainText('Order Confirmed');
});

Sample 2: GitHub Actions Debugging

.github/skills/github-actions-debugging/SKILL.md

---
name: github-actions-failure-debugging
description: Debug GitHub Actions workflow failures. Use when CI fails.
---

# GitHub Actions Failure Debugging

This skill provides an efficient process for debugging GitHub Actions workflow failures.

## Debugging Process

When debugging GitHub Actions workflows that failed on a Pull Request, follow these steps:

1. **Check Workflow Execution Status**
   - Use the `list_workflow_runs` tool to check recent executions and statuses for the PR

2. **Get Log Summary**
   - Use the `summarize_job_log_failures` tool to get an AI summary of failed job logs
   - Understand issues without overwhelming the context window

3. **Identify Root Cause**
   - Classify the issue type from error messages:
     * Dependency issues
     * Test failures
     * Build errors
     * Permission errors
     * Timeouts

4. **Propose Solutions**
   - Provide specific fixes for identified problems
   - Suggest workflow file modifications as needed

## Common Issues and Solutions

### Dependency Issues
- Node.js version mismatch
- Package installation failure
→ Check `package-lock.json`, clear cache

### Test Failures
- Missing environment variables
- Test data issues
→ Verify environment variable settings, validate test seed data

### Permission Errors
- Insufficient GITHUB_TOKEN scope
- Incorrect secrets configuration
→ Check permissions and secrets in repository settings

Agent Skills Benefits

  • Portability: Common use across VS Code, CLI, and coding agent
  • Context Understanding: Copilot automatically loads relevant skills
  • Team Sharing: Share knowledge by including in repository
  • Open Standard: Compliant with agentskills.io

4. Custom Agents - Role-Specific Assistants

Custom Agents define chat modes specialized for specific roles or tasks.

Sample 1: Planning-Only Agent

.github/agents/planner.md

---
name: 'planner'
description: 'Agent specialized in pre-implementation planning'
tools:
  - 'search/codebase'
  - 'githubRepo'
toolsets:
  - 'read-only'
model: 'GPT-4o'
---

# Implementation Planning Agent

You are an agent specialized in creating implementation plans. You don't write code, only create implementation plans.

## Responsibilities

1. **Requirements Analysis**: Analyze user requirements in detail
2. **Impact Investigation**: Identify files and components that need changes
3. **Task Decomposition**: Break down implementation into small tasks
4. **Risk Identification**: Identify potential issues

## Plan Format

### 1. Overview
[Purpose of implementation and expected results]

### 2. Impact Scope
- List of files requiring changes
- Affected components

### 3. Implementation Steps
1. [Details of Step 1]
   - Required changes
   - Notes
2. [Details of Step 2]
   ...

### 4. Testing Strategy
- Unit test targets
- E2E test scenarios

### 5. Risks and Countermeasures
| Risk | Countermeasure |
|------|----------------|
| ...  | ...            |

After plan approval, hand off to the implementation agent.

Sample 2: Security Review Agent

.github/agents/security-reviewer.md

---
name: 'security-reviewer'
description: 'Agent that reviews code from a security perspective'
tools:
  - 'search/codebase'
model: 'Claude Sonnet 3.5'
---

# Security Review Agent

You are an agent that detects code vulnerabilities as a security expert.

## Review Items

### 1. Authentication & Authorization
- [ ] Proper authentication mechanism implementation
- [ ] No authorization check leaks
- [ ] Session management safety

### 2. Input Validation
- [ ] Sanitize all user inputs
- [ ] SQL injection countermeasures
- [ ] XSS countermeasures
- [ ] CSRF countermeasures

### 3. Data Protection
- [ ] No hardcoded sensitive information
- [ ] Proper use of encryption
- [ ] No sensitive information output to logs

### 4. Dependencies
- [ ] Use of packages with known vulnerabilities
- [ ] Recommend updating to latest versions

### 5. API Security
- [ ] Rate limiting implementation
- [ ] Proper CORS configuration
- [ ] Safe API key management

## Report Format

For each detected issue, report:
- **Severity**: Critical / High / Medium / Low
- **Description**: What is the problem
- **Impact**: Impact if exploited
- **Fix Method**: Specific code examples

Critical/High vulnerabilities require immediate fixes.

Sample 3: Frontend Development Agent

.github/agents/frontend-dev.md

---
name: 'frontend-dev'
description: 'Agent specialized in frontend development'
tools:
  - 'search/codebase'
  - 'terminal'
  - 'edit'
model: 'GPT-4o'
---

# Frontend Development Agent

You are an expert in frontend development using React/TypeScript/Tailwind CSS.

## Development Principles

### Component Design
- Prioritize reusability
- Follow single responsibility principle
- Keep props minimal
- Appropriate abstraction level

### State Management
- Manage local state with useState/useReducer
- Keep global state to minimum necessary
- Prevent unnecessary re-renders

### Styling
- Use Tailwind CSS utility classes
- Minimize custom CSS
- Implement responsive design mobile-first

### Performance
- Prevent unnecessary re-renders with React.memo
- Memoize callbacks with useCallback
- Cache heavy calculations with useMemo
- Optimize images (next/image, etc.)

## Implementation Flow

1. Clarify component responsibilities
2. Define props interface
3. Design state management
4. Implement JSX structure
5. Apply styling
6. Verify accessibility (ARIA attributes)
7. Implement responsive support

Always preview in browser after implementation to verify functionality.

How to Use Custom Agents

  1. Open agent selector in chat view
  2. Select custom agent
  3. Defined tools and instructions are applied

5. MCP (Model Context Protocol) - External Service Integration

MCP is an open standard for Copilot to integrate with external services like databases and APIs.

MCP Server Configuration

Workspace Configuration

.vscode/mcp.json

{
  "inputs": [
    {
      "type": "promptString",
      "id": "github-token",
      "description": "GitHub Personal Access Token",
      "password": true
    },
    {
      "type": "promptString",
      "id": "db-connection",
      "description": "Database Connection String",
      "password": true
    }
  ],
  "servers": {
    "github-server": {
      "type": "http",
      "url": "https://github-mcp.com",
      "headers": {
        "Authorization": "Bearer ${input:github-token}"
      }
    },
    "database-server": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "DATABASE_URL": "${input:db-connection}"
      }
    },
    "filesystem-server": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
    }
  }
}

User Configuration

Define globally used MCP servers in settings.json:

{
  "chat.mcp.servers": {
    "perplexity-search": {
      "type": "http",
      "url": "https://perplexity-mcp.com/api",
      "env": {
        "PERPLEXITY_API_KEY": "${env:PERPLEXITY_API_KEY}"
      }
    },
    "slack-integration": {
      "command": "docker",
      "args": ["run", "-i", "slack-mcp-server"],
      "env": {
        "SLACK_TOKEN": "${env:SLACK_BOT_TOKEN}"
      }
    }
  }
}

Implementation Example 1: Using GitHub MCP Server

# Prompt Example

@agent Get recent issues from GitHub repository contoso/my-app,
and list them in order of priority.

# Copilot's Actions
1. Call GitHub MCP Server's `list_issues` tool
2. Sort retrieved issues by priority
3. Respond in markdown format

Implementation Example 2: Using Database MCP Server

# Prompt Example

Retrieve all users from the database and
aggregate the count of active users.

# Copilot's Actions
1. Execute Database MCP Server's `query` tool
2. SQL: SELECT COUNT(*) FROM users WHERE is_active = true
3. Format and display results

Implementation Example 3: Creating a Custom MCP Server

Create a simple MCP server with Node.js:

// custom-mcp-server/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server(
  {
    name: "custom-api-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// Tool definition
server.setRequestHandler("tools/list", async () => {
  return {
    tools: [
      {
        name: "fetch_user_data",
        description: "Fetch user data",
        inputSchema: {
          type: "object",
          properties: {
            userId: { type: "string", description: "User ID" },
          },
          required: ["userId"],
        },
      },
    ],
  };
});

// Tool execution
server.setRequestHandler("tools/call", async (request) => {
  if (request.params.name === "fetch_user_data") {
    const userId = request.params.arguments?.userId;
    // API request implementation
    const response = await fetch(`https://api.example.com/users/${userId}`);
    const data = await response.json();
    
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
  throw new Error("Unknown tool");
});

// Start server
const transport = new StdioServerTransport();
await server.connect(transport);

package.json:

{
  "name": "custom-mcp-server",
  "type": "module",
  "dependencies": {
    "@modelcontextprotocol/sdk": "latest"
  },
  "bin": {
    "custom-mcp-server": "./index.js"
  }
}

MCP Server Management

  1. Server List: Command Palette → MCP: List Servers
  2. Tool Selection: Click tool icon in agent mode
  3. Auto-approval: Configure auto-approval for trusted tools

6. Practical Integration Example

Use Case: Microservice Development Project

Directory Structure

my-microservice/
├── .github/
│   ├── copilot-instructions.md          # Overall development standards
│   ├── instructions/
│   │   ├── backend.instructions.md     # Backend-specific
│   │   ├── frontend.instructions.md    # Frontend-specific
│   │   └── infra.instructions.md       # Infrastructure-specific
│   ├── agents/
│   │   ├── planner.md                   # Planning agent
│   │   ├── implementer.md              # Implementation agent
│   │   ├── reviewer.md                  # Review agent
│   │   └── deployer.md                  # Deployment agent
│   ├── skills/
│   │   ├── api-testing/
│   │   │   ├── SKILL.md
│   │   │   └── sample-api-test.ts
│   │   └── k8s-deployment/
│   │       ├── SKILL.md
│   │       └── deployment-template.yaml
│   └── prompts/
│       ├── create-service.prompt.md
│       ├── add-endpoint.prompt.md
│       └── generate-migration.prompt.md
└── .vscode/
    └── mcp.json                         # MCP configuration

Workflow Example

1. Planning New Feature

# Request to @planner agent
I want to add user authentication functionality.
Implement OAuth and JWT token-based authentication.

2. Implementation Delegation

After plan approval, hand off to implementation agent:

# Implement with @implementer agent
Based on the above plan, implement the authentication middleware.

3. Auto-generate Tests

# Use Prompt File
/generate-tests

4. Security Review

# Verify with @security-reviewer agent
Conduct a security review of the implemented authentication middleware.

5. Deployment Preparation

# Leverage MCP + K8s Skill
@agent Generate deployment configuration for the authentication service using kubernetes-skill.

7. Language Models - Task-Specific Model Selection

Model Selection Strategy

In VS Code, you can select the optimal AI model for each task. Here are examples (note that new models are released daily, so the information below may become outdated):

Model Recommended Use Characteristics
GPT-4o Complex implementation, architecture design High reasoning capability
Claude Sonnet 3.5 Code review, refactoring Wide context window
GPT-4o-mini Simple code generation, quick Q&A Fast and cost-effective

Switching Models

  1. Click the model picker next to the chat input
  2. Select the model suitable for the task
  3. The selected model is applied to the current session

Using Custom Models (BYOK: Bring Your Own Key)

settings.json:

{
  "github.copilot.chat.models": [
    {
      "id": "my-custom-model",
      "name": "Custom GPT-4",
      "endpoint": "https://api.openai.com/v1/chat/completions",
      "apiKey": "${env:OPENAI_API_KEY}",
      "model": "gpt-4-turbo-preview"
    },
    {
      "id": "local-llm",
      "name": "Local LLaMA",
      "endpoint": "http://localhost:8080/v1/chat/completions",
      "model": "llama-3-70b-instruct"
    }
  ]
}

8. Best Practices

1. Gradual Adoption

Week 1: Set up Custom Instructions
Week 2: Convert frequent tasks to Prompt Files
Week 3: Trial introduction of Custom Agents
Week 4: External integration with MCP servers

2. Team Sharing

  • Commit Custom Instructions and Prompt Files to repository
  • Place Agent Skills in .github/skills/
  • Manage project-specific MCP configuration in .vscode/mcp.json

3. Security

// Manage API keys with environment variables
{
  "chat.mcp.servers": {
    "secure-api": {
      "env": {
        "API_KEY": "${env:MY_API_KEY}"  // Don't hardcode
      }
    }
  }
}

4. Performance Optimization

  • Disable unnecessary tools to save context
  • Split large Prompt Files into smaller ones
  • Adjust MCP server timeout settings

5. Documentation

# team-wiki/copilot-usage.md

## Custom Agent Usage

- `@planner`: Pre-implementation planning
- `@implementer`: Code implementation
- `@reviewer`: Code review
- `@deployer`: Deployment work

## Prompt Files Quick Reference

- `/create-component`: Generate React component
- `/add-api-route`: Add API endpoint
- `/generate-tests`: Auto-generate test code

Summary

By leveraging GitHub Copilot's customization features, you can build an AI assistant tailored to your team's development style.

Also, the current feature selection policy would likely be:

What You Want to Do Feature to Use
Unify coding standards Custom Instructions
Automate repetitive tasks Prompt Files
Create specialized AI assistants Custom Agents
Share skills across AI tools Agent Skills
Integrate with external APIs and DBs MCP Servers
Use optimal models for different tasks Language Models

References