Kipt

CLAUDE.md for Go: a copyable template for Go modules and services

A CLAUDE.md template for Go you can copy: go test, vet, gofmt and race commands, cmd/ and internal/ layout, error and context rules, plus an AGENTS.md variant.

By the Kipt team · Updated 24 October 2026

What should a CLAUDE.md for Go include?

A CLAUDE.md for Go should give Claude Code the exact go commands to build, test, vet, format and run a single test, a short map of cmd/ and internal/, and your rules for errors, context.Context, interfaces and generated code. Keep it under 200 lines and end it with a clear "done means" line so Claude knows which checks to run before it stops.

Go already gives an agent a lot: one formatter, one build tool, one test runner. What it cannot see from a few files is your choices. Is golangci-lint part of CI? Do integration tests need a database? Which packages are generated? Is log/slog the logger? Those are the lines that change what Claude does in your repo.

The template below targets the Go 1.27 toolchain, the current release on the Go release history page as of October 2026. Every command comes from the go command documentation or official Go tools. The layout follows the official Organizing a Go module guide for server projects. golangci-lint, log/slog and net/http.ServeMux routing are common choices, labeled as swappable, so replace them with whatever your team uses. Memory behavior comes from Anthropic's CLAUDE.md documentation. For the file format in general, see what a CLAUDE.md file is.

The Go CLAUDE.md template

Save this as CLAUDE.md at the root of your module, next to go.mod. Replace the angle-bracket placeholders and delete any line that does not match your project.

# <Service name>

<One sentence: what this module does and who calls it.>
Module: <github.com/acme/api> (see go.mod). Toolchain: Go 1.27.
The go line in go.mod sets which language features and std APIs we can use. Check it first.

## Commands
- Build everything: `go build ./...`
- Run the server: `go run ./cmd/<api-server>`
- All tests: `go test ./...`. One package: `go test ./internal/auth`
- One test: `go test ./internal/auth -run '^TestLogin$'`
- One subtest: `go test ./internal/auth -run '^TestLogin$/expired_token'`
- Race detector: `go test -race ./...`
- Bypass the test cache: add `-count=1`
- Short tests only (skips DB tests): `go test -short ./...`
- Vet: `go vet ./...`
- Format check: `gofmt -l .` (must print nothing). Fix: `go fmt ./...`
- Tidy deps after changing imports: `go mod tidy`
- Regenerate code: `go generate ./...`
- Lint (swappable): `golangci-lint run`
- Vulnerabilities: `govulncheck ./...`
- Done means: `gofmt -l .` is empty, and `go vet ./...` and `go test -race` pass for touched packages

## Project structure
- `cmd/<name>/main.go`: one folder per binary. main only parses config, wires deps, calls run
- `internal/`: all server logic. Nothing outside this module can import it
- `internal/<domain>/`: one package per domain, for example auth, billing, store
- `internal/store/`: the only package that talks to the database
- Package names are short, lowercase, one word. No util, common or misc packages
- Files starting with `// Code generated ... DO NOT EDIT.` are generated. Never edit them;
  change the source and run `go generate ./...`

## Errors
- Check every error. Never discard one with `_` unless a comment says why
- Wrap with context: `fmt.Errorf("load user %d: %w", id, err)`
- Compare with `errors.Is`. Extract types with `errors.AsType[*NotFoundError](err)` (Go 1.26+)
- Error strings are lowercase with no trailing punctuation
- Do not use panic for normal error handling

## Context and concurrency
- Anything that does I/O takes `ctx context.Context` as its first parameter
- Never store a Context in a struct. Never pass nil; use `context.TODO()` if unsure
- Every goroutine has a clear exit (ctx cancel, closed channel or WaitGroup)
- Run `go test -race` on any change that touches shared state

## Code style
- Define interfaces in the package that uses them. Return concrete types
- Do not add an interface only to mock something in tests
- Logging: `log/slog` with key-value attributes (swappable)
- HTTP routing: `net/http.ServeMux` patterns like `"GET /items/{id}"` (swappable)
- No `v := v` copies in loops; each iteration gets its own variable since Go 1.22

