How to Get Started with GitHub Copilot
Most “getting started with Copilot” guides stop at installation, which is the part that was never difficult. This one goes further: by the end you will have built a small Python service with Copilot’s help, asked chat to review it, and run a test suite that actually passes.
That last step matters. Installing Copilot teaches you nothing about whether to trust it. Running its output does.
Key takeaways
- Copilot Free needs only a GitHub account, so you can complete this tutorial at no cost.
- Setup is minutes; the skill is in what you do afterwards.
- Write the function signature and docstring first — that context does more for suggestion quality than any prompt.
- Chat is most valuable for reviewing and explaining, not only for generating.
- Always run the code. This tutorial ends with a passing test suite for exactly that reason.
Step 1 — Prerequisites
Before starting, confirm you have:
- A GitHub account. Free is fine.
- Python 3.10 or later. Check with
python3 --version. - A code editor. VS Code, Visual Studio, a JetBrains IDE, Eclipse or Xcode all support Copilot.
That is genuinely all. There is no local model to download and nothing to configure at the system level.
Step 2 — Get a GitHub account
If you already have one, skip ahead.
Otherwise, sign up at github.com. Use an email address you will keep — your Copilot subscription, if you buy one later, attaches to this account.
Step 3 — Get Copilot access
For this tutorial, Copilot Free is sufficient.
Step 4 — Choose an IDE
Copilot’s features are not distributed evenly across editors. VS Code gets features first and has the broadest support; Visual Studio is close behind; JetBrains, Eclipse and Xcode support the core features with some in public preview; Neovim supports completion only.
If you have a strong preference, use it. If you do not, use VS Code for this tutorial — the instructions below assume it.
How to Install GitHub Copilot covers every environment in detail, including a full feature matrix.
Step 5 — Install Copilot
In VS Code, setup is largely automatic: when you first use Copilot, the required extensions install themselves. You do not need to hunt through the marketplace.
Open VS Code and click the Copilot icon in the title bar. If Copilot is not yet set up, VS Code will prompt you through it.
For other editors:
- Visual Studio 2022 17.10 and later — Copilot is included as a built-in component.
- JetBrains IDEs — install the GitHub Copilot plugin from the Marketplace, then restart.
- Eclipse and Xcode — install the GitHub Copilot extension for that IDE.
Step 6 — Authenticate
Copilot needs to know who you are.
In VS Code, when prompted, sign in to GitHub and authorise the request in your browser. In JetBrains IDEs, go to Tools → GitHub Copilot → Login to GitHub, copy the device code, and complete authorisation in the browser window that opens.
Once authenticated, confirm the Copilot status indicator shows it is active. If it shows an error, the problem is almost always one of three things: no Copilot access on the account, an organisation policy blocking it, or an out-of-date extension. The installation lesson has a troubleshooting table.
Step 7 — Create a small project
Now for something real. You are going to build a small utility module with a deliberately specific contract, then test it.
Create the project:
mkdir copilot-demo && cd copilot-demo
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install pytestCreate the structure:
copilot-demo/ ├── .venv/ ├── app.py ├── requirements.txt └── tests/ └── test_app.py
mkdir tests
touch app.py tests/test_app.py
echo "pytest" > requirements.txtOpen the folder in your editor.
Step 8 — Get your first suggestion
Here is the important technique, and it is not a prompt.
Open app.py and type only this — the signature and the docstring, not the
body:
def parse_duration(value: str) -> int:
"""Convert a duration string such as '90s', '5m' or '2h' into seconds.
Supports the suffixes s (seconds), m (minutes) and h (hours).
Raises ValueError for an empty string, an unknown suffix,
a non-numeric quantity, or a negative value.
"""Press Enter and pause. Copilot should propose an implementation as ghost text.
Notice what just happened. You did not write a prompt. You wrote a contract: the input type, the return type, the accepted suffixes, and four specific error conditions. That docstring is the prompt, and it is a far better one than most people type into a chat box.
Check specifically:
- Does it handle all four error cases the docstring named?
- Does it reject negative values, or silently accept them?
- Does
'5'with no suffix raise, or default to seconds?
If the suggestion misses something, that is useful — it is the gap between what you specified and what was inferred. Press Esc to dismiss, or Tab to accept and then fix it.
Step 9 — Use Copilot Chat
Now switch layers. Open Copilot Chat — Ctrl+Shift+Alt+L on Windows and Linux, Shift+Option+Command+L on macOS — and ask it to critique what you just accepted.
Review the parse_duration function in this file. Identify any input that would produce a wrong result or an unhandled exception rather than the documented ValueError. List each case concretely with the exact input that triggers it.
This is chat used well: not “write me code”, but “find what I missed”. Inputs
worth checking that implementations commonly miss include '5', '', '-3m',
'1.5h', ' 30s ' and '10x'.
Now ask for tests:
Write pytest tests for parse_duration in tests/test_app.py.
Cover: valid seconds, minutes and hours; zero; whitespace around the value; and each documented failure case raising ValueError. Use pytest.mark.parametrize for the valid cases and pytest.raises for the failures. Import from app.
Apply the result to tests/test_app.py. Read it before you run it — check that
the assertions are actually correct, not just plausible. A generated test that
asserts the wrong expected value will pass against a wrong implementation and
tell you nothing.
One more chat pattern worth practising now, because it is the one people reach for least and benefit from most — asking for a change with an explicit constraint on what must not change:
Refactor parse_duration to separate parsing from validation, so each failure case raises from one obvious place.
Do not change the function signature, the exception type, or any of the documented behaviour. The existing tests must still pass unmodified.
The final sentence is doing the work. Without it, “refactor this” invites the model to improve things you did not ask about — renaming the function, changing the exception type to something it considers more idiomatic, or helpfully extending the accepted suffixes. Stating what is fixed is how you keep a refactor a refactor.
Step 10 — Review the code
Before running anything, read both files properly. You are looking for the things that are easy to miss:
- Does the implementation match its own docstring?
- Are the test assertions right, or merely self-consistent with a bug?
- Are there imports you did not need?
- Would you defend every line in code review?
This step feels skippable. It is the step.
Step 11 — Run it
python -c "from app import parse_duration; print(parse_duration('5m'))"Expect 300. If you get something else, or an exception, you have found a real
defect — fix it before continuing.
Step 12 — Run the tests
pytest -qIf a test fails, that is a good outcome for a learning exercise. Feed the failure back:
This pytest failure comes from the parse_duration implementation in this workspace. Explain the root cause, then propose the smallest change that fixes it without breaking the other passing cases.
[paste the full pytest output here]
Pasting the actual error output matters far more than describing it. The traceback is context; your paraphrase is not.
Step 13 — Write repository custom instructions
This is the step that pays off every day afterwards, and almost nobody does it on day one.
Custom instructions are persistent context prepended to Copilot’s requests in this repository. Instead of restating your conventions in every prompt — and getting suggestions that ignore them whenever you forget — you state them once, check the file into version control, and the whole team gets them.
Create .github/copilot-instructions.md in the project:
mkdir -p .github# Project conventions
This is a small Python 3.10+ utility library.
## Style
- Use type hints on every public function.
- Docstrings state the contract: inputs, return value, and every exception raised.
- Prefer the standard library. Do not add a dependency without a stated reason.
## Errors
- Raise `ValueError` for invalid input; do not return sentinel values such as -1 or None.
- Error messages name the offending value.
## Tests
- pytest, in `tests/`, mirroring the module layout.
- Use `pytest.mark.parametrize` for input tables rather than repeated near-identical tests.
- Every documented exception has a test asserting it is raised.Now start a fresh chat session and ask for a second function — say, the inverse
format_duration(seconds: int) -> str. You should see the conventions applied
without you mentioning them: type hints present, ValueError rather than a
sentinel, a parametrised test.
When not to reach for Copilot
Worth establishing early, because the habit forms fast in both directions.
- When you do not understand the problem yet. Copilot will produce a confident implementation of the wrong thing, and its confidence is contagious.
- When correctness is subtle. Concurrency, floating-point precision, authentication and authorisation boundaries, anything handling money. The output looks the same whether it is right or wrong.
- When you are learning the language. The struggle is where the understanding forms. Skipping it produces someone who can ship code they cannot debug.
- When the code is trivial. Reading a suggestion takes longer than typing three lines.
None of these are permanent restrictions. They are situations where the review cost exceeds the typing saved, which is the actual trade being made.
Common mistakes
| Mistake | Why it hurts | Do this instead |
|---|---|---|
| Accepting suggestions without reading them | Unreviewed code accumulates one keystroke at a time | Read the ghost text before Tab |
Vague prompts ("make a parser") | Every unstated decision gets guessed | State inputs, outputs and error behaviour |
| Asking for a whole application at once | Large diffs are unreviewable, so they go unreviewed | One capability per request |
| Trusting generated tests | A wrong test passing against wrong code proves nothing | Verify the expected values yourself |
| Working with no relevant files open | Copilot cannot use context it was not given | Open the interfaces and neighbouring modules |
| Pasting real secrets into chat | Credentials end up in prompt context | Use placeholders, always |
What you actually learned
The Python was incidental. The loop is the lesson, and it is the same loop at every level of the product:
- Establish context. The docstring, the open files, the instructions file.
- Ask for something specific. A contract, not a vibe.
- Read what came back, before accepting it.
- Run it. Not “it looks right” — run it.
- Feed real output back when it fails. Tracebacks, not paraphrases.
When you move to agent mode later, the same five steps apply, except step 4 is something the agent can do itself and step 3 covers a multi-file diff instead of one function. The scale changes; the discipline does not.
Frequently asked questions
Do I need to pay to follow this tutorial? No. Copilot Free covers everything here. Its limits — 2,000 completions a month and no cloud agent — do not bite on a project this size.
Copilot is not suggesting anything. What is wrong? Work through it in order: is the status indicator showing Copilot as active; are you signed in to the right GitHub account; does that account have Copilot access; is an organisation policy blocking it; is the extension current. The installation lesson has the full table.
Why did my suggestion differ from what this page describes? Because output is probabilistic. The same prompt in the same file produces different results between runs. That is expected, and it is why this tutorial tells you what to check rather than what you will see.
Should I commit .github/copilot-instructions.md?
Yes. That is the point of repository-scope instructions — the conventions travel
with the repository, so every contributor gets the same context.
Can I do this in a language other than Python? Yes, and the structure transfers directly: write a signature with a documented contract, let completion propose the body, ask chat for tests, run them. Use a language you can review confidently — the review step is where the value is.
What to do next
You now have the full loop: context in, suggestion out, review, run, verify. Everything else in Copilot is a variation on it.
The most valuable next habit is a repository custom instructions file — a one-time write that tells Copilot your language version, test framework and conventions, so you stop restating them. It improves every future interaction in that repository, for everyone on the team.
From here:
- How to Install GitHub Copilot — every supported environment, plus troubleshooting.
- Code Completion Explained — get more out of the layer you just used.
- Copilot Chat: Complete Beginner’s Guide — a working prompt library.
- Best Practices for Beginners — why the specific prompts above worked.
When you are comfortable with these, Agent Mode is the next real step up — the same loop, but Copilot drives and you supervise.
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.