By the end of this lab, you will be able to:
- Understand what prompt files are and how they differ from instructions
- Create reusable
.prompt.mdfiles for common tasks - Use variables like
${file},${selection}, and${input:name}in prompts - Configure prompt metadata (description, agent, model, tools)
- Build a library of prompt files for your team
- Run prompt files from Copilot Chat using
/commands
Prompt files are reusable, version-controlled prompt templates stored as .prompt.md files. While instructions tell Copilot how to behave, prompt files define what to do β they are task recipes you can trigger on demand.
| Feature | Instructions | Prompt Files |
|---|---|---|
| Purpose | Define rules and conventions | Define reusable tasks |
| When applied | Automatically, always | On demand, when invoked |
| Location | .github/copilot-instructions.md |
.github/prompts/*.prompt.md |
| Invoked via | Automatic | Type / in chat to see available prompts |
| Contains | Rules, standards, preferences | Task descriptions, variables, tool config |
.github/
βββ prompts/
βββ new-endpoint.prompt.md β reusable prompt for creating API endpoints
βββ write-tests.prompt.md β reusable prompt for generating tests
βββ code-review.prompt.md β reusable prompt for reviewing code
βββ add-feature.prompt.md β reusable prompt for adding features
When you type / in Copilot Chat, your prompt files appear as available commands alongside skills. Select one and Copilot executes the prompt template.
Every .prompt.md file has two parts:
- YAML frontmatter (optional) β metadata like description, agent, model, tools
- Body β the actual prompt content in Markdown
---
description: Create a new REST API endpoint
agent: agent
model: GPT-4.1
tools: ['codebase', 'terminal', 'editFiles']
---
Your prompt instructions here...Prerequisites: Lab 06 (Custom Instructions) completed β this lab builds on the Recipe API project and assumes the instructions file from Lab 06 is in place.
Make sure the Recipe API project is ready:
cd starter-code/recipe-api
npm installCreate the prompts directory (run from inside starter-code/recipe-api/):
mkdir -p .github/promptsNote: All
.prompt.mdfiles in this lab live understarter-code/recipe-api/.github/prompts/. Relative file-reference paths in prompts are resolved from the prompt file's location.
Create the file .github/prompts/new-endpoint.prompt.md:
---
description: Create a new REST API endpoint following project conventions
---
# New API Endpoint
Create a new REST API endpoint for the Recipe API.
## Requirements
- Create the route handler in `src/routes/`
- Add input validation for all parameters
- Include proper error handling with JSON error responses
- Use appropriate HTTP status codes
- Add JSDoc comments with @route, @method, and @param tags
- Follow existing code patterns in the project
## Endpoint Details
Create the endpoint as described by the user's request.
## Checklist
- [ ] Route handler created
- [ ] Input validation added
- [ ] Error handling implemented
- [ ] Route registered in server.js
- [ ] JSDoc comments added- Open Copilot Chat (Agent Mode recommended)
- Type
/to see available prompts β you should seenew-endpoint - Select it and add your specific request:
/new-endpoint
GET /api/recipes/search?q=chicken&category=dinner
Search recipes by title (partial, case-insensitive match) with optional
category filter. Return matching recipes sorted by title.
β Observe:
- Copilot follows the template structure
- Input validation is included automatically
- Error handling matches the template requirements
- The checklist items are all addressed
Use the same prompt file for a completely different endpoint:
/new-endpoint
POST /api/recipes/:id/ratings
Add a rating (1-5 stars) with an optional comment to a recipe.
Body: { "stars": 4, "comment": "Delicious!" }
β Observe:
- The same template produces consistent output for different endpoints
- Team members can create endpoints that all follow the same patterns
Prompt files support variables that reference context from your workspace.
| Variable | Description |
|---|---|
${file} |
Path of the active editor file (its content is added as chat context) |
${selection} |
The currently selected text in the editor |
${selectedText} |
Same as ${selection} |
${workspaceFolder} |
The absolute path to the root folder of the workspace |
${workspaceFolderBasename} |
The name (basename) of the workspace folder |
${input:variableName} |
Prompts the user for free-text input when the prompt runs |
${input:variableName:placeholder} |
Same as above, with placeholder text in the input box |
You can also reference other files using Markdown links: [filename](path/to/file.js)
Create .github/prompts/write-tests.prompt.md:
---
description: Generate comprehensive unit tests for a source file
agent: agent
---
# Write Tests
Generate comprehensive unit tests for the specified source file.
## Context
The source file to test: ${file}
## Test Requirements
- Use Vitest as the test framework
- Place tests in `tests/` directory mirroring the `src/` structure
- Name the test file with `.test.js` suffix
- Group tests with `describe` blocks by method/function name
- Use `it` (not `test`) for individual test cases
- Write descriptions as: "should [expected behavior] when [condition]"
## Coverage Requirements
For each exported function or method, include:
1. At least one happy path test
2. At least one error/edge case test
3. Boundary value tests where applicable
## Test Structure Template
```javascript
import { describe, it, expect, beforeEach, vi } from 'vitest';
describe('[ModuleName]', () => {
describe('[methodName]', () => {
it('should [expected] when [condition]', () => {
// Arrange
// Act
// Assert
});
});
});
```
## Additional Instructions
- Mock external dependencies
- Use `beforeEach` to reset state between tests
- Include both positive and negative test cases- Open
src/routes/recipes.jsin the editor (make it the active file) - In Copilot Chat, use the prompt:
/write-tests
β Observe:
- The
${file}variable is automatically populated with the active editor file - Tests are generated specifically for that file's exports
- All the template rules are followed
Open different files and run the same prompt:
- Open
src/models/recipe.jsβ run/write-tests - Open
src/data/store.jsβ run/write-tests
β Observe: Same consistent test patterns, different file content each time.
Create .github/prompts/explain.prompt.md:
---
description: Explain code at a specific level of detail
argument-hint: Describe what to explain
---
# Explain Code
Explain the following code: ${file}
Explain at the following level of detail: ${input:level}
Focus your explanation at this level. Be concise but thorough.β Try This:
- Open a file and run
/explain - When prompted, enter a detail level like "beginner", "senior developer", or "architecture overview"
- Observe how the
${input:level}variable captures your free-text input
The YAML frontmatter lets you configure which agent, model, and tools a prompt uses.
The agent field controls which agent runs the prompt:
| Value | Description |
|---|---|
agent |
Agent mode (can make changes, run commands) |
ask |
Ask mode (read-only, answers questions) |
plan |
Plan mode (creates an implementation plan) |
<custom-agent-name> |
A custom agent you defined (Lab 08) |
Create .github/prompts/code-review.prompt.md:
---
description: Perform a thorough code review
agent: ask
---
# Code Review
Perform a thorough code review of the currently selected code.
## Code to Review
${selection}
## Review Checklist
### 1. Correctness
- Does the code do what it's supposed to?
- Are there any logical errors?
- Are edge cases handled?
### 2. Security
- Is user input validated and sanitized?
- Are there SQL injection or XSS vulnerabilities?
- Is sensitive data handled properly?
### 3. Performance
- Are there any N+1 query issues?
- Is there unnecessary computation?
### 4. Readability
- Are names descriptive and consistent?
- Is the code self-documenting?
## Output Format
For each issue found, provide:
- **Severity**: π΄ Critical / π‘ Warning / π΅ Suggestion
- **Line(s)**: Where the issue is
- **Issue**: What's wrong
- **Fix**: How to fix it
End with a summary of the overall code quality.Note: This prompt uses
agent: askbecause code review is read-only β it shouldn't make changes.
The tools field limits which tools the prompt can use. Create .github/prompts/research.prompt.md:
---
description: Research a topic using codebase search and web fetch
tools: ['codebase', 'fetch', 'search']
---
# Research
Research the following topic in the context of our Recipe API project:
${input:topic}
## Steps
1. Search the codebase for related code
2. Look up relevant documentation online
3. Summarize findings with code examples
## Output
Provide a summary with:
- What exists in our codebase already
- Relevant external resources
- Recommended approach with code examplesYou can reference project files directly in prompts using Markdown links. These files are included as context.
Create .github/prompts/add-feature.prompt.md:
---
description: Build a complete feature following project architecture
agent: agent
---
# Add Feature
Build a complete feature for the Recipe API following our project architecture.
Reference these files for existing patterns:
- [Server setup](../../src/server.js)
- [Route patterns](../../src/routes/recipes.js)
- [Data model](../../src/models/recipe.js)
## Implementation Steps
### 1. Model (if needed)
- Create in `src/models/`
- Include all relevant properties with types
- Add validation methods
### 2. Service
- Create in `src/services/`
- Implement all business logic
- Keep it independent of Express (no req/res)
- Named export only
### 3. Route Handler
- Create in `src/routes/`
- Thin handlers that delegate to the service
- Proper HTTP status codes
- Input validation
### 4. Integration
- Register routes in `src/server.js`
- Update any existing files that need changes
### 5. Tests
- Create in `tests/`
- Cover happy paths and error cases
- Mock external dependencies
### 6. Documentation
- Add JSDoc to all exported functions
- Update README.md with new endpointsTest it:
/add-feature
Recipe collections β users can create named collections (like "Weeknight
Dinners" or "Holiday Baking") and add/remove recipes to/from them.
Note: The Recipe API uses an in-memory store (no real database). This task demonstrates how a migration prompt would look for a project that does use one β the prompt itself is the deliverable, not a working migration.
Create .github/prompts/db-migration.prompt.md:
---
description: Create a database migration with up and down functions
agent: agent
---
# Database Migration
Create a database migration for the Recipe API.
## Requirements
- Create a migration file in `src/migrations/` with timestamp prefix
- File name format: `YYYYMMDDHHMMSS-description.js`
- Include both `up()` and `down()` functions
- Use parameterized queries (no string interpolation for values)
- Add appropriate indexes for frequently queried columns
## Migration Template
```javascript
/**
* Migration: [description]
* Created: [timestamp]
*/
export async function up(db) {
// Apply changes
}
export async function down(db) {
// Reverse changes
}
```Create .github/prompts/document-api.prompt.md:
---
description: Generate API documentation for endpoints
agent: ask
argument-hint: Describe which endpoints to document
---
# Document API Endpoint
Generate API documentation for the specified endpoint(s).
## Source
${file}
## Documentation Format
### `[METHOD] [PATH]`
**Description:** Brief description of what the endpoint does.
**Parameters:**
| Name | In | Type | Required | Description |
|------|------|------|----------|-------------|
**Request Body** (if applicable):
```json
{
"example": "value"
}
```
**Responses:**
| Status | Description | Body |
|--------|-------------|------|
**Example Request:**
```bash
curl -X [METHOD] http://localhost:4000[PATH] \
-H "Content-Type: application/json"
```
**Example Response:**
```json
{
"example": "response"
}
```Test each prompt to see how they produce consistent, high-quality output:
/db-migration
Add a 'tags' column to the recipes table as a JSON array. Also create a
'recipe_tags' junction table for normalized tag queries.
/document-api
Document all endpoints in the active file.
Use prompts in sequence to build a complete feature:
-
First, build the feature:
/add-feature Recipe import from URL β given a URL to a recipe website, extract the recipe title, ingredients, and steps, and create a new recipe. -
Then, generate tests:
/write-tests(with the new service file open)
-
Then, document it:
/document-api -
Finally, review it:
/code-review(select the implementation code)
Create .github/prompts/debug-issue.prompt.md:
---
description: Debug and fix an issue in the codebase
agent: agent
tools: ['codebase', 'terminal', 'editFiles']
---
# Debug Issue
Help debug and fix an issue in the Recipe API.
## Context
${file}
## Debugging Steps
1. **Reproduce**: Identify the minimal reproduction steps
2. **Locate**: Find the relevant code causing the issue
3. **Analyze**: Determine the root cause
4. **Fix**: Implement the fix
5. **Verify**: Suggest how to verify the fix works
6. **Prevent**: Suggest a test to prevent regression
## Output Format
### Root Cause
Explain what's causing the issue.
### Fix
Show the code changes needed.
### Test
Provide a test that would catch this bug.
### Prevention
Suggest what could prevent similar issues in the future.In addition to typing / in chat, you can run prompts from:
- Command Palette:
Cmd+Shift+Pβ "Chat: Run Prompt" - Editor: Click the play button when viewing a
.prompt.mdfile
β Try This: Open one of your prompt files and look for the play button to run it directly.
If you set up MCP servers in Lab 05, you can list their tools alongside the built-in ones in tools:
---
description: Fetch and analyze a web resource
tools: ['codebase', 'fetch']
---
# Analyze Web Resource
Fetch ${input:url} and analyze its structure.Tool names match what you see in the tool picker (Configure Toolsβ¦ from the chat input). MCP server tools typically appear under their server name β pick the specific tools your prompt needs.
A small _README.md in your prompts directory makes the library discoverable for teammates. Ask Copilot Chat directly (no slash command β /add-feature is for app code, not docs):
Read every .prompt.md file under .github/prompts/ and write a _README.md
in that directory listing each prompt with a one-line description and
an example invocation.
Modify an existing prompt with additional context when running it:
/write-tests
Additional requirement: Also include integration tests that test the full
HTTP request/response cycle using supertest.
β Observe: You can extend prompts with additional context on the fly.
Create a prompt that combines multiple steps into one:
- Plan the feature
- Implement it (model, service, routes, tests)
- Document it
- Review it All from a single prompt invocation.
Modify your prompts to work across languages (JavaScript, Python, C#) by using ${file} to detect the language and adapt output accordingly.
Create a "meta-prompt" that generates new prompt files:
/add-feature
Create a prompt file for generating Express middleware with error handling,
logging, and request validation. Save it in .github/prompts/.
| Tip | Example |
|---|---|
| Be specific | Define exact output format, not vague goals |
| Include structure | Use headers, checklists, templates |
| Add constraints | Mention what NOT to do |
| Use variables | ${file}, ${selection}, ${input:name} for dynamic context |
| Include examples | Show expected output format |
| Set agent mode | Use agent: ask for read-only, agent: agent for changes |
| Field | Description |
|---|---|
description |
Brief description shown in the prompt picker |
agent |
Which agent to use: ask, agent, plan, or a custom agent name |
model |
AI model to use β match the name shown in your model picker (e.g., GPT-4.1, Claude Sonnet 4.5) |
tools |
List of tools available to the prompt |
argument-hint |
Hint text shown in the chat input when the prompt is selected |
| Strategy | Benefit |
|---|---|
| Name by task | Easy to find: write-tests, code-review |
| Keep focused | Each prompt does one thing well |
| Document usage | Add a README to the prompts directory |
| Version control | Check prompts into Git for team sharing |
| Iterate | Refine prompts based on output quality |
| Mistake | Fix |
|---|---|
| Too vague | Add specific requirements and output format |
| Too long | Focus on one task per prompt |
| No examples | Include at least one example of expected output |
| Wrong agent | Use ask for read-only, agent for making changes |
| No description | Always add description in frontmatter for the picker |
| Concept | Takeaway |
|---|---|
| Prompts are reusable | Write once, use for every similar task |
| Variables add flexibility | ${file}, ${selection}, ${input:name} make prompts dynamic |
| Metadata controls behavior | agent, model, tools configure how the prompt runs |
Invoked with / |
Type / in chat to see and run available prompts |
| Version-controlled | Check prompts into .github/prompts/ for team sharing |
| Composable | Chain prompts for complex workflows |
You have reusable task templates. Now let's explore custom agents that can orchestrate complex multi-step workflows with specialized personas.
π Continue to Lab 08 - Custom Agents