The config key that quietly did nothing
Config loaders ignore keys they do not recognise, so a typo runs on the old value. Deriving a validation schema from struct tags to catch it.

Config loaders ignore keys they do not recognise, so a typo runs on the old value. Deriving a validation schema from struct tags to catch it.

Go allows only one trailing variadic parameter, so adding another argument to a function that already has one is impossible. What to do instead.

The other audience for a CLI is the script that greps its output and breaks. Giving every command a JSON output mode with one response envelope.

When a Go CLI grows into a service: ordered graceful shutdown on SIGTERM, separate liveness and readiness probes, and an opt-in restart supervisor.

Timing, auth, recovery and logging are cross-cutting in a CLI too. Wrapping Cobra commands in web-style middleware rather than PreRun hooks.

One tool, three logging backends: colour for a terminal, JSON for a container, silence for tests. Depend on the interface, choose the backend once.

Recovery advice belongs in a structured error hint, not buried in the message string. One error handler then decides how to show it.

Go embed.FS is per-package, so a modular CLI ends up with islands. Merging them into one filesystem, and deep-merging YAML and JSON across them.

Passing dependencies to Go commands in a typed struct rather than stuffing them in context.Context, so the compiler checks them and tests stay simple.

go-tool-base keeps an entire CLI command tree in one manifest file and generates the wiring from it, without locking you out of hand-written Go.
