Dotenv-KMP
1.0.0indexedLoads and parses .env files with support for Original and extended Dotenvy dialects, offering variable interpolation, heredocs, optional command substitution, system-env override and string parsing.
Loads and parses .env files with support for Original and extended Dotenvy dialects, offering variable interpolation, heredocs, optional command substitution, system-env override and string parsing.
Kotlin Multiplatform Dotenv reader/parser library
A Kotlin Multiplatform library for loading and parsing `.env` files.
Supports two dialects: the widely-used Original format (compatible with motdotla/dotenv) and the extended Dotenvy format with variable interpolation and heredocs.
✔ Any PRs are welcome!
// build.gradle.kts
dependencies {
implementation("dev.mooner:dotenv-kmp:1.0.0")
}
val env = dotenv {
path = ".env"
}
val host = env["DB_HOST"] ?: "localhost"
val port = env.getOrDefault("DB_PORT", "5432")
val secret = env.getOrThrow("SECRET_KEY") // throws if missing
All options are set inside the dotenv { } block:
val env = dotenv {
path = "/etc/myapp/.env"
format = DotenvFormat.Dotenvy
overrideSystemEnv = true
ignoreIfMissing = true
}
// Parse from a string (useful in tests or when loading from a non-filesystem source)
val env = dotenv {
content = "KEY=value\nOTHER=123"
}
val env = dotenv()
env["KEY"] // String? — null if absent
env.getOrDefault("KEY", "fallback") // String
env.getOrThrow("KEY") // String — throws MissingKeyException if absent
"KEY" in env // Boolean
env.toMap() // Map<String, String>
env.size // Int
env.keys // Set<String>
Compatible with motdotla/dotenv. Use DotenvFormat.Original (default).
# Full-line comments
export EXPORT_PREFIX=ignored # 'export' keyword is stripped
UNQUOTED=hello world # trailing whitespace is trimmed
SINGLE='raw \n no escapes' # single-quotes: completely literal
DOUBLE="line1\nline2" # double-quotes: \n \r \t \\ \" supported
BACKTICK=`multi
line` # backtick: multiline, basic escapes
INLINE=value # this part ignored # inline comments after values
No variable interpolation — ${} and $VAR are kept as-is.
Extended format. Use DotenvFormat.Dotenvy.
Includes everything in Original, plus:
# Variable interpolation
BASE=/home/user
DERIVED=${BASE}/app # → /home/user/app
SHORT=$BASE/app # same, without braces
# Self-referential / chained interpolation
A=first
B=${A}-second # → first-second
# Extended escape sequences (double-quoted only)
UNICODE=
MISC=
SQL =
HOSTNAME=$(hostname)
Single-quoted values are always fully literal in both formats — no interpolation, no escapes.
All exceptions extend DotenvException:
try {
val env = dotenv { path = "missing.env" }
} catch (e: DotenvException.FileNotFoundException) {
println("Not found: ${e.path}")
}
Surfaced from shared tags and platforms — no rankings paid for.
| Target | File I/O | Command substitution |
|---|
| JVM | ✅ | ✅ |
| linuxX64 | ✅ | ✅ |
| macosX64 / macosArm64 | ✅ | ✅ |
| mingwX64 | ✅ | ❌ |
| Property | Type | Default | Description |
|---|
path | String | ".env" | Path to the .env file |
format | DotenvFormat | Original | Parsing dialect (Original or Dotenvy) |
overrideSystemEnv | Boolean | false | When true, .env values take precedence over system environment variables |
ignoreIfMissing | Boolean | false | When true, a missing file returns an empty Dotenv instead of throwing |
enableCommandSubstitution | Boolean | false | When true, $(command) expressions are executed (Dotenvy only) |
content | String? | null | Parse a string directly, bypassing all file I/O |
| Type | When thrown |
|---|
DotenvException.FileNotFoundException | File not found and ignoreIfMissing is false |
DotenvException.ParseException | Malformed input |
DotenvException.MissingKeyException | getOrThrow() called for an absent key |
DotenvException.CommandSubstitutionException | $(command) execution fails |