Skip to content

JohnTitor/dotenvor

Repository files navigation

dotenvor

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).

Highlights

  • Fast parser for common .env syntax
  • 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 .env files
  • First-party dotenv CLI (dotenv run ...)
  • Process-env or in-memory targets for safer tests
  • Quiet/verbose logging controls

Installation

[dependencies]
dotenvor = "0.1"

MSRV

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.

Quick Start

safe load (in-memory)

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.

process-env load (unsafe)

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().

Attribute macro startup 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<_, _>.

Multi-environment stack convention

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

Parse only

use dotenvor::parse_str;

let entries = parse_str("A=1\nB=\"hello\"\n")?;
assert_eq!(entries.len(), 2);
# Ok::<(), dotenvor::Error>(())

CLI: run a command with dotenv files

cargo run --bin dotenv -- run -- printenv DATABASE_URL

Select files explicitly (repeat -f or use comma-separated paths):

cargo run --bin dotenv -- run -f ".env.local,.env" -- my-app

Useful 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

Opt in to permissive key parsing

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>(())

Implemented Behavior

Parsing

  • KEY=VALUE pairs
  • 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 export prefix
  • 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

Loading

  • Multi-file loading with deterministic precedence
  • Convention helper for environment stacks (.convention("development"))
  • override_existing(false) by default
  • EnvLoader::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 enabled
    • EnvLoader: upward search disabled by default (enable with .search_upward(true))
  • Missing-file mode
    • required(true) (default): missing files return Error::Io
    • required(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 .env when no file is selected
    • Accepts -f/--file for file selection (repeatable and comma-separated)
    • Supports -o/--override and -i/--ignore

Substitution

  • 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

Logging

  • .verbose(true) enables loader diagnostics on stderr
  • .quiet(true) suppresses diagnostics

License

Licensed under either of:

at your option.

About

A small, fast .env parser and loader for Rust.

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

 
 
 

Contributors

Languages