GitHub Copilot CLI is a command-line coding agent that you start with copilot in your Go project folder. It reads your code, runs Go tooling such as go test and go vet, and proposes or applies edits you can verify with the standard Go workflow. This guide covers setup, a working loop, and the places where a Go developer should watch the agent closely.
Why GitHub Copilot CLI is practical for Go codebases
Go’s fast compiler and test runner create a tight feedback loop for an agent that can run commands and inspect failures. Rather than generating a large speculative patch, you can ask for a small change and let the agent see the actual test output, then focus only on the narrow fix. This is especially useful for Go’s repetitive but important chores: table-driven tests, context plumbing, interface extraction, and error wrapping. The agent is less helpful when the task requires deep reasoning about ownership and cancellation; those are the cases where you want to keep the changes small and review the diff.
Go project instructions for Copilot CLI
The agent reads project instructions from .github/copilot-instructions.md or AGENTS.md. Put one of these files at the repository root with the exact commands and conventions you want it to follow. Without this, the agent guesses and tends to drift toward non-idiomatic choices. Keep the file short and specific. A realistic Go example:
# Go project instructions
Run all commands from the repository root.
Build:
go build ./...
Test:
go test ./...
Lint:
go vet ./...
Format:
gofmt -w .
Folder conventions:
- /cmd for main packages
- /internal for private packages
- /pkg for exported packages
Rules:
- Keep go.mod and go.sum tidy; run `go mod tidy` after adding or removing imports.
- Prefer table-driven tests in the same package as the code.
- Use context.Context as the first argument for functions that block or perform I/O.
- Wrap errors with fmt.Errorf("...: %w", err) unless a sentinel error is required.
- Do not introduce package-level mutable state without explicit approval.
- For any concurrent change, run `go test -race ./...` before marking the task complete.
The key is to be exact: if you use go test -race ./... in CI, put it in the file so the agent runs the same check. If you use build tags or go generate, add the command as well. Missing instructions is the most common reason the agent produces code that passes locally but fails in CI. For a broader walkthrough of the agent itself, see How to use GitHub Copilot CLI.
A plan-and-verify workflow for Go prompts
A working loop that fits Go starts by asking for a plan. Require the agent to name the files and functions it will touch. Then approve a minimal patch, let it run go test ./... and go vet ./... in the terminal, and read the diff yourself. If a test fails, ask the agent to show the failure and propose a fix with an explanation. Each cycle should be small enough to review in a few minutes. This keeps the agent from refactoring broad swaths of the module. Example prompts for typical Go tasks:
- “Look at
internal/clientand list the changes needed to add request timeouts usingcontext.WithTimeout; do not edit files yet.” - “Write a plan for extracting the
Storeinterface frominternal/dbintointernal/store, then show the affected call sites.” - “Implement the timeout plan in small steps; run
go test ./...after each step and stop if a test fails.” - “Add table-driven tests for
internal/ratelimit.Allowcovering burst, refill, and zero-burst cases; rungo test -race ./...when done.” - “Fix the data race reported by
go test -race ./...inpkg/workerand explain why the fix is safe.”
After the agent finishes, run git diff to read the actual patch, then go vet ./... and gofmt -l .. Do not accept a change without reading the diff, especially around goroutines and error handling.
Where Copilot CLI excels and where to watch it
The agent handles several Go tasks well when the prompt names the function or package and the expected behavior. The table below shows tasks that are safe to delegate and the verification to run.
| Task | Good prompt | Verification |
|---|---|---|
| Add context plumbing | “Thread ctx context.Context through all internal/store methods and update callers.” | go vet ./..., go test -race ./... |
| Extract an interface | “Extract a Searcher interface from internal/db used by cmd/api; keep the real DB behind it.” | go test ./..., review interface shape |
| Write table tests | “Add table-driven tests for pkg/retry.Backoff covering zero, max, and overflow cases.” | go test -run TestBackoff -count=1 |
| Fix gofmt/vet issues | “Run gofmt -l . and go vet ./..., then fix only the reported issues.” | git diff --check, gofmt -l . |
| Update go.mod dependencies | “Upgrade x/sync to the latest patch release and show the go.mod and go.sum diff.” | go mod tidy, go test ./... |
Watch it closely in a few Go-specific places. Concurrency is the biggest risk: the agent can write plausible sync.WaitGroup or channel code that passes a short test but leaks or races under load. Always require go test -race and ask for explicit context.Context cancellation paths. Error handling can drift toward fmt.Errorf without %w or log-and-return; make your instructions explicit. Interface extraction may generate an empty interface or a bloated interface with methods only one caller needs, so review the consumer side. The agent may also add an unnecessary dependency or update go.mod incorrectly; ask it to show the go.mod and go.sum diff before accepting. When the agent edits multiple packages at once, check for import cycles because Go rejects them, but the agent may not realize the cycle until it runs go build.
Testing and verification with go test and go vet
Make verification part of the prompt, not an afterthought. Have the agent run the exact commands you would run locally. For ordinary changes: go test ./... and go vet ./.... For concurrent code: go test -race ./.... For formatting: gofmt -l . should return nothing, and git diff --check should be clean. Table-driven tests are the easiest thing to ask for; give the agent the function name and the edge cases, and let it write the test table. When it claims a fix works, run the tests again yourself with go test -count=1 to skip the test cache, because the agent may rely on cached passing tests without realizing. The race detector is essential for any code that uses goroutines, channels, or shared state. Ask the agent to paste the race output; if it reports a race, have it propose a fix and explain the memory model reasoning. If the repository is large, a codebase map for AI agents can help the agent find the right Go files instead of guessing with grep, but the final check is always the test suite.
Parallel changes with AgentVera on a Go repo
For larger Go refactors, AgentVera lets you run GitHub Copilot CLI alongside other agents in separate terminal panels, each in its own git worktree, so parallel changes to internal/ packages do not overwrite each other. Automatic code review after each turn catches issues like a missing defer cancel() or an unhandled error, with findings linked to file:line. Checkpoints let you undo a bad concurrency change and replay the session to see where it went wrong. This matters most in Go because the compiler and race detector can catch many mistakes, but only if each agent’s diff is reviewed in isolation.
Final checks before you merge
GitHub Copilot CLI is most useful in Go when you treat it as a fast implementer with a short leash. Put your exact build, test, and lint commands in the instructions file, ask for small patches with tests, and always run the race detector for anything concurrent. The tool writes idiomatic Go when the rules are explicit, but the verification remains yours. Before accepting any agent change, read the diff at least twice: once for correctness and once for idiomatic style like context propagation, error wrapping, and interface size. Then run the full test suite one more time and commit with confidence.