CMD Master
Back to Blog
Arnošt Havelka

GitHub Copilot Prompting Best Practices

Get better GitHub Copilot results with clear task descriptions, relevant repository context, constraints, and testable acceptance criteria.

GitHub Copilot Prompting Best Practices

GitHub Copilot produces more useful coding help when the task description explains the problem, scope, constraints, and proof of success. A short prompt can work for a local code completion. A repository change needs the same clarity as a well-written issue.

The product surface matters: GitHub’s repository custom instructions documentation describes repository-wide instructions, path-specific instruction files, agent instructions, and reusable prompt files—with support varying by feature and IDE. Use the tools available in your environment, but keep the underlying request explicit.

Give code completion a local contract

For a small function, the surrounding name, types, and tests are often enough. Add the behavior that is easy to get subtly wrong:

Implement a parser for the retry-after header.

Return milliseconds for either seconds or a valid HTTP date. Return null for a
missing, negative, or invalid value. Do not throw from a response-error path.
Add table-driven tests for seconds, a future date, a past date, and malformed
input.

The contract guides completion without requiring a long architecture briefing.

Describe test work as behavior

Avoid:

Write tests for the preferences hook.

Use:

Add tests for the preferences hook using the existing test conventions.

Verify that the initial loading state does not redirect, a successful read
exposes the saved preferences, an update writes the complete preference object
atomically, and a failed update keeps the previous visible value.

Use public behavior rather than internal function-call counts. Include the
regression that would fail with the reported bug.

The assistant now has a user-facing contract, including an important negative case.

Give refactoring prompts behavior-preservation rules

Code suggestions can make a tidy local abstraction while dropping a public detail. Put preservation in the request:

Extract the repeated status presentation from these two cards.

Preserve current props, visible labels, analytics event names, keyboard focus,
and mobile layout. Limit changes to this feature and its direct tests.

Before editing, list the repeated behavior and the differences that must remain
separate. Do not turn this into a shared design-system component unless the
existing primitive cannot represent the result.

If you cannot name the behavior to preserve, first ask Copilot to explain the current contract and call sites.

Debug with symptoms and evidence

Symptom: The search page shows stale results after a user changes filters.

Expected: The newest filter selection controls the displayed results.
Observed: A slower previous request can overwrite a newer response.

Relevant code: the filter UI, request hook, and result renderer. Recent change:
request retries were added.

First outline the request lifecycle and competing hypotheses. State what logs or
test timing would prove each one. Then propose the smallest fix and regression
coverage. Do not replace the data layer without evidence.

This prevents a generic “fix the race condition” answer from expanding into an unnecessary state-management migration.

Use repository instructions for stable context

Stable rules should live with the project, where supported:

  • how to run tests and formatting;
  • deployment constraints;
  • supported locales or platforms;
  • public APIs that must remain compatible;
  • paths where security or accessibility reviews matter.

GitHub’s documentation describes repository-level custom instructions and more targeted instruction files. Keep those instructions short, accurate, and scoped to durable conventions. Put the current ticket’s details—symptoms, outcome, and acceptance criteria—in the prompt itself.

Request documentation that is grounded in code

Update the deployment troubleshooting guide after the new environment check.

Verify every command and environment variable against the repository. Explain
the success signal, common failure signal, and safe next action. Keep secrets
out of examples. Add links to the existing operational runbook instead of
duplicating it.

The phrase “verify against the repository” matters. It tells Copilot that accurate documentation is a code-reading task, not a prose-generation task.

End every significant prompt with acceptance criteria

Use a finish line that someone else can review:

Done means:
- the reported user behavior changes as described;
- protected behavior stays unchanged;
- focused tests prove the new and old paths;
- the type check and relevant lint command pass;
- the diff contains no unrelated cleanup.

For the general prompt structure, read how to write better AI prompts. For task-specific patterns, continue with prompt engineering for developers, then avoid the failure modes in AI coding assistant mistakes and how to avoid them.

When a coding task includes scripts, command output, or a terminal reproduction, validate it rather than describing it from memory. Practice the command-line workflow in your browser before you turn it into a prompt or test.

References

These documentation links provide authoritative details for the commands used in this article.