GitHub Copilot Playbook

Developer Workflow

The Copilot Playbook

A step-by-step, hands-on guide to getting real value out of GitHub Copilot — from inline suggestions to multi-file agent tasks — with worked examples at every step.

Inline suggestions Comments & docstrings Copilot Chat Scope references Agents Review checklist
01

Work the inline suggestion

This is Copilot’s default mode in VS Code, Visual Studio, JetBrains, and Xcode: a gray, ghosted completion that appears as you type. Most people only ever use this mode — knowing the individual steps well is what separates “autocomplete” from “a tool that writes decent first drafts.”

1

Start from a signature or a comment

Type a function name and parameters, or a one-line comment describing what you want, and pause. Copilot reads everything above the cursor to predict what comes next.

Example — starting from a signature

def calculate_average(numbers):

Example — starting from a comment instead

# Return the average of a list of numbers, handling an empty list safely
def calculate_average(numbers):
2

Let it complete, then read before you accept

Copilot fills in a suggestion below the cursor. Read the whole block, not just the first line — the interesting bugs (an unhandled empty list, a wrong operator) usually show up two or three lines in.

def calculate_average(numbers):
    if not numbers:
        return 0
    return sum(numbers) / len(numbers)
3

Accept, reject, or take it in pieces

ActionTypical shortcutWhen to use it
Accept the whole suggestionTabIt matches what you’d have written
Reject itEscWrong approach entirely
Accept one wordCtrl + →The shape is right, a name isn’t
Accept one lineIDE-specificYou want the first line, not the rest

Shortcuts vary by IDE and are rebindable — check your editor’s Copilot keybindings if these don’t match.

4

If it’s wrong, don’t just retype it — cycle

Use your IDE’s “next suggestion” shortcut to see an alternative completion before you give up and write it by hand. A second or third pass often fixes the exact issue you noticed on the first.

Good fit Small completions, boilerplate, repetitive patterns, and finishing a thought you’ve already started. If you’re asking for something with real structure — a whole endpoint, a migration, a refactor — skip ahead to Copilot Chat instead of fighting the inline suggestion.
02

Compare with the suggestions pane

Copilot often has more than one plausible completion in mind. The multiple-suggestions pane lets you see them side by side instead of committing to whichever one happened to render first.

1

Open the panel

With a suggestion showing, use your IDE’s “show suggestions” shortcut (commonly Ctrl+Enter / Cmd+Enter) to open a panel of alternatives instead of a single inline ghost.

2

Judge each one on the same criteria

For a request like “slugify this title,” Copilot might offer three different shapes. Don’t default to the first — read each one against correctness, simplicity, performance, security, and whether it matches the conventions already in the file.

Three candidates for the same comment