## Testing
- Tests live next to the code as `*_test.go`
- Table-driven tests with `t.Run` subtests
- Failures say input, got and want: `t.Errorf("Parse(%q) = %v, want %v", in, got, want)`
- Tests that need a database call `t.Skip` when `testing.Short()` is true
- Every bug fix comes with a test that failed before the fix

## Do not
- Do not add a dependency without asking. Prefer the standard library
- Do not edit go.sum by hand; `go mod tidy` maintains it
- Do not change the go or toolchain lines in go.mod unless the task is an upgrade

## Gotchas
- `(cached)` in test output means the test did not run again. Use `-count=1` when
  a test reads external state
- `go test` runs a subset of vet checks first; if one fails, the tests do not run
- <Your service's own surprises: local Postgres port, env vars, feature flags>

What does each part of the template do?

Header and go line. The Go 1.27 release notes add generic methods, and Go 1.26 let new take an expression and added errors.AsType. Models trained before those releases will not reach for them, and code that uses them will not build in a module whose go line is older. Telling Claude to read go.mod first settles both cases. Since Go 1.27, go test also runs the stdversion vet check, which reports standard library symbols that are too new for the module's go line.

Commands. Each one is documented in the go command reference. The -run flag takes a regular expression that is split on slashes, so -run '^TestLogin$/expired_token' targets one subtest. Successful package test results are cached, and the docs name -count=1 as the idiomatic way to disable that. -race turns on the data race detector on the supported platforms. go fmt runs gofmt -l -w, so gofmt -l . on its own is a read-only check. govulncheck ./... comes from the official govulncheck tutorial. The "Done means" line is the most useful rule in the file: it replaces "test your changes" with checks Claude can actually run.

Project structure. The module layout guide recommends keeping a server's logic in internal/ and putting each command under cmd/, and it notes that packages in internal/ cannot be imported from outside the module. The package naming rule comes from Effective Go (lowercase, single-word names) and the Go blog on package names, which calls util, common and misc meaningless. The generated-file marker is the exact pattern go generate documents.

Errors. Wrapping with %w and checking with errors.Is follow the errors package docs, which say errors.Is should be used in preference to simple equality. The lowercase error string and "don't panic" rules come from the official Go Code Review Comments.

Context and concurrency. The rules that a Context is the first parameter, is never stored in a struct and is never nil are quoted almost directly from the context package docs. The goroutine exit rule comes from the "Goroutine Lifetimes" section of Code Review Comments.

Code style. Code Review Comments says interfaces generally belong in the package that uses them, and warns against defining them on the implementor side "for mocking". The loop variable line matters because Go 1.22 gave each loop iteration its own variables, for modules whose go line is 1.22 or later, so the old copy idiom is noise. The same release added method and wildcard patterns to net/http.ServeMux.

Testing. The got and want message format is the example from the "Useful Test Failures" section of Code Review Comments. testing.Short() pairs with the -short flag so Claude can run fast tests without a database.

Which agent mistakes does the template prevent?

Go is simple enough that most agent mistakes are habits carried over from other languages or from older Go. Each section targets one:

Without the rule Line in the template that prevents it
Claude writes if err == ErrNotFound and misses wrapped errors "Compare with errors.Is"
A test "passes" because the result came from the cache "Bypass the test cache: add -count=1" and the gotcha
A new utils package collects unrelated helpers "No util, common or misc packages"
Claude edits a generated .pb.go file and the change is lost "Never edit them; change the source and run go generate"
A goroutine leaks because nothing cancels it "Every goroutine has a clear exit"
A mock interface appears next to every struct "Do not add an interface only to mock something"
Claude uses a std API newer than the module allows "Check the go line first"

When you add a rule later, name the mistake first, then write the shortest line that prevents it.

