opencode is a terminal coding agent you start by running opencode in a project folder. For Go work, add an AGENTS.md file that records your build, test, vet, and layout rules. Then work in small steps: ask for a change, run go test ./... and go vet ./..., and review the diff before moving on. See opencode for the agent itself.
opencode’s strengths for idiomatic Go codebases
opencode operates on the actual source tree and can run the same commands you already use: go build, go test, go vet, and gofmt. Because Go projects tend to have strong conventions around packages, interfaces, and table-driven tests, a coding agent that reads project instructions from AGENTS.md can apply those rules consistently. The agent handles mechanical refactors such as renaming an interface or threading context.Context through a call chain without losing the shape of your tests. It also respects module boundaries: it can reason about internal/ visibility and import paths, and it typically avoids suggesting package cycles when you ask for a design change.
Prepare a concise AGENTS.md for the Go module
The single most useful thing you can do is write a concise AGENTS.md in the repository root. opencode reads it before acting, so it becomes the default specification for every task. Keep it specific to this codebase, not generic Go advice.
# AGENTS.md
Module: github.com/acme/checkout
Layout:
cmd/ - main packages
internal/ - private packages
pkg/ - public libraries (avoid unless necessary)
Build: go build ./...
Test: go test ./...
Race: go test -race ./...
Vet: go vet ./...
Format: gofmt -w .
Rules:
- Prefer the standard library; justify third-party dependencies.
- All exported identifiers need doc comments.
- Functions that block on I/O take context.Context as the first argument.
- Use table-driven tests in the same package with t.Run for subtests.
- Return errors instead of panicking for normal failures.
- Goroutines must have clear ownership and cancellation via context.
That file gives the agent enough to start a task without asking you whether to run go test ./... or where main packages live. Update it whenever you change the module path or add a required lint step such as staticcheck.
Keep a tight edit, test, and review cycle
Do not hand the agent a 50-line request. Plan the change, ask for a small slice, run the verification commands, then review the diff. opencode works best when each step is testable in isolation.
A typical loop looks like this:
- State the goal and the files or packages affected.
- Ask the agent to write or update tests along with the implementation.
- Run
go test ./...,go vet ./..., andgofmt -l .yourself. - Review the diff for interface changes, goroutine ownership, and error handling.
- Commit the verified step and move to the next slice.
Example prompts that match this loop:
- Add a context-aware worker pool to internal/worker using sync.WaitGroup, with table tests that exercise cancellation and error aggregation.
- Define a smaller PaymentProvider interface in the consumer package, keep the existing gateway as the implementation, and update all tests without changing public behavior.
- Trace the hot path in internal/checkout and replace the hand-rolled retry loop with a context-aware helper; add tests for backoff and deadline exceeded.
- Convert the store package from package-level globals to an explicit Store struct with a constructor; update all callers and tests.
- Run gofmt and go vet, fix the reported issues, and add a doc comment for every newly exported identifier.
For longer sessions, the step-by-step guide at How to use opencode: a step-by-step guide is a useful reference.
Concurrency, interfaces, and other areas to watch
opencode handles several Go tasks well: generating table tests for existing functions, adding context propagation through a package, splitting a large package into internal subpackages, writing mocks for interfaces, and updating error wrapping with fmt.Errorf and %w. It is also good at enforced formatting and vet fixes.
Watch it closely in these specific areas:
- Nil interfaces versus nil concrete pointers. An error or interface can be non-nil even when the underlying pointer is nil; tests may pass incorrectly.
- Goroutine leaks. If the agent writes a worker pool or retry loop, confirm cancellation exits all paths and cleanup runs.
- Copying values that contain sync.Mutex or sync.WaitGroup.
go vetcan catch some of this, but not always after a refactor. - Error comparisons. Prefer
errors.Isanderrors.Asinstead of==or type assertions; the agent may revert to simpler patterns. - Importing internal packages from outside the allowed parent. The compiler will catch it, but you can save a round trip by checking import paths in the diff.
- Ignoring context cancellation in long-running operations. Always read from a context or use a helper like
errgroupif it is already a dependency.
If the agent proposes a change in generated code such as protobuf or stringer output, inspect it manually or regenerate the code yourself.
Run go test, race, and vet after each change
Make verification explicit in every prompt: ask the agent to run go test ./... and go vet ./... before reporting completion. Then run them again yourself. For concurrency-sensitive changes, add go test -race ./...; it is slower but catches data races that table tests may miss.
| Command | What it catches |
|---|---|
go test ./... | package compilation and unit/table test failures |
go test -race ./... | data races in goroutines and shared state |
go vet ./... | unsafe or suspicious constructs, such as copying locks |
gofmt -l . | formatting drift that should not enter the diff |
When the agent adds tests, look for table-driven style with subtests and a clear name per case. Avoid accepting tests that only assert the happy path; request at least one case for cancellation, one for an error, and one for a zero value. After a refactor, use git diff --stat and git diff to confirm that unrelated files did not change.
Run parallel agents in separate worktrees with AgentVera
AgentVera is a desktop app that runs coding agents’ real command line tools, including opencode, side by side in one window. For Go work, the most valuable parts are parallel git worktrees, automatic code review, checkpoints, and flows. Separate worktrees let agents refactor packages without overwriting each other’s files. Automatic review after each turn catches mistakes such as copied mutexes or leaked goroutines and links to file:line. Checkpoints make it safe to undo a bad interface change. Flows let one agent design a package API and the next implement and test it. The other AgentVera features are less relevant when you already have Go’s own test and vet loop.
Practical wrap-up for Go teams
opencode is most useful on a Go project when you treat it as a fast junior engineer with strong knowledge of the standard library. Give it a specific AGENTS.md, keep tasks small, verify with go test and go vet, and review every diff. If you need more throughput, run several agents in separate worktrees with AgentVera. For a comparison with another popular CLI agent, see opencode vs Claude Code: an honest comparison.