Fully Typed
Load[T] returns your exact struct — not map[string]interface{}. Types checked at compile time. No casting, no panics.
Load from YAML, env, JSON, TOML, Vault, AWS, or Kubernetes. Validate with struct tags. Redact secrets automatically. Human-readable errors, not stack traces.
go get github.com/MimoJanra/confkit Glissez à droite — la vitrine défile.
Load[T] returns your exact struct — not map[string]interface{}. Types checked at compile time. No casting, no panics.
Rules in struct tags: validate:"required,min=1,max=65535". No extra config files. Custom validators per load call.
Know which field failed, which rule, and which source. Explain(err) gives actionable messages — not cryptic stack traces.
Tag any field secret:"true". Automatically redacted in errors, dumps, and logs. No secrets ever leak.
YAML, env, JSON, TOML, flags, Kubernetes, Vault, AWS — in explicit priority order. First source per field wins.
Only yaml.v3 + go-toml in core. Cloud integrations are optional modules — pull only what you need.
Define your struct once. Defaults and validation live in the tags.
go get github.com/MimoJanra/confkit
Annotate fields with env, default, validate, and secret tags.
confkit.Load[T](...)Pass sources in priority order. Get back your typed struct or a clear error.
Explain(err)One call gives a human-readable message safe to log.Fatal — secrets redacted.
type Config struct {
Host string `env:"HOST" default:"localhost"`
Port int `env:"PORT" default:"8080" validate:"min=1,max=65535"`
Timeout time.Duration `env:"TIMEOUT" default:"30s"`
DB struct {
DSN string `env:"DSN" validate:"required" secret:"true"`
MaxConns int `env:"MAX_CONNS" default:"10" validate:"min=1,max=100"`
} `prefix:"DB_"`
}
cfg, err := confkit.Load[Config](
confkit.FromFlags(),
confkit.FromEnv(),
confkit.FromYAML("config.yaml"),
)
if err != nil {
log.Fatal(confkit.Explain(err))
}type Config struct {
Server struct {
Addr string `env:"ADDR" default:":8080"`
TLS bool `env:"TLS" default:"false"`
}
Database struct {
URL string `env:"URL" validate:"required" secret:"true"`
MaxConns int `env:"MAX_CONNS" default:"10"`
}
}
cfg, err := confkit.Load[Config](confkit.FromEnv()) // SERVER_ADDR=:3000 // DATABASE_URL=postgres://user:pass@localhost/db // DATABASE_MAX_CONNS=20
type Config struct {
Verbose bool `flag:"verbose" short:"v"`
Output string `flag:"output" short:"o" default:"stdout"`
InputDir string `flag:"input" validate:"required"`
}
cfg, err := confkit.Load[Config](confkit.FromFlags()) // ./mytool -v -o report.txt --input /dataimport "github.com/MimoJanra/confkit/vault"
type Config struct {
API struct {
Key string `validate:"required" secret:"true"`
Secret string `validate:"required" secret:"true"`
}
}
auth := vault.VaultTokenAuth(os.Getenv("VAULT_TOKEN"))
cfg, err := confkit.Load[Config](
vault.FromVault("https://vault.example.com", auth, "/secret/myapp"),
)// Priority: env → env-specific YAML → defaults
cfg, err := confkit.Load[Config](
confkit.FromEnv(),
confkit.FromYAML("config."+os.Getenv("ENV")+".yaml"),
confkit.FromYAML("config.defaults.yaml"),
) // ENV=prod → config.prod.yaml // ENV=dev → config.dev.yaml // Fallback: config.defaults.yaml
confkit gives you typed config with validation, defaults, and safe error messages — all from a single struct definition.
| Feature | confkit | Viper | envconfig | koanf |
|---|---|---|---|---|
Typed Load[T] | ✓ | ✗ | ⚠ | ✗ |
| Defaults via struct tags | ✓ | ⚠ | ✓ | ✗ |
| Built-in validation rules | ✓ | ✗ | ✗ | ✗ |
| Secret redaction | ✓ | ✗ | ✗ | ✗ |
| Multi-source merging | ✓ | ✓ | ⚠ | ✓ |
| Lightweight core | ✓ | ✗ | ✓ | ✓ |
| Cloud integrations | optional | bundled | — | optional |
| Runtime hot reload | ✓ | ✓ | ✗ | ⚠ |
you need heavy runtime reloading with watches across many files and don't need validation or type safety.
you only care about environment variables and simple type conversion — nothing else.
you want extreme modularity and don't need validation, secret redaction, or typed loading.
you want one struct for all config, built-in validation, safe error messages, and optional cloud sources.
Built-in sources cover the common cases. Cloud integrations are optional modules — each a separate go get.
Rules are comma-separated: validate:"required,min=1,max=65535"
| Rule | Types | Behaviour |
|---|---|---|
required | any | Non-zero value required |
min=N | int, float | Value ≥ N |
min=N | string | Length ≥ N characters |
max=N | int, float | Value ≤ N |
max=N | string | Length ≤ N characters |
oneof=a b c | string | Must equal one option |
email | string | Valid email address |
http_url | string | Valid HTTP/HTTPS URL |
ip, ipv4, ipv6 | string | Valid IP |
uuid | string | Valid UUID v1–v5 |
port | int, string | Port 1–65535 |
regex=pattern | string | Must match regexp |
env:"VAR_NAME"Read from environment variable
flag:"flag-name"Read from CLI flag --flag-name
default:"value"Use when no source provides a value
validate:"rules"Validation rules, comma-separated
secret:"true"Redact in errors, dumps & logs
prefix:"PREFIX_"Prepend to env names in nested struct
help:"description"Shown in schema and CLI help
short:"f"Single-character short flag -f
Pas de boilerplate. Pas de panics au runtime. Pas de fuites de secrets.