cmdguard
Website · Docs · pkg.go.dev
---
The Go CLI framework that catches missing handlers, duplicate commands, and invalid flags at construction — not at 2am in production.
cmdguard is the only Go CLI framework that unifies type-safe flags, dependency injection with lifecycle management, and a zero-panic error contract into a single system validated at construction. It wraps Cobra so you keep full compatibility while eliminating its footguns.
Get started in 30 seconds: go get github.com/larsartmann/cmdguard/v4 · Quick Start · Full Docs
API Stability: v4.0.0 is the current release on the v4 major line. The legacy v2 line is in maintenance at v2.10.4. See CHANGELOG.md and the v2→v3 Migration Guide.
---
Why cmdguard?
Other Go CLI frameworks give you flags. cmdguard gives you flags plus everything production CLIs need: dependency injection, service lifecycle, health checks, graceful shutdown, styled output, and error handling that won't bite you.
The trinity — what no other CLI framework offers together
| Capability | Cobra | Kong | urfave/cli | cmdguard | | ------------------------------------------------- | ----- | ------------------- | ---------- | ------------ | | Struct-tag flags (no string lookups) | — | Yes | — | Yes | | Dependency injection (lazy services, lifecycle) | — | — | — | Yes | | Graceful shutdown (reverse-order on SIGINT) | — | — | — | Yes | | Health checks (DoctorCommand, Healthchecker) | — | — | — | Yes | | Zero panics by construction (no Run, no Must) | — | — | — | Yes | | Validated at construction (not at runtime) | — | Some <sup[1]</sup | — | Yes | | Error printed exactly once + correct exit codes | — | — | — | Yes | | Styled output by default (fang + lipgloss) | — | — | — | Yes | | Gradual migration (raw cobra + typed runtime) | — | — | — | Yes |
<sup[1]</sup Kong validates struct tags at parse time but does not validate command structure (missing handlers, duplicates) at registration.
Dependency injection — the real differentiator
Register services, invoke them in handlers, and manage their entire lifecycle:
cli, _ := v4.NewCLI[AppConfig]("myapp", "My production CLI", AppConfig{},
v4.WithGracefulShutdown(), // SIGINT → reverse-order shutdown of all services
)
// Register a database service (lazy — created on first invoke)
v4.Provide(cli.Scope(), func(i do.Injector) (*Database, error) {
return &Database{DSN: "postgres://..."}, nil
})
// Use it in any command handler
v4.NewCommand("query", v4.NoFlags{},
func(ctx context.Context, cfg *AppConfig, _ v4.NoFlags) error {return db.Query(ctx) }, )
Services can implement `HealthCheck` (wired into `DoctorCommand`) and `Shutdown` (called on SIGINT/SIGTERM in reverse invocation order).
### Type-safe flags — validated at construction
**Raw Cobra — flags are strings, validated at runtime:**