clapfig
Rich, layered configuration for Rust CLI apps. Define a struct, point at your files, and go.
clapfig orchestrates configuration from multiple sources — config files, environment variables, and CLI flags — through a builder API that takes a few lines to set up. Built on confique for struct-driven defaults and commented template generation.
Features
- Struct as source of truth — define settings as a Rust struct with defaults and
///doc comments - Layered merge — defaults < config files < env vars < CLI flags, every layer sparse
- Multi-path file search — platform config dir, home, cwd, or any path, in precedence order
- Prefix-based env vars —
MYAPP__DATABASE__URLmaps todatabase.urlautomatically - Clap override — map individual clap args to config keys in one call each
- Strict mode — unknown keys in config files error with file path, key name, and line number (on by default)
- Template generation —
config genemits a commented sample config derived from the struct's doc comments - Config subcommand — drop-in
config gen|get|setcommands for clap - Persistence —
config setpatches values in place, preserving file comments
Quick Start
Define your config with confique's Config derive:
use Config;
use ;
Load it in one line:
use Clapfig;
That app_name("myapp") call sets sensible defaults:
- Searches for
myapp.tomlin the platform config directory - Merges env vars prefixed with
MYAPP__ - Fills in
#[config(default)]values for anything not provided
Setup
Defaults from app_name
| Derived setting | Value |
|---|---|
| File name | {app_name}.toml |
| Search paths | Platform config dir (via directories) |
| Env prefix | {APP_NAME} (uppercased) |
Builder methods
use ;
let config: AppConfig = builder
// Required — sets defaults for file_name, search_paths, env_prefix
.app_name
// Optional overrides
.file_name // override config file name
.search_paths // replace default search paths
.add_search_path // append a path without replacing
.env_prefix // override env var prefix
.no_env // disable env var loading entirely
.strict // disable strict mode (allow unknown keys)
.cli_override // override a key from a CLI arg
.load?;
Search Paths
use ;
let config: AppConfig = builder
.app_name
.search_paths
.load?;
Files load in order. Later paths override earlier ones. A myapp.toml in ./ overrides one in ~/.config/myapp/, which overrides compiled-in defaults.
If a file doesn't exist at a given path, it's silently skipped.
Strict Mode
Strict mode is on by default. If a config file contains a key that doesn't match any field in your struct, loading fails with a clear error including the file path, key name, and line number:
Unknown key 'typo_key' in /home/user/.config/myapp/myapp.toml (line 5)
Disable it with .strict(false) if you want to allow extra keys.
Environment Variables
With env prefix MYAPP, variables map via double-underscore nesting:
| Env var | Config key |
|---|---|
MYAPP__HOST |
host |
MYAPP__PORT |
port |
MYAPP__DATABASE__URL |
database.url |
MYAPP__DATABASE__POOL_SIZE |
database.pool_size |
__ (double underscore) separates nesting levels. Single _ within a segment is literal (part of the field name).
Disable env loading entirely with .no_env().
Clap Integration
CLI Overrides
use Parser;
cli_override(key, value) takes Option<V> where V: Into<toml::Value> — None (flags the user didn't pass) is silently skipped. Dot notation addresses nested keys. Names don't need to match: --db-url maps to database.url through the explicit mapping.
Supported value types: String, &str, i64, i32, i8, u8, u32, f64, f32, bool.
Config Subcommand
Add config management to your CLI by nesting clapfig::ConfigArgs:
use Subcommand;
use ;
This gives your users:
Template Generation
config gen produces a commented TOML file derived from your struct's /// doc comments:
# The host address to bind to.
# Default: "127.0.0.1"
#host = "127.0.0.1"
# The port number.
# Default: 8080
#port = 8080
[]
# Connection string URL.
#url =
# Connection pool size.
# Default: 10
#pool_size = 10
The template stays in sync with code — it's generated from the same struct. Change a doc comment or a default, the template reflects it.
Layer Precedence
Compiled defaults #[config(default = ...)]
↑ overridden by
Config files search paths in order, later paths win
↑ overridden by
Environment vars MYAPP__KEY
↑ overridden by
CLI overrides .cli_override()
Every layer is sparse. You only specify the keys you want to override. Unset keys fall through to the next layer down.
Persistence
config set <key> <value> writes to the primary config file (first resolved search path by default).
- If the file exists, the key is patched in place using
toml_edit, preserving existing comments and formatting. - If the file doesn't exist, a fresh config is created from the generated template with the target key set.
Full Example
use ;
use Config;
use ;
use ;
// -- Config struct --
// -- CLI --
// -- Main --