go-coding — Go standards router
Route the Go task to the right standard and tool — this skill is a router, not an encyclopedia. Two principles from the project research drive it:
- Deterministic beats prose. Whatever a formatter or linter enforces, run the tool — don't reason it out by hand. The plugin's value is judgment the model lacks, not re-deriving tooling.
- Don't rebuild code intelligence. For defs/refs/diagnostics/rename/vulncheck, recommend the
official
gopls-lspplugin (@claude-plugins-official).
Routing table
| Topic | Run now (deterministic) | Deeper skill |
|---|---|---|
| Formatting | gofmt -l / gofumpt -l (+ goimports) — machine-enforced, non-negotiable |
— |
| Static analysis / likely bugs | go vet ./..., golangci-lint run |
go-lint-setup |
Modern idioms (range-int, min/max, slices/maps, wg.Go, strings.Cut, new(expr), errors.AsType) |
go fix ./... (the toolchain's modernizer suite), or golangci-lint run --enable-only=modernize for CI reproducibility |
go-idioms |
Errors (%w, errors.Is/AsType, errors.Join, sentinel/typed, enum dispatch) |
golangci-lint run --enable-only=errorlint,exhaustive |
go-errors |
| Concurrency (goroutine leaks, ctx lifecycle, atomics) | go test -race ./..., go vet ./... |
go-concurrency |
Testing (table-driven, t.Parallel, t.Context, B.Loop, testing/synctest) |
go test -race ./...; use testing/synctest for time/concurrency tests |
go-testing |
Layout, naming & API surface (internal/, imports, initialisms, receiver type, in-band errors, struct literals, doc comments) |
golangci-lint run --enable-only=revive (var-naming, receiver-naming, exported, blank-imports, dot-imports), go vet (composites), gofmt for doc-comment layout; the rest is judgment |
go-layout |
| Code intelligence (defs/refs/diagnostics/rename/vulncheck) | install the gopls-lsp plugin |
— |
Open the focused go-* skill for the topic — it carries the cited rules and the judgment; run the
tool in the middle column to enforce them. Don't invent rules: each skill cites its sources.
Route, then load
The router is an index, not the standard. Before writing or reviewing Go you MUST load the focused
skill matching the change — with the Skill tool (go-coding:go-errors, …), not by recalling it:
| The diff touches… | Load |
|---|---|
any _test.go, a benchmark, a fuzz target, a "verified by temporarily breaking it" claim |
go-testing |
fmt.Errorf, errors.*, a sentinel, a typed error, a Must helper, a switch over an enum |
go-errors |
a loop, map, slice, string split, interface{}, a struct literal that could be new(expr), a nested := on err |
go-idioms |
go func, chan, sync., atomic., errgroup, context.With*, a Close on a goroutine-owned resource |
go-concurrency |
a new package, an exported identifier, a cmd/ or internal/ decision, an import block, a struct literal of a foreign type, a doc comment on an API |
go-layout |
.golangci.y*ml, a linter complaint you do not understand |
go-lint-setup |
One load per skill per session is enough; the skill stays in context. Orchestrators dispatching implementer or reviewer subagents carry this table into every brief — a subagent does not inherit the parent session's skills.
Minimum checklist (when a second load is not affordable)
Apply these even if you load nothing else; they are the rules the focused skills most often catch:
- Wrap with
fmt.Errorf("…: %w", err); inspect witherrors.Is/errors.AsTypeand guard the result (ok && v != nil— a typed-nil pointer satisfies the match). Never swallow an error. - Every guard has a test that fails when the guard is deleted; a "temporarily broke it by hand"
check is not evidence — commit it as a can-fail test. Table-driven
t.Runwith got/want messages. range n,min/max,slices/maps,strings.Cut,any;go fix ./...before hand-edits.ctxfirst; no goroutine without an owner that waits for it;t.Context()in tests.- Run
gofmt/gofumptandgolangci-lint run— never reason out what a tool decides.
Tie-breaks (when two valid forms compete)
When both forms pass the tools, decide by the order Google's Go Style Guide gives for readable code: clarity, then simplicity (with its rule of least mechanism: the most standard tool that expresses the idea), then concision, then maintainability, then consistency. Say which attribute decided it; "more idiomatic" on its own is not a reason. Source: https://google.github.io/styleguide/go/guide (normative and canonical).
Writing for the human
Anything a person reads — a PR description, a review comment, a question, a design choice put to them — goes in plain English, not Go shorthand. State the effect before the mechanism ("the request keeps running after the caller gives up", not "ctx leak in the errgroup"), and expand a term the first time it appears or leave it out. Keep it short: a few sentences per point, and a decision they must make gets the options plus a recommendation, not an essay. Identifiers, commands and linter names stay verbatim — it is the prose around them that must be plain.
Authoritative sources (cite, don't guess)
- Effective Go — https://go.dev/doc/effective_go
- Go Code Review Comments — https://go.dev/wiki/CodeReviewComments
- Google Go Style Guide — https://google.github.io/styleguide/go/ — three documents, cite the one a rule comes from: the Guide (https://google.github.io/styleguide/go/guide, normative and canonical: the principles), Style Decisions (https://google.github.io/styleguide/go/decisions, normative: the reviewer rulebook), Best Practices (https://google.github.io/styleguide/go/best-practices, advisory)
- Uber Go Style Guide — https://github.com/uber-go/guide
- Package & toolchain docs — https://pkg.go.dev
- Linter rule catalogues (name the rule, not just the tool) —
go vethttps://pkg.go.dev/cmd/vet; staticcheck https://staticcheck.dev/docs/checks/; revive https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md; golangci-lint linters https://golangci-lint.run/docs/linters/
For a focused review
Dispatch the go-reviewer agent — a report-only, context-isolated reviewer that applies the
review-heuristics catalog and returns severity-ranked findings on a diff or file.
If a workflow already owns the reviewer seat, that reviewer loads the focused skills itself instead — one review seat per diff. Orchestrators: put the "Route, then load" table into every implementer and reviewer brief.
/go-lint-setup scaffolds the reference golangci-lint v2 config into a repo.
Top-level structure adapted from samber/cc-skills-golang (MIT © 2026 Samuel Berthe).