// Convert the title to lowercase, replace spaces with hyphens,
// remove punctuation, and limit the result to 80 characters
function createSlug(title) {
Candidate A — fragile
return title.toLowerCase()
  .replace(/ /g, '-');

Doesn’t strip punctuation and ignores the 80-character limit entirely.

Candidate B — close, but unbounded
return title.toLowerCase()
  .replace(/[^a-z0-9]+/g, '-')
  .replace(/(^-|-$)/g, '');

Handles punctuation correctly, but a long title still isn’t capped at 80 characters.

Candidate C — matches the spec
return title.toLowerCase()
  .replace(/[^a-z0-9]+/g, '-')
  .replace(/(^-|-$)/g, '')
  .slice(0, 80);

Satisfies every requirement in the comment, including the length limit.

3

Insert the one that fits — not the fastest one

Once you’ve picked, insert only that candidate. If none of them are right, that’s your cue to add more context rather than keep cycling — which is exactly what the next section covers.

03

Feed it context before you ask again

Copilot predicts from whatever is visible: comments, open files, function names, existing patterns. If the suggestions keep missing, the fix usually isn’t a better prompt trick — it’s writing down the requirements you were holding in your head.

1

Upgrade a vague comment to a specific one

Vague
// process the data
Specific
// Parse the CSV input, skip the header row, ignore blank
// lines, convert column 3 to an integer, and return
// invalid rows separately from valid ones
2

Use a block comment for anything with real logic

State inputs, outputs, constraints, and edge cases up front — treat it like a mini spec, not a caption.

"""
Implement binary search on a sorted list.

Requirements:
- Return the index of target when found.
- Return -1 when target is absent.
- Use O(log n) time.
- Do not modify the input list.
"""
def binary_search(items, target):
3

Write the docstring before the body

For functions, classes, and small APIs, a docstring gives Copilot (and the next person reading the code) the contract before any implementation exists.

def get_active_users(users, minimum_age=18):
    """
    Return users who are active and at least minimum_age years old.

    Args:
        users: A list of dictionaries containing `active` and `age`.
        minimum_age: The minimum permitted age.

    Returns:
        A new list containing matching users.

    Raises:
        ValueError: If minimum_age is negative.
    """

A docstring this specific is usually enough for Copilot to generate a correct body, and it doubles as documentation you’d have had to write anyway.

4

Show it an example input and output

For parsing or transformation functions, a worked example above the signature often outperforms a paragraph of description.

// Input: "alice@example.com, Alice"
// Output: { email: "alice@example.com", name: "Alice" }
// Throw an error when the email is missing.
function parseContact(value: string) {
5

Clean up what’s around the cursor

Keep related functions close together, use descriptive names, close files that aren’t relevant to the current task, and open the ones that are. Copilot treats your open tabs as context — a stray unrelated file can pull suggestions in the wrong direction.

Reminder Better context produces better first drafts, not guaranteed-correct ones. Every example on this page still needs the review pass in the last section.
04

Switch to Copilot Chat for anything bigger

Inline suggestions are for finishing a line. Chat is for generating a feature, debugging a real failure, or getting an explanation — and it rewards the same discipline as good comments: be specific, and iterate.

1

Write the first prompt as a spec, not a wish

Less effective
Build an authentication system.
More effective
Create an Express.js authentication endpoint using
TypeScript. Use bcrypt for password hashing and JWT
for access tokens. Validate the email and password
with Zod. Return HTTP 400 for invalid input and HTTP
401 for invalid credentials. Do not include passwords
in responses.
2

Iterate turn by turn instead of re-prompting from scratch

Keep building on the same conversation:

Add refresh-token support.

Now write unit tests for successful login, invalid
input, and incorrect passwords.

Refactor this to separate validation, authentication,
and token creation.
3

Debug with the error, not just the symptom

Give Copilot the full error message, the stack trace, the relevant function, and what you expected to happen. That’s the difference between a guess and a diagnosis.

This function throws `TypeError: Cannot read properties
of undefined`. Explain the likely cause, identify the
line responsible, and propose a fix. Also explain how
to prevent the problem in the future.

For a harder case, ask it to trace a single value through the function:

Trace the value of `userId` through this function and
explain where it can become undefined.
4

Ask for explanations when you’re the one who needs context

Explain this function line by line.
What assumptions does this code make?
Summarize this file for a developer who is new to the project.
Explain the time and space complexity.
What security risks should I consider here?
5

Generate the tests and docs you’d otherwise skip

Generate unit tests for this function, including normal
cases, boundary cases, and invalid input.

Create a JSDoc comment for this function.

Suggest integration tests for this API endpoint.
05

Scope the conversation to the right code

A precise question about the right file beats a general question about the whole codebase. Scope references and slash commands are how you point Copilot at exactly what matters.

1

Name the file, symbol, or selection explicitly

Explain the error in `src/auth/login.ts` and compare it
with the validation logic in `src/auth/schema.ts`.

In an IDE, select the relevant block before opening chat, or use the editor’s file/symbol picker — don’t rely on Copilot guessing which of twenty open tabs you mean.

2

Reach for a slash command when the task is common

CommandWhat it does
/explainExplains the selected code
/fixSuggests a fix for the selection
/testsGenerates tests for the selection
/helpShows available commands

Exact commands vary by IDE and platform version.

3

Attach constraints to the command — don’t send it bare

Bare
/fix This function fails when the input list is empty.
With constraints
/fix Preserve the public API, avoid adding
dependencies, and include a regression test.
06

Hand off multi-file work to an agent

When a task spans several files — a feature, a refactor, a bug fix plus its regression test — a single chat answer isn’t the right shape. Agent mode explores the repo, makes the changes, and can run validation, but it needs a ticket-quality prompt to do that well.

1

Structure the request like a small ticket

State the goal, the files or area involved, any constraints, the expected behavior, and what tests or validation are required — in that order.

Implement pagination for the users API.

Requirements:
- Update the controller and service layers.
- Accept `page` and `limit` query parameters.
- Use a default limit of 20.
- Reject limits greater than 100.
- Preserve backward compatibility.
- Add unit and integration tests.
- Run the existing test suite and summarize the results.
2

Combine everything for a real bug: diagnosis, fix, test, and a hard boundary

In `src/orders/checkout.ts`, explain why checkout can
create duplicate orders.

Use the related tests in `tests/orders/checkout.test.ts`
and the database code in `src/orders/repository.ts`.

Then:
1. Identify the race condition.
2. Propose the smallest safe fix.
3. Add a regression test.
4. Explain how the fix affects transaction behavior.
5. Do not change the public API.

Compare that with what an agent can actually do with three words:

Too little to act on
Fix checkout.
A ticket the agent can execute and be checked against
(the five-step prompt above)
3

Reach for agent mode specifically for

  • Implementing a feature across multiple files
  • Refactoring related modules together
  • Fixing a bug and adding its regression test in one pass
  • Updating documentation and examples alongside a code change
  • Reviewing a pull request
  • Running tests and analyzing the failures
07

Review before you merge — every time

Nothing above changes this: Copilot can misread requirements, miss edge cases, or produce an insecure pattern that looks completely normal at a glance. Treat every suggestion, chat answer, and agent diff as a draft from a fast collaborator, not a finished change.

  • Run the tests — including the ones Copilot just wrote for you.
  • Run the linter and formatter — don’t let style drift in with the logic.
  • Check new dependencies — was one actually necessary?
  • Read the authentication and authorization paths closely — this is where a plausible-looking suggestion is most expensive to get wrong.
  • Look for injection risk — string-built queries, unsanitized input, unescaped output.
  • Sanity-check performance and maintainability — a suggestion can be correct and still be an O(n²) trap.