Ziqi (Katrina) Ding

Back

The Situation#

AI-assisted development tools have become part of everyday coding. But how much they actually help depends on the codebase, how specific the task is, and above all how much context the model has about what you’re doing.

Over a few months my team’s use of GitHub Copilot went through four distinct stages. Each one fixed a problem the previous one created. This post is the overview; the two bigger lessons have their own posts.

What I Learned#

  1. An LLM is an excellent executor but bad at planning on its own (at least right now). Give it the plan, or make it write one and approve it first.
  2. Output quality tracks context and specificity. Vague ask, vague answer.
  3. Different models have different strengths. Pick per task, not per habit.

Stage 1: Just ask#

We attached a couple of files and talked to Copilot like a colleague.

User[attach file 1 + file 2]Hi, can you fix this error: some errorhereCopilot Chat[Read File 1][Read File 2]Ok, I will help you ...

It works for small, self-contained questions. It falls apart as soon as the answer depends on project conventions the model can’t see.

Stage 2: Ask with custom instructions#

Copilot reads .github/copilot-instructions.md on every request, so we used it to describe the project, coding style and the rules we wanted followed.

.github
└── copilot-instructions.md
plaintext
User[attach file 1 + file 2]Hi, can you fix this error: some errorherecopilot-instructions.mdProject Context...Project structure...Your workflow...Critical: DO NOT... ALWAYS...Copilot Chat[Read File 1][Read File 2]Ok, I will help you ...

This was the single biggest quality jump. Suggestions started matching our patterns instead of generic ones.

Around the same time we moved to agent mode. The agent gets tools: search the codebase, run commands, edit files, and connect to MCP servers for external resources. It can chain small steps on its own to reach the goal.

Copilot Agent's Tool Button Tools Configuration window

Stage 3: Custom chat modes#

We didn’t always want the agent to have every tool. Some workflows should be read-only; some should never touch the network. Limiting tools keeps the agent focused and reduces the blast radius when it misunderstands.

Custom chat modes solve that: a mode bundles a system prompt with a fixed tool list. I wrote up how to build one in GitHub Copilot Custom Chat Modes.

User[attach file 1 + file 2]Hi, can you fix this error: some errorherepackage-upgrade.chatmode.mdRequirements...Workflow...Critical: Ignore high-risk updates...copilot-instructions.mdProject Context...Structure...Workflow...Critical rulesCopilot Chat — Custom Agent[Read File 1][Read File 2]Ok, I will help you ...

Chat modes shine for regular, medium-sized jobs with a well-defined sequence, like our NPM package upgrade mode.

The limitation: a mode’s prompt and tools apply to the whole conversation. You can’t mix a bug-fix procedure into a general chat without switching modes and losing context.

Stage 4: Prompt files#

We needed something smaller: a reusable prompt we could drop into any conversation, in any mode. That’s what .github/prompts/*.prompt.md files are. Type / in chat and pick one.

.github
├── chatmodes
│   └── package-upgrade.chatmode.md
├── copilot-instructions.md
└── prompts
    └── bug-fix.prompt.md   # <== here
sh
User[attach file 1 + file 2]Hi, can you fix this error: some errorherecopilot-instructions.mdProject Context...Structure...Workflow...Critical rulesbug-fix.prompt.mdStep 1...Step 2...IMPORTANT:Copilot Chat[Read File 1][Read File 2]Ok, I will help you ...

How to set them up, with the ones we use, is in GitHub Copilot Prompt Files.

Then the problems started#

With instructions, a chat mode and a prompt file all loaded at once, three things went wrong:

  • The context window filled up too fast. Copilot forgot the conversation and stopped following the rules we’d set at the start.
  • Instructions contradicted each other. One file said async/await, an old prompt said callbacks, and we got both in the same function.
  • The wrong instruction won. Whatever was typed last overrode the project rules, especially on weaker models.

The fix was to split copilot-instructions.md into a small behaviour file and a separate project-context file, and cut both hard. That’s the subject of Why Your Copilot Instructions Stop Working.

How It Changed My Approach#

  • Behaviour rules, project facts and task procedures now live in three different files, each short, each cross-referencing the others instead of repeating them.
  • Chat modes for repeatable workflows; prompt files for one-off procedures; instructions only for what applies to every request.
  • Plan with a strong model, execute with a fast one, and write the plan down before any code changes.

Summary#

Plain chat, then instructions, then chat modes, then prompt files: each stage gave Copilot more context, and the last lesson was that too much context in one place is its own problem.

References#

How My GitHub Copilot Setup Evolved - From Plain Chat to Instructions, Modes and Prompt Files
https://katrina-ziqi-ding.com/blog/github-copilot-use-insights
Author Ziqi (Katrina) Ding
Published at 25-08-2025