How do you adapt it to your project?

  • Library instead of a service: drop cmd/ and the server lines, and describe your exported API and compatibility promise instead. The layout guide shows a basic package with code in the module root.
  • No golangci-lint: delete the lint line. If you use it, add golangci-lint fmt too, as its quick start documents.
  • Different router or logger: replace the two swappable lines with your choice, such as chi or zap, and one example of the pattern you use.
  • Several modules in one repo: if you use a go.work workspace, say so and list go work use paths. The workspaces tutorial covers the commands. The monorepo template shows how to layer files per module.
  • Rules for one area: move them into .claude/rules/. A file with paths: ["internal/store/**/*.go"] in its frontmatter loads only when Claude reads or edits a file there, which keeps SQL rules out of unrelated work.
  • Code navigation: Anthropic's code intelligence docs list a gopls-lsp plugin that uses gopls, so Claude sees type errors right after an edit.

After saving, run /context in a Claude Code session and check the file appears under Memory files. In a repo without a CLAUDE.md, /init generates a draft from your code that you can merge with these sections.

How do you share it with other agents through AGENTS.md?

If your team also uses Codex, Cursor or Copilot, move the template into AGENTS.md and keep CLAUDE.md tiny. By default, Claude Code reads AGENTS.md only when the project has no CLAUDE.md or CLAUDE.local.md, and only from v2.1.277, so an import keeps both working:

@AGENTS.md

## Claude Code only
- Use plan mode before changing anything under internal/billing/
- Run `/doctor prompt-audit` after editing AGENTS.md or this file

Claude expands the import first, then reads the lines below it. The AGENTS.md guide covers which tools read the file, and the CLAUDE.md vs AGENTS.md comparison covers the trade-offs.

How do you keep a Go CLAUDE.md useful?

Add a line when Claude makes the same mistake twice, and delete lines it already follows without being told. When you bump the go line, revisit the header and any version notes. /doctor prompt-audit (Claude Code v2.1.283 or later) reports outdated or conflicting instructions with proposed edits and changes nothing until you ask. CLAUDE.md is context, not enforcement, so to block something outright, such as edits to generated files, use a hook.

If you start Go services often, keep the template somewhere you can reuse it. Kipt stores prompts and Agent Skills as Markdown in a private GitHub repo you own, so you could save this as a prompt with blanks like {{module_path:github.com/acme/api}} and fill them per project. The Go prompts collection pairs well with it. Templates for other stacks: Rust, Next.js, FastAPI, Django and Rails.

Questions

What should a CLAUDE.md for a Go project include?

The exact commands to build, test, vet, format and run one test, a short map of cmd/ and internal/, your rules for errors, context and interfaces, and the gotchas Claude cannot see from the code. Keep it under 200 lines, as Anthropic's memory docs recommend, and leave out generic Go advice Claude already knows.

How do I make Claude Code run a single Go test?

Write the pattern in CLAUDE.md: go test ./internal/auth -run '^TestLogin$' runs one test in one package. The -run flag takes a regular expression split on slashes, so -run '^TestLogin$/expired' runs one subtest. Add -count=1 when you need to bypass the test cache.

Should a Go CLAUDE.md mention golangci-lint?

Only if your project uses it. go vet ships with Go and go test already runs a high-confidence subset of vet checks, so vet is the safe default. golangci-lint is a popular third-party runner; if you use it, list golangci-lint run and golangci-lint fmt so Claude runs the same checks as your CI.

Where do I put rules that apply to one Go package?

Either in a short CLAUDE.md inside that package's folder, which Claude Code loads when it reads or edits files there, or in .claude/rules/ with a paths field such as internal/store/**/*.go. Both keep the root file short.

Does Claude know about new Go features like generic methods?

Not reliably. Go 1.27, released in August 2026, added generic methods, and Go 1.26 let new take an expression. Tell Claude to check the go line in go.mod before using recent language features or standard library APIs, because the go directive decides what the module can use.

More in Templates

All guides

Keep your prompts and skills in one place, in your own GitHub. Install every skill with one command.

Get started

Kipt is an independent product, not affiliated with or endorsed by Anthropic, OpenAI, Cursor or GitHub. Claude, ChatGPT, Codex, Cursor and GitHub are trademarks of their owners.