baseline.md

Go baseline

Start from Amolith's strict Go baseline, then adapt it deliberately with the user and the project in front of you. This file is for Go tooling, architecture, libraries, tests, packaging, and build workflow, not for copying a boilerplate blindly.

Go operating mode

  1. Inspect go.mod, existing task runner, build files, packaging files, UI surface, and tests.
  2. Classify the project: library, CLI, TUI, MCP server, light web app, Wails desktop app, frontend-heavy app, service, or some mix.
  3. Start from the strict baseline, then relax, remove, or add further pieces only when the project needs them.
  4. Verify each slice with the narrowest useful mise run ... task.

Do not introduce Taskfiles or justfiles by default. If an older project uses Task or just, translate the useful commands into mise.toml unless the user explicitly asks to keep the old runner.

Defaults

Default to:

  • mise.toml for tools and tasks
  • golangci-lint fmt for formatting
  • golangci-lint run --enable-only modernize --fix ./... for modernization
  • golangci-lint run --fix for lint fixes
  • govulncheck ./... for vulnerability scanning
  • slower, race-enabled tests in development: go test -v -race -count=5 -p=3 -timeout=5m ./..., with CGO_ENABLED=1 for the test task
  • pure-Go static release builds for CLIs, TUIs, and MCP servers when the project does not require CGO
  • explicit build/install tasks for binaries
  • nFPM when shipping native Linux packages
  • small packages with domain names, not generic utils
  • standard library first unless a preferred library clearly fits
  • Amolith's licensing convention when the project does not already say otherwise: CC0 for docs/examples/config/prompt text, MutuaL for meaningful code

Use this .golangci.toml shape unless the project already has a stronger local configuration. Replace the module path placeholders with the module from go.mod:

version = "2"

[linters]
enable = ["bodyclose", "errcheck", "errorlint", "exhaustive", "gocognit", "govet", "ineffassign", "modernize", "nilerr", "nilnil", "noctx", "revive", "staticcheck", "unused"]

[linters.settings.gocognit]
min-complexity = 15

[[linters.settings.revive.rules]]
name = "file-length-limit"
arguments = [{ max = 1000, skip-comments = true, skip-blank-lines = true }]

[[linters.settings.revive.rules]]
name = "max-control-nesting"
arguments = [5]

[formatters]
enable = ["goimports", "gofumpt", "gci", "golines"]

[formatters.settings.goimports]
local-prefixes = ["<module-path>"]

[formatters.settings.gofumpt]
module-path = "<module-path>"

[formatters.settings.gci]
sections = ["standard", "default", "localmodule"]

[formatters.settings.golines]
max-len = 120

Default away from:

  • Taskfiles and justfiles in new setup
  • clix/kong, even when another Go skill recommends it; use stdlib flags for tiny tools and Cobra + Fang for user-facing CLIs
  • generated wrappers around one command
  • large frontend stacks for light server-rendered pages
  • configuration frameworks when direct parsing is enough
  • hidden global state unless a test seam restores it with t.Cleanup

Use generic Go skills for implementation details, but this skill wins for Amolith-specific setup choices: mise, golangci-lint formatting/fixing, modernize, static build shape, CLI framework, packaging, Wails frontend stack, web styling posture, and explicit gocuke adoption.

Gocuke is an explicit project choice. Ask whether the project wants gocuke/BDD automation; if yes, load the gocuke skill after behaviour is formulated. If no, use ordinary Go tests.