Config that fits your application.
dotcfg handles where configuration lives, how it is encoded, and how you read it — without forcing one directory strategy or one access pattern.
Start with the format you need.
[dependencies]
dotcfg = "0.3.0"
serde = { version = "1", features = ["derive"] }Published release: 0.3.0. Explore more on the examples page.
Load a typed Rust configuration.
use dotcfg::DotCfg;use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Default)]struct Config { username: String, port: u16,} fn main() -> Result<(), Box<dyn std::error::Error>> { let cfg = DotCfg::new("mytool"); cfg.save(&Config { username: "tayo".into(), port: 8080 })?; let config: Option<Config> = cfg.load()?; Ok(())}Use a dot directory, XDG, an exact custom path, or discover project config from ancestors.
Read guide →Multiple formatsTOML by default, with feature-gated JSON and YAML support.
Read guide →Typed key accessRead and write individual values as Rust types without replacing the whole config.
Read guide →Environment overridesLayer environment variables over file configuration for CLI and deployment workflows.
Read guide →Common things you’ll do with config.
Load configuration optionally, require it, or create defaults.
Read and write numbers, booleans, strings, and nested values without flattening your config.
Move from the default dot directory to XDG, a custom directory, or ancestor discovery.
Need the full API?
Every method, type, and error is in the Rust reference.