GitHub Copilot Chat: Complete Beginner's Guide
Copilot Chat is where Copilot becomes useful for work that is not typing. Inline suggestions can only continue what you started; chat can explain, critique, plan, translate and argue with you.
Most people use it as a code generator and stop there, which leaves the larger half of its value unused. This lesson covers how its context actually works, then gives you a prompt library you can use immediately.
Key takeaways
- Chat’s most undervalued use is comprehension — explaining code you did not write.
- Chat lets you state constraints (“do not change the signature”) that inline suggestions have no way to express.
- Context is controlled explicitly with
#file,#selection,#projectand attachments. Guessing is optional. - Long, wandering sessions degrade. Start a new conversation per problem.
- Paste real error output, never a paraphrase of it. The traceback is context; your summary is not.
Where Copilot Chat runs
The IDE experience and the GitHub.com experience differ meaningfully. In your editor, chat sees your working code. On GitHub.com, it sees repositories, issues, pull requests and files you attach — better for questions about a project than about the file in front of you.
Opening chat
Inline chat deserves separate mention. It opens at your cursor, applies changes directly in the editor, and is the right tool for “change this function” rather than “explain this architecture”. Reaching for the full chat panel for a three-line edit is slower than inline chat.
How context works
This is the part that determines whether chat is useful or frustrating.
Chat receives the file you have open and, by default, whatever code you have selected. It does not automatically see your entire repository. Everything else you must provide.
Chat variables
Type # in the prompt box to include specific context. In VS Code the
documented variables are:
| Variable | Includes |
|---|---|
#file | The current file’s content |
#selection | The currently selected text |
#project | Project context |
#function | The current function or method |
#class | The current class |
#block | The current block of code |
#line | The current line |
#path | The file path |
#sym | The current symbol |
#comment | The current comment |
In Visual Studio, # references work slightly differently — you reference a
file by name (#MyFile.cs), specific lines (#MyFile.cs: 66-72), or the whole
solution (#solution).
Chat participants
Type @ to scope a question to a domain. In VS Code:
| Participant | Domain |
|---|---|
@github | GitHub-specific Copilot skills |
@terminal | The VS Code terminal shell and its contents |
@vscode | VS Code commands and features |
@azure | Azure services (public preview) |
Slash commands
Slash commands cover common operations without writing a full prompt. The documented sets differ by editor:
| Editor | Commands |
|---|---|
| VS Code | /clear, /explain, /fix, /fixTestFailure, /help, /new, /tests |
| Visual Studio | /doc, /explain, /fix, /help, /optimize, /tests |
| JetBrains | /chronicle, /compact, /explain, /fix, /help, /remote, /tests |
| Xcode | /doc, /explain, /fix, /simplify, /tests |
| GitHub.com | /clear, /delete, /new, /rename |
Lesson 11 covers commands in depth, with each entry labelled as official syntax, CLI syntax, a prompt or a workflow.
Asking better questions
The difference between a mediocre chat session and a useful one is almost entirely in how the request is framed. Four principles, in order of impact.
State the contract, not the goal. “Make this faster” invites guesswork. “Reduce this from O(n²) to O(n log n) without changing the return type” does not.
Say what must not change. Models default to helpfulness, which manifests as unrequested improvements. Naming the fixed points — signature, exception type, public behaviour — keeps a refactor a refactor.
Give it the real artefact. Paste the actual traceback, the actual failing assertion, the actual config. Your description of an error omits precisely the detail that would have identified the cause.
Ask for reasoning when you need to evaluate it. “Explain each decision” turns an opaque answer into one you can check.
Explaining code
The highest-value use of chat, and the most neglected.
Explain this function and identify edge cases.
For each edge case, state the specific input that triggers it and what the function does in that case. Do not describe the happy path.
I am new to this codebase. Explain what this module is responsible for, which functions have side effects, what a caller must know before using it, and anything here that would surprise an experienced developer reading it for the first time.
Break this regular expression down piece by piece, explain what each group matches, give three example strings it matches and three that look like they should match but do not.
Generating code
Generation works when you supply a specification. Compare a weak request with a strong one:
Create a Python API.
Create a FastAPI REST endpoint that accepts a server hostname and returns CPU, memory, and disk utilisation as JSON.
Use Pydantic for request validation. Return HTTP 400 for invalid hostnames. Include pytest tests covering successful and failed requests.
The second names the framework, the response shape, the validation library, the error behaviour and the test expectation — five decisions the first leaves to chance. Lesson 13 develops this properly.
Debugging
This traceback comes from the code in this file. Identify the root cause, not just the line that threw. Then propose the smallest change that fixes it without altering behaviour elsewhere.
[paste the complete traceback here]
This function works in testing but fails intermittently in production under load. List the possible causes in order of likelihood, and for each one tell me what I could log or measure to confirm or rule it out.
This test fails. Determine whether the bug is in the test or in the implementation before proposing a change — do not assume the test is correct.
[paste the test and the failure output]
Refactoring
Refactor this function to reduce duplication without changing externally observable behaviour.
Keep the public signature, the exception types, and the log messages exactly as they are. Explain what you extracted and why.
This function is too long to review comfortably. Split it into smaller functions along its natural seams. Each extracted function should have a name that describes what it does rather than when it is called. Do not change behaviour.
Testing
Write pytest tests for this function, including boundary conditions and expected failures.
Use pytest.mark.parametrize for the valid input table. Use pytest.raises for each documented exception. Do not test implementation details — only the documented contract.
Here is a function and its existing 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.
Documentation
Write a docstring for this function stating its parameters, return value, and every exception it can raise. Describe actual behaviour, not intended behaviour — if the code and its name disagree, say so.
Write the “Getting started” section of a README for this project, based only on what the code actually does. Include installation, minimal configuration, and one runnable example. Do not invent features that are not present.
Git
Write a conventional-commits message for this diff. The subject line must be under 72 characters and describe the change, not the files touched. Include a body only if the reason for the change is not obvious from the subject.
Explain what state this repository is in and what each of my options would do. I want to keep my local changes. Show the exact commands and tell me which are reversible.
[paste git status and git log --oneline -5 output]
Shell and terminal
@terminal Explain why the last command failed and what to run instead. Tell me what the fix changes before I run it.
Write a shell command that finds all files larger than 100 MB modified in the last 30 days, sorted by size descending.
Explain each part of the pipeline. Prefer readability over cleverness, and note any GNU-specific flags that would fail on macOS.
DevOps
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 to a specific version, and do not copy the build toolchain into the final image.
Review this Terraform configuration 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.
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 file or in the application.
[paste the relevant log section]
Chat on GitHub.com
The web experience is a different tool with the same name, and it is worth knowing what it is good at.
On GitHub.com you attach context with @ mentions rather than chat variables.
Typing @ offers discussions, extensions, files, issues, pull requests and
repositories. This makes it the right place for questions that span a project
rather than a file:
Summarise what this pull request changes, which parts carry the most risk, and what a reviewer should look at first. Point at specific files rather than describing the change in general terms.
Chat on GitHub.com also has access to a set of MCP skills for acting on the
repository. The documented skills are create_branch, create_or_update_file,
push_files, update_pull_request_branch, merge_pull_request, get_me and
search_users.
The GitHub.com slash commands are correspondingly different, and are about
managing conversations rather than acting on code: /clear, /delete, /new
and /rename.
Choosing a model
Chat lets you select which model handles a request, or leaves it to auto model selection.
The honest guidance runs against the discourse: for most everyday questions the default is fine, and context quality matters more than model choice. Where the model genuinely changes the outcome is on tasks requiring many constraints held at once — a refactor with subtle invariants, or a bug whose cause is several inferential steps from its symptom.
Two practical considerations:
- Model access depends on your plan. Copilot Free and Student reach models through auto selection only; Pro gets a selection; Pro+, Max, Business and Enterprise reach premium models. See the plans comparison.
- Models consume AI credits at different rates. Running a heavy reasoning model for mechanical work is a real cost, not a free upgrade.
A worked session
Prompts in isolation undersell how chat is actually used. A realistic session for “this endpoint is occasionally returning stale data” looks more like this:
1. Orient before proposing anything.
Explain how this endpoint retrieves and returns data. Identify every place a value could be cached, including anything implicit in the framework.
2. Narrow the hypothesis space. Now you know where caching happens, ask what would produce the specific symptom — not “fix it”.
Given those caching points, list the conditions under which this endpoint would return stale data. Order them by likelihood and tell me what I could log to distinguish between them.
3. Verify before changing anything. Add the logging, reproduce, and come back with real output — not your summary of it.
4. Then, and only then, ask for the change, with the constraint stated:
The logs confirm the second hypothesis. Propose the smallest change that fixes it. Do not alter the response schema or the function signature, and tell me what could break as a result.
Notice that three of the four turns are not asking for code. That ratio is roughly right for non-trivial work, and it is the main thing separating people who find chat transformative from people who find it a slightly better autocomplete.
Limitations
Chat inherits every limitation of the underlying model, plus a few of its own:
- It does not know your system. No production behaviour, no incident history, no institutional context.
- It is confidently wrong. There is no calibration signal separating a correct answer from a fabricated one.
- It cannot run anything. Chat does not execute your code or your tests. Agent mode can; chat cannot.
- Long sessions degrade. As the context window fills, earlier detail drops out. Answers start contradicting things established twenty messages ago.
- It cannot see closed files unless you attach them.
The session-length issue is worth taking seriously. A conversation that has wandered across four topics carries all four into every subsequent answer. Starting a new conversation per problem is not wasteful — it is how you stop the model reasoning from stale premises.
Security
Two further points:
Generated code is unreviewed code. Chat will produce string-built SQL, missing input validation, permissive CORS and outdated cryptographic practice — because those patterns are abundant in what these models learned from. Ask specifically about security when it matters:
Review this code 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.
Suggested dependencies deserve scrutiny. Chat may propose a package that is unmaintained, unnecessary, or simply not the one your team standardised on.
Prompt design in one page
If you remember nothing else:
| Do | Instead of |
|---|---|
| State inputs, outputs and error behaviour | “Write a function to handle users” |
| Name what must not change | “Refactor this” |
| Paste the actual error output | “It throws an error” |
| Ask one thing per message | Bundling four requests together |
| Ask it to explain its reasoning | Accepting an opaque answer |
| Start a new chat per problem | One session all day |
| Attach the relevant files | Hoping it infers them |
Best practices
- Use chat for comprehension first. It is the fastest way into unfamiliar code, and there is no review risk in an explanation.
- Review before applying. Chat output arrives looking finished. Apply, then read the diff.
- Run everything. Especially code that looks obviously correct.
- Prefer inline chat for small edits and the panel for discussion.
- Write repository custom instructions so you stop restating conventions. This is the single highest-return configuration available.
- Keep a personal prompt library. The prompts on this page are a starting point; the ones that work for your codebase are worth saving.
Frequently asked questions
Is Copilot Chat included on the free plan? Yes. Chat is available on every plan including Copilot Free. Chat skills in IDEs are excluded from Free but present on all other plans.
What is the difference between chat and inline chat? Inline chat opens at your cursor and applies changes directly in the editor, suited to focused edits. The chat panel is a conversation, suited to explanation, planning and discussion.
Why does chat give different answers to the same question? Model output is probabilistic. There is no phrasing that makes it deterministic.
Can chat see my whole repository? Not automatically. It sees the current file, your selection, and whatever you attach or reference with chat variables. Workspace indexing extends this in supported editors, but explicit context still beats inference.
Should I use chat or agent mode? Chat when you want to understand something or draft a change you will apply yourself. Agent mode when you want Copilot to make the changes across files and iterate.
Next steps
Continue to Code Completion Explained for the other half of the assistive layer, or step up to Agent Mode, where Copilot acts on the plans you have been discussing.
For more prompts, 50 Things You Can Do with GitHub Copilot covers fifty concrete jobs across testing, DevOps, security and review.
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.