dotenvor is a small, fast .env parser and loader for Rust.
It focuses on predictable behavior, low dependency overhead, and an ergonomic API (EnvLoader + convenience functions).
- Fast parser for common
.envsyntax - Builder-style loader with multi-file precedence
- Built-in multi-environment stack helper (
.convention("development")) - Optional variable substitution (
$VAR,${VAR},${VAR:-fallback}) - Optional upward search for
.envfiles - First-party
dotenvCLI (dotenv run ...) - Process-env or in-memory targets for safer tests
- Quiet/verbose logging controls
[dependencies]
dotenvor = "0.1"The minimum supported Rust version (MSRV) is Rust 1.88.0+. We don't treat MSRV changes as breaking, it may be changed in any release.
use dotenvor::EnvLoader;
let env = EnvLoader::new().load()?.env;
println!("DATABASE_URL={:?}", env.get("DATABASE_URL"));
# Ok::<(), dotenvor::Error>(())EnvLoader::load() is safe and returns an in-memory map.
Use builder options (.path(...), .required(false), etc.) when needed.
use dotenvor::dotenv;
let report = unsafe { dotenv()? };
println!("loaded={} skipped={}", report.loaded, report.skipped_existing);
# Ok::<(), dotenvor::Error>(())dotenv() mutates process-wide state via std::env::set_var and is unsafe,
because callers must guarantee no concurrent process-environment access.
In concurrent code or isolated tests, prefer EnvLoader::load().
#[dotenvor::load]
fn main() -> Result<(), dotenvor::Error> {
Ok(())
}Or, you can specify options:
#[dotenvor::load(path = ".env", required = true, override_existing = false, search_upward = false)]
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), dotenvor::Error> {
println!("inside async runtime");
Ok(())
}#[dotenvor::load] injects the same process-env loading flow before the function runs.
The function must return Result<_, _>.
use dotenvor::EnvLoader;
let loaded = EnvLoader::new()
.convention("development")
.required(false)
.load()?;
println!("loaded={}", loaded.report.loaded);
# Ok::<(), dotenvor::Error>(())Convention precedence (highest to lowest):
.env.development.local.env.local.env.development.env
use dotenvor::parse_str;
let entries = parse_str("A=1\nB=\"hello\"\n")?;
assert_eq!(entries.len(), 2);
# Ok::<(), dotenvor::Error>(())cargo run --bin dotenv -- run -- printenv DATABASE_URLSelect files explicitly (repeat -f or use comma-separated paths):
cargo run --bin dotenv -- run -f ".env.local,.env" -- my-appUseful flags:
-o,--override: let file values override existing environment variables-i,--ignore: skip missing files-u,--search-upward: resolve relative files by walking parent directories
use dotenvor::{parse_str_with_mode, KeyParsingMode};
let entries = parse_str_with_mode(
"KEYS:CAN:HAVE_COLONS=1\n%TEMP%=/tmp\n",
KeyParsingMode::Permissive,
)?;
assert_eq!(entries.len(), 2);
# Ok::<(), dotenvor::Error>(())KEY=VALUEpairs- Whitespace trimming around keys and values
- Empty values (
FOO=) - Comments with
#outside quotes - Single quotes, double quotes, and backticks
- Double-quoted escapes:
\n,\r,\t,\\,\" - Optional
exportprefix - Duplicate keys: last value wins
- Reader, string, and bytes parsing APIs
- Multiline quoted values (including PEM-style blocks)
- Strict key mode by default, plus opt-in
KeyParsingMode::Permissive
- Multi-file loading with deterministic precedence
- Convention helper for environment stacks (
.convention("development")) override_existing(false)by defaultEnvLoader::load()is safe and returns a memory map + report- Process-env loading is available via unsafe APIs (
dotenv,from_path,from_paths,from_filename,EnvLoader::load_and_modify) - Upward file search support
dotenv()/from_filename(...): upward search enabledEnvLoader: upward search disabled by default (enable with.search_upward(true))
- Missing-file mode
required(true)(default): missing files returnError::Iorequired(false): missing files are skipped silently
- Configurable file decoding via
.encoding(...)Encoding::Utf8(default)Encoding::Latin1(ISO-8859-1)
- CLI command execution (
dotenv run)- Defaults to
.envwhen no file is selected - Accepts
-f/--filefor file selection (repeatable and comma-separated) - Supports
-o/--overrideand-i/--ignore
- Defaults to
- Optional mode:
SubstitutionMode::Expand - Expands
$VAR,${VAR}, and${VAR:-fallback}(strict key mode) - Supports chained and forward references
- Falls back to current target environment values when needed
- Treats single-quoted values and escaped dollars (
\$) as literal in expand mode
.verbose(true)enables loader diagnostics on stderr.quiet(true)suppresses diagnostics
Licensed under either of:
- MIT license (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
at your option.