# CLAUDE.md — Agent Instructions This file is read automatically by Claude Code at the start of every session. Keep it concise — the agent needs signal, not essays. --- ## Project overview Go 1.24 template / PoC starter. Demonstrates: structured logging (zap), config (viper), interfaces + mocks (mockery), linting (golangci-lint), security scanning (gosec, govulncheck), git hooks, devcontainer, VSCode tasks. Module: `github.com/your-org/go-template` — update this when you fork. --- ## Project structure ``` cmd/app/main.go composition root — wires deps, no logic here internal/config/ Viper config loader (config.Load) internal/logger/ Zap wrapper with WithField / WithFields internal/greeter/ Example domain package (delete or repurpose) mocks/greeter/ Generated mocks — regenerate with `make mocks` config/dev.yaml Local dev config (committed, no secrets) tools.go Tool version pinning (build tag: tools) .golangci.yml Linter rules .mockery.yaml Mockery code-gen config .githooks/pre-commit Runs gofmt + golangci-lint + gosec before commit ``` --- ## Project rules - **Module imports** — always use the full module path `github.com/your-org/go-template/...` - **Packages** — keep `cmd/` thin (wiring only); business logic belongs in `internal/` - **Interfaces** — define interfaces where they are *used*, not where they are *implemented* - **Errors** — wrap with `fmt.Errorf("context: %w", err)`; never swallow errors silently - **Logging** — use `log.WithField("key", val)` for structured context, never `fmt.Sprintf` in log messages - **Config** — all configuration through `internal/config`; no hard-coded values in logic packages - **Secrets** — never commit `.env` files or credentials; use env var overrides of config keys --- ## Code style - Follow `gofmt` + `goimports` formatting (enforced by linter and git hook) - Imports: stdlib → blank line → external → blank line → internal (goimports handles this) - Error variables: `err` for local, `ErrFoo` for package-level sentinels - Constructors: `New(deps...) *Type` pattern - Comment every exported symbol (golangci-lint will warn if missing) - Max line length: 120 chars (configured in `.golangci.yml`) - Prefer explicit over clever; PoC code should be readable first --- ## Testing rules - All tests use **testify** (`assert` for soft checks, `require` for stop-on-fail) - Test files: `package foo_test` (black-box) unless white-box access is needed - Mock dependencies via **mockery**-generated mocks with `EXPECT()` chains - Use `logger.NewNop()` when the test doesn't care about log output - Table-driven tests with `t.Run("description", ...)` for multiple cases - The race detector is enabled in CI (`make test-race`); don't introduce data races - Never use `time.Sleep` in tests; use channels or `require.Eventually` --- ## Development commands ```bash make init # first-time setup: fetch deps, install tools, git hooks make build # compile to ./bin/app make run # go run with config/dev.yaml make test # run all tests make test-race # tests + race detector make lint # golangci-lint make lint-fix # auto-fix lint issues make security # gosec + govulncheck make mocks # regenerate all mocks make generate # run all //go:generate directives make clean # remove bin/ and mocks/ ``` VSCode: `Ctrl+Shift+B` = build, `Ctrl+Shift+T` = test. Debug: use launch config "Debug: app" (F5). --- ## Adding new features (checklist) 1. Define the interface in `internal//` 2. Write the implementation and its unit tests 3. Add the interface to `.mockery.yaml` and run `make mocks` 4. Wire it in `cmd/app/main.go` 5. Run `make lint test` before committing --- ## Known pitfalls - `mocks/` are committed intentionally — regenerate after interface changes - `govulncheck` makes network calls; excluded from pre-commit hook (run manually) - `config/dev.yaml` is committed but never add real credentials here - `tools.go` has `//go:build tools` — it won't compile into the binary --- ## Recent work - 2026-03-05 — Initial template scaffolded: config, logger, greeter example, mocks, git hooks, devcontainer, VSCode tasks, golangci-lint, Makefile.