Config seams
The Resolver and OutputCodec interfaces, and the .env helpers.
The core keeps two small interfaces as its only extension seams, so file config and output formats never pull dependencies into it. The .env helpers are standalone.
Resolver
type Resolver interface {
// Resolve overlays this resolver's layer onto values, the map accumulated by
// earlier resolvers in the chain, and returns it. cmd is the command path
// (space-joined, e.g. "db migrate"). The first resolver receives an empty map.
Resolve(cmd string, values map[string]any) (map[string]any, error)
}Contributes a layer of values to a command's config before Run. Resolvers compose like middleware, each overlaying its layer on the map the previous one produced. The framework runs them in registration order, then folds in the environment, then overlays flags. File-backed resolution lives in the config sub-package and satisfies this interface structurally, so the core never imports it.
OutputCodec
type OutputCodec interface {
// Marshal encodes v into bytes.
Marshal(v any) ([]byte, error)
// Extension returns the file extension for this codec (e.g. ".yml").
Extension() string
}Renders help output for a custom --help-format value. It is satisfied structurally by the yaml, toml, and json config addon codecs, so registering one never pulls an encoding library into the core. The format name a user types comes from Extension with the leading dot trimmed.
.env helpers
func LoadDotEnv(paths ...string) errorReads .env files and sets environment variables that are not already set. With no arguments it loads .env from the working directory, and it silently skips files that do not exist.
func GetDotEnv(file string) (map[string]string, error)
func GetDotEnvs(files ...string) (map[string]string, error)Parse .env files into a map without touching the process environment. GetDotEnv reads one file, and GetDotEnvs merges several, where an earlier file takes precedence. Both return ErrDotenvNotFound for a missing file.