A modern .env file parser and loader for Mojo, compatible with Mojo 2025/2026.
Status: ✅ Production-ready - Advanced features, near-100% python-dotenv compatibility
mojo-dotenv loads environment variables from .env files into your Mojo applications.
from dotenv import load_dotenv, dotenv_values
from os import getenv
fn main() raises:
# Option 1: Load .env file into environment
if load_dotenv(".env"):
var db_url = getenv("DATABASE_URL")
print("Connecting to:", db_url)
# Option 2: Parse without modifying environment (with safe key access)
var config = dotenv_values(".env")
print("Port:", config.get("PORT", "8080")) # Default to 8080 if not setThis project was inspired by mojoenv by itsdevcoffee, which pioneered .env support in Mojo. However, mojoenv was built for Mojo in 2023 and is no longer compatible with modern Mojo syntax and stdlib.
mojo-dotenv is a complete rewrite using current Mojo patterns (2025/2026), with:
- ✅ Modern Mojo syntax and stdlib
- ✅ Comprehensive tests against python-dotenv
- ✅ Clear documentation and examples
- ✅ Production-ready error handling
- Parse
KEY=valuepairs - Handle comments (
#lines and inline comments) - Handle quotes (
"value",'value') - Strip whitespace
- Load into environment (
load_dotenv()) - Return
Dict[String, String](dotenv_values()) - Variable expansion (
${VAR}and$VARsyntax) - Multiline values (quoted strings spanning lines)
- Escape sequences (
\n,\t,\",\\,\') - Export prefix support (
export KEY=value) -
find_dotenv()- automatic .env file discovery - Keys without
=(returns empty string) - Verbose mode for debugging
- 98%+ compatibility with python-dotenv
- Comprehensive test suite (49 tests across 11 test files)
- Multiple .env files with precedence
- Stream input support
- Custom encoding options
See docs/planning/PLAN.md for detailed roadmap.
Choose the installation method that best fits your workflow:
Easiest method using the official modular-community channel.
# Add modular-community channel to your pixi.toml
[project]
channels = [
"conda-forge",
"https://conda.modular.com/max",
"https://repo.prefix.dev/modular-community"
]
# Install mojo-dotenv
pixi add mojo-dotenvStatus: PR #192 in review. Once merged, this will be the preferred installation method.
Best for version-controlled projects with easy updates.
# Add to your project
cd your-project
git submodule add https://github.com/databooth/mojo-dotenv vendor/mojo-dotenv
# Use in your code
mojo -I vendor/mojo-dotenv/src your_app.mojo
# Update to latest version
git submodule update --remote vendor/mojo-dotenvSimplest method for quick projects.
# Clone and copy source
git clone https://github.com/databooth/mojo-dotenv
cp -r mojo-dotenv/src/dotenv your-project/lib/dotenv
# Use in your code
mojo -I your-project/lib your_app.mojoPre-compiled packages available from GitHub Releases.
# Download from releases
curl -L -o dotenv.mojopkg https://github.com/databooth/mojo-dotenv/releases/latest/download/dotenv.mojopkg
# Use in your code
mojo -I . your_app.mojo # Ensure dotenv.mojopkg is in import path.mojopkg files are tied to specific Mojo versions. Check the release notes for compatibility. Source installation is recommended for maximum compatibility.
See docs/DISTRIBUTION.md for detailed installation guides and advanced options.
git clone https://github.com/databooth/mojo-dotenv
cd mojo-dotenv
pixi install
pixi run test-allfrom dotenv import dotenv_values, load_dotenv
from os import getenv
fn main() raises:
# Parse .env file without setting environment variables
var config = dotenv_values(".env")
# Use .get() for safe key access with defaults
print("Database:", config.get("DATABASE_URL", "localhost"))
# Load .env file and set environment variables
if load_dotenv(".env"):
print("API Key:", getenv("API_KEY"))Parse a .env file and return its content as a dictionary. Does NOT modify environment variables.
Parameters:
dotenv_path: Path to .env file (absolute or relative)verbose: Print debug information during parsing (default: False)
Returns: Dictionary mapping variable names to values
Example:
var config = dotenv_values("config/.env")
# Iterate through all values
for item in config.items():
print(item.key, "=", item.value)
# Safe key access with defaults
var db_url = config.get("DATABASE_URL", "localhost:5432")
var port = config.get("PORT", "8080")Load variables from a .env file into the environment.
Parameters:
dotenv_path: Path to .env fileoverride: If True, override existing environment variables (default: False)verbose: Print debug information during loading (default: False)
Returns: True if successful, False if file not found
Example:
if load_dotenv(".env"):
print("Loaded successfully")find_dotenv(filename: String = ".env", raise_error_if_not_found: Bool = False, usecwd: Bool = False) -> String
Search for a .env file by traversing parent directories.
Parameters:
filename: Name of .env file to search for (default: ".env")raise_error_if_not_found: Raise error if file not found (default: False)usecwd: Start search from current directory instead of file's directory (default: False)
Returns: Path to .env file, or empty string if not found
Example:
var env_path = find_dotenv()
if len(env_path) > 0:
_ = load_dotenv(env_path)mojo-dotenv maintains 98%+ compatibility with python-dotenv. The main difference is in how missing environment variables are handled:
Environment variable access:
# Python: os.getenv() returns None for missing variables
import os
value = os.getenv("MISSING_VAR") # Returns None
print("Value:", value) # Prints: Value: None# Mojo: os.getenv() returns empty string for missing variables
from os import getenv
var value = getenv("MISSING_VAR") # Returns ""
print("Value:", value) # Prints: Value: This is a difference in the underlying standard libraries, not in mojo-dotenv itself. Both load_dotenv() and dotenv_values() behave identically to python-dotenv.
Best practice: Always check if load_dotenv() succeeded before accessing environment variables:
if load_dotenv(".env"):
var api_key = getenv("API_KEY")
# Use api_keySupported syntax:
# Full-line comments
KEY=value
QUOTED="value"
SINGLE='value'
EMPTY=
SPACES= value # Inline comments supported
KEY_WITH_EQUALS=value=with=equals
# Export prefix (stripped automatically)
export DATABASE_URL=postgresql://localhost
# Variable expansion
BASE_DIR=/home/user
DATA_DIR=${BASE_DIR}/data
LOG_FILE=$BASE_DIR/app.log
# Escape sequences (in quoted strings only)
MULTILINE="Line 1\nLine 2\nLine 3"
TABS="Col1\tCol2\tCol3"
QUOTE="He said \"hello\""
PATH="C:\\\\Users\\\\name"
# Multiline values (quoted strings can span lines)
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAAS
-----END PRIVATE KEY-----"
# Keys without values
KEY_WITHOUT_VALUEmojo-dotenv/
├── src/dotenv/ # Source code
├── tests/ # Tests
├── examples/ # Examples
├── docs/ # Documentation
│ └── planning/ # Project planning docs
└── README.md # This file
- Mojo 2025/2026 (via pixi)
- Python 3.10+ (for testing against python-dotenv)
# Clone repository
git clone https://github.com/databooth/mojo-dotenv
cd mojo-dotenv
# Install dependencies
pixi install
# Run tests
pixi run test # Basic tests
pixi run test-compat # Python compatibility tests
pixi run test-load # load_dotenv tests
pixi run test-all # All tests
# Run example
pixi run example-simple- docs/planning/PLAN.md - Detailed project plan and roadmap
- CREDITS.md - Acknowledgments and project history
- Building mojo-dotenv - Blog post: lessons from building the package
- docs/DISTRIBUTION.md - Packaging and distribution guide
- docs/MOJO_PACKAGE_MANAGEMENT.md - Mojo packaging ecosystem overview
- docs/RESEARCH.md - python-dotenv API analysis and testing
- docs/MOJOENV_COMPATIBILITY_ANALYSIS.md - mojoenv compatibility findings
Contributions welcome! This is an open-source project (MIT License).
- Report bugs or request features
- Improve documentation
- Add test cases
- Implement features
- Review code
This project is sponsored by DataBooth — Data analytics consulting for medium-sized businesses.
DataBooth transforms raw data into actionable strategies that drive growth, reduce costs, and manage emerging risks. Bringing risk expertise refined through quantitative finance, regulatory roles (APRA/ASIC), and hands-on AI development to help organisations make informed, data-driven decisions.
Need help with data analytics, risk management, or evaluating Mojo for your infrastructure? Let's talk.
This project builds on excellent prior work:
- python-dotenv by Saurabh Kumar - Reference implementation and compatibility target. We validate against python-dotenv 1.2.1 and maintain 98%+ compatibility.
- mojoenv by itsdevcoffee - Pioneer of
.envsupport in Mojo (2023). Inspired this modern rewrite. - Modular Team - For creating the Mojo programming language
See CREDITS.md for detailed acknowledgments and project history.
MIT License - See LICENSE for details.