50 Things You Can Do with GitHub Copilot
Most people use Copilot for a fraction of what it does, because the first thing it does — finishing a line of code — is so immediately visible that it becomes the whole mental model.
Fifty concrete jobs follow, organised by the work rather than by the feature. Each one states the task, gives a prompt you can use, explains why it is worth doing this way, and says where it falls short.
Key takeaways
- The highest-value uses are comprehension and review, not generation.
- Every entry names its limits, because a use case without them is marketing.
- Prompts here are specific on purpose — the specificity is what makes them work.
- Infrastructure and security uses need more scrutiny than application code, not less.
- Nothing here removes the need to run the code.
Writing code
Use case 1: Implement against a documented contract
Write the signature and docstring first, then let Copilot fill the body. The docstring is the specification.
Implement this function according to its docstring. Raise ValueError for every documented failure case rather than returning a sentinel value.
Use case 2: Fill in a repetitive data structure
Complete a lookup table, an enum, a mapping between representations, or a parametrised test table.
Complete this mapping for the remaining HTTP status codes in the 4xx range, following the format of the entries above.
Use case 3: Translate code between languages
Port a working function from one language to another, preserving behaviour.
Translate this Python function to Go. Preserve the exact error semantics: what raises in Python should return an error in Go, not panic.
Use case 4: Scaffold a module that matches its neighbours
Create a new module consistent with existing ones in the same directory.
Create a new service module following the same structure, error handling and logging conventions as the existing modules in this directory.
Understanding existing code
Use case 5: Explain a function you did not write
Get an explanation framed around assumptions and failure modes rather than the happy path.
Explain what this function does, what it assumes about its inputs, and which edge cases would make it behave incorrectly. Be specific about failure modes.
Use case 6: Map an unfamiliar module
Understand a module's responsibility and its relationship to the rest of the system.
Explain what this module is responsible for, which functions have side effects, what a caller must know before using it, and anything that would surprise a first-time reader.
Use case 7: Decode a regular expression
Break down a regex nobody wants to touch.
Break this regular expression down piece by piece. Give three strings it matches and three that look like they should match but do not.
Use case 8: Trace a value through a codebase
Work out where a value comes from and everywhere it is used.
Trace where this configuration value is set, every place it is read, and what happens if it is missing or empty.
Debugging
Use case 9: Diagnose from a real traceback
Identify the root cause of an exception, not just the line that threw.
This traceback comes from the code in this file. Identify the root cause rather than the throwing line, then propose the smallest fix that does not change behaviour elsewhere.
Use case 10: Reason about an intermittent failure
Generate hypotheses for a bug you cannot reliably reproduce.
This works in testing but fails intermittently under load. List possible causes in order of likelihood, and for each one tell me what I could log or measure to confirm or rule it out.
Use case 11: Fix a failing test correctly
Determine whether the bug is in the test or in the implementation.
This test fails. Determine whether the bug is in the test or the implementation before proposing a change. Do not assume the test is correct.
Use case 12: Add diagnostic logging
Instrument a code path so the next failure is legible.
Add logging to this function that would let me diagnose a failure from logs alone. Log inputs, the decision taken at each branch, and the outcome. Do not log secrets or personal data.
Refactoring
Use case 13: Reduce duplication safely
Extract shared logic without changing observable behaviour.
Refactor this to reduce duplication without changing externally observable behaviour. Keep the public signature, exception types and log messages exactly as they are.
Use case 14: Break up a long function
Split an overgrown function along its natural seams.
Split this function into smaller functions along its natural seams. Name each one for what it does rather than when it is called. Do not change behaviour.
Use case 15: Modernise outdated patterns
Update code to current language idioms.
Update this to modern Python 3.12 idioms. Do not change behaviour, and tell me anything where the modern form differs subtly from the original.
Unit testing
Use case 16: Generate a contract-focused test suite
Write tests covering documented behaviour, including failures.
Write pytest tests for this function covering boundary conditions and expected failures. Use parametrize for the valid input table and pytest.raises for each documented exception. Test the contract, not the implementation.
Use case 17: Find the gaps in existing tests
Identify behaviour your suite does not cover.
Here is a function and its test suite. Identify behaviour that is not covered, and for each gap give the specific input that would exercise it. Do not rewrite the existing tests.
Use case 18: Generate edge-case inputs
Produce the awkward inputs you would not think of.
List inputs that would break this function: empty values, boundary values, unicode, very large inputs, and anything type-adjacent that would pass a naive check.
Use case 19: Write test fixtures and fakes
Build the setup code a test needs.
Write a pytest fixture providing a fake implementation of this interface. It should be configurable to return success, a timeout, and a malformed response.
Integration testing
Use case 20: Draft an end-to-end test
Write a test exercising a full request path.
Write an integration test for this endpoint covering a successful request, a validation failure, and a downstream timeout. Use the existing test client setup in this repository.
Use case 21: Generate realistic test data
Produce fixture data matching a schema.
Generate twenty realistic test records matching this schema. Include boundary values and at least three that should fail validation.
Documentation
Use case 22: Write a contract-stating docstring
Document what a function actually does.
Write a docstring stating parameters, return value and every exception raised. Describe actual behaviour, not intended behaviour — if the code and its name disagree, say so.
Use case 23: Draft a README from the code
Produce project documentation grounded in what exists.
Write a Getting Started section for this project based only on what the code actually does. Include installation, minimal configuration and one runnable example. Do not invent features.
Use case 24: Explain a change for reviewers
Turn a diff into a description someone can review against.
Write a pull request description for this diff: what changed, why, what a reviewer should focus on, and what is deliberately out of scope.
Git
Use case 25: Write a commit message from a diff
Produce a message describing the change rather than the files.
Write a conventional-commits message for this diff. The subject must be under 72 characters and describe the change, not the files touched. Add a body only if the reason is not obvious.
Use case 26: Understand a Git situation
Work out what state a repository is in and what your options do.
Explain what state this repository is in and what each of my options would do. I want to keep my local changes. Show exact commands and tell me which are reversible.
Use case 27: Resolve a merge conflict
Understand what two branches each intended.
Explain what each side of this conflict was trying to do and what a correct resolution preserving both intentions would look like. Do not just pick one side.
GitHub
Use case 28: Summarise a pull request
Understand a large PR before reviewing it.
Summarise what this pull request changes, which parts carry the most risk, and what a reviewer should look at first. Point at specific files.
Use case 29: Triage an issue
Turn a vague bug report into something actionable.
Based on this issue and the code in this repository, identify the likely area of the codebase involved, what information is missing from the report, and what I should ask the reporter.
DevOps
Use case 30: Explain an unfamiliar configuration file
Understand what a config actually does before changing it.
Explain what this configuration does, which values are safe to change, and which would break something if changed. Flag anything that looks like it was set to work around a problem.
Use case 31: Write a shell pipeline you can read
Build a command without reaching for the manual.
Write a shell command that finds files over 100 MB modified in the last 30 days, sorted by size descending. Explain each part and note any GNU-specific flags that would fail on macOS.
Docker
Use case 32: Write a Dockerfile with justified decisions
Containerise an application with the reasoning attached.
Create a Dockerfile for this FastAPI application. Use a non-root runtime user and explain each security decision. Use a multi-stage build, pin the base image, and keep the build toolchain out of the final image.
Use case 33: Diagnose a failing container
Work out why an image will not build or a container will not start.
This Docker build fails at the layer shown. Explain the cause and the fix, and tell me whether it is a Dockerfile problem or an application problem.
Kubernetes
Use case 34: Explain a manifest before applying it
Understand what a manifest will do to a cluster.
Explain what this Kubernetes manifest creates, what it exposes, what permissions it grants, and anything that would be unsafe in a shared cluster.
Use case 35: Draft resource limits and probes
Add the production readiness bits people leave out.
Add resource requests and limits, plus liveness and readiness probes, to this deployment. Explain what each probe checks and what happens if it fails.
Infrastructure as code
Use case 36: Review Terraform for exposure
Find configuration that would create something publicly reachable or over-permissioned.
Review this Terraform for resources that would be publicly accessible, permissions broader than necessary, and anything that would be destroyed and recreated on the next apply. Quote the specific lines.
Use case 37: Explain a plan diff
Understand what an infrastructure change will actually do.
Explain what this Terraform plan will do, which changes are destructive, and which resources will be replaced rather than updated in place.
CI/CD
Use case 38: Write a CI workflow
Set up a build, test and lint pipeline.
Write a GitHub Actions workflow that runs on pull requests: install dependencies, run the linter, run the type checker, run pytest. Cache dependencies between runs, and fail fast on lint errors.
Use case 39: Debug a failing pipeline
Work out why CI fails when local passes.
This GitHub Actions workflow fails at the build step. Identify the cause from the log output and tell me whether the fix belongs in the workflow or in the application.
Security
Use case 40: Review a change for vulnerabilities
Check code for common security problems before merging.
Review this for injection risks, missing input validation, unsafe deserialisation and permissions broader than required. For each finding, give the specific input or condition that exploits it.
Use case 41: Audit dependencies in a diff
Check what a change is pulling in.
List every dependency this change adds or updates. For each one, tell me what it is for and whether the same result could be achieved with the standard library.
Use case 42: Find where secrets could leak
Check that credentials are not being exposed.
Identify anywhere in this code where a credential, token or personal data could end up in a log, an error message, an exception trace or a response body.
SQL and data
Use case 43: Write a query with the schema in context
Produce SQL against a real schema.
Write a query returning the top ten customers by total order value in the last quarter, using the schema in this file. Use parameters rather than string interpolation.
Use case 44: Explain a query you inherited
Understand what a complex query does.
Explain what this query returns, what each join does to the row count, and which parts would be slow on a large table.
Use case 45: Draft a data migration
Write a migration with a rollback path.
Write a migration adding this column with a default, backfilling existing rows in batches, and provide the rollback. Explain what happens if it fails partway through.
Code review
Use case 46: Review your own work first
Clear the obvious findings before requesting human review.
Review this diff as a reviewer would. Identify correctness problems, missing error handling, and anything a reviewer would ask me to change. Ignore style the formatter handles.
Use case 47: Check for silently widened behaviour
Catch changes that make things pass without making them correct.
In this diff, identify anywhere behaviour was widened rather than fixed: broadened exception handling, loosened types, removed validation, or a default where a value was previously required.
AI agents
Use case 48: Plan before implementing
Get an implementation plan you can correct cheaply.
Create an implementation plan for adding rate limiting to the public API endpoints. List the files you would change and why, before writing any code.
Use case 49: Delegate a well-specified task
Hand a complete, self-contained task to the cloud agent and do something else.
Add pagination to GET /api/orders. Accept page and per_page with documented defaults and maximums, return 400 for out-of-range values using the existing error shape, follow the pattern in GET /api/customers, and add tests for defaults, an explicit page, the maximum, and an invalid value.
Use case 50: Set the standing rules for agents
Write repository custom instructions so every agent session inherits your conventions.
Draft a repository custom instructions file for this project covering the language version, test command, error-handling convention, directory layout, and a rule that existing tests must never be modified to make a change pass.
What runs through all fifty
Three patterns repeat across the list, and they are worth extracting.
Specificity does the work. Almost every prompt above names inputs, outputs, constraints or a definition of done. That is not stylistic — it is the difference between a usable result and a plausible one. The prompts that look longest are longest because they leave less to chance.
Constraints matter as much as goals. “Do not change the signature”, “do not modify the tests”, “do not invent features”, “quote the specific lines”. Models default to helpfulness, which shows up as unrequested changes. Naming what is fixed is how you get a change rather than a rewrite.
Comprehension outperforms generation. The entries with the best value-to-risk ratio on this list are the ones asking Copilot to explain something. There is no review burden on an explanation, and understanding code better makes every subsequent decision better.
Where to go next
- New to Copilot? How to Get Started builds one of these end to end.
- Want better prompts? Best Practices for Beginners explains why the specific ones above work.
- Want the syntax? 50 Commands, Actions and Workflows covers real slash commands and CLI syntax.
- Ready to delegate? Agent Mode and Cloud Agent vs Agent Mode.
Sources
Every version-sensitive claim on this page was checked against first-party documentation. Only sources actually used are listed.
Your progress
Saved in this browser only. No account, no server, and nothing leaves your device. Clearing site data resets it.
Was this lesson helpful?
Your answer is stored in this browser and is not sent anywhere.