| Crates.io | clap-config-file |
| lib.rs | clap-config-file |
| version | 0.6.0 |
| created_at | 2025-01-27 16:40:44.702573+00 |
| updated_at | 2025-09-23 12:05:49.401213+00 |
| description | A proc macro for adding config file support to clap |
| homepage | |
| repository | https://github.com/bodo-run/clap-config-file |
| max_upload_size | |
| id | 1532586 |
| size | 109,316 |
ClapConfigFileUse a single struct for both CLI and config file.
Consider you have a CLI tool that accepts a series of arguments:
my-tool --port 8080 --debug --database-url="sqlite://mem.db"
And you want to be able to specify a configuration file to make it easier to run the tool:
# my-tool.yaml
port: 8080
debug: true
database_url: sqlite://mem.db
After integrating ClapConfigFile, your tool will be able to load the config file automatically:
my-tool --port 4242 # still possible to provide CLI arguments
# my-tool now will get the rest of the config from the "my-tool.yaml" file
use clap_config_file::ClapConfigFile;
#[derive(ClapConfigFile, Debug)]
#[config_file_name = "my-tool"]
#[config_file_formats = "yaml,toml,json"]
struct AppConfig {
// Available in both CLI & config, with CLI override by default
#[config_arg(default_value = "8080")]
pub port: u16,
// CLI-only. A field in config is ignored.
#[config_arg(accept_from = "cli_only")]
pub cli_secret: String,
// Config-only. CLI flag is ignored.
#[config_arg(accept_from = "config_only")]
pub database_url: String,
// Example of a multi-value field, merged from config and CLI.
// e.g. --ignored-files foo.txt --ignored-files bar.txt
#[config_arg(multi_value_behavior = "extend")]
pub ignored_files: Vec<String>,
// Example of a multi-value field, CLI overwrites config.
#[config_arg(multi_value_behavior = "overwrite")]
pub overwrite_list: Vec<String>
}
fn main() {
// Provide a default config file name (e.g., "my-tool").
// This will be used in file discovery unless `--config-file` or `--no-config` is set.
let (config, used_file, format) = AppConfig::parse_info();
println!("Config: {:?}", config);
}
Now it's possible to run the tool with the config file:
my-tool --port 4242
Config: AppConfig { port: 4242, cli_secret: "", database_url: "sqlite://mem.db", ignored_files: [], overwrite_list: [] }
Use these attributes on your struct fields to control sources and behaviors:
#[config_arg(accept_from = "cli_only")]
#[config_arg(accept_from = "config_only")]
#[config_arg(accept_from = "cli_and_config")] (default)
#[config_arg("arg_name", ...)]
#[clap(...)])#[config_arg(multi_value_behavior = "extend" | "overwrite")]
Vec<T> fieldsextend merges config and CLI-supplied itemsoverwrite replaces config items if CLI has any valuesStruct Attributes
#[config_file_name = "my-tool"]
#[config_file_formats = "yaml,toml,json"]
These flags are automatically added to the CLI parser:
--config-file <FILE>
<FILE> directly--no-config
--help
my-tool.yaml, my-tool.json) exist in the same directory, the crate exits with an error.config_only field is not found in the file, or if the user omits a required CLI field, an error is reported.my-tool.yaml is invalid YAML syntax, the crate reports a parse error.--no-config is given, in which case it's valid if the user provides enough CLI arguments).By default, if you provide "my-tool" as the file name using config_file_name:
my-tool.yaml, my-tool.toml, or my-tool.json exist (or whatever formats you specified in config_file_formats).