Generate a .env File¶
Compile .env-fuse files (with directives) into standard .env format.
Why generate a file?¶
Tools like VS Code, Docker Compose, and deployment CLIs can't read directives like #@import or #@if. They need a flat file with KEY=value lines, but their exact parsing rules are not universal.
Compile the configuration¶
# .env-fuse (source with directives)
APP_NAME=MyApp
#@import configs/database-${ENV}.env
#@import secrets/${REGION}/keys.env
#@if ${ENV} == production
LOG_LEVEL=error
CACHE_TTL=3600
#@else
LOG_LEVEL=debug
CACHE_TTL=60
#@endif
# Result: .env (default dotenv dialect)
APP_NAME="MyApp"
DB_HOST="prod-db-eu.example.com"
DB_PORT="5432"
API_KEY="sk-..."
LOG_LEVEL="error"
CACHE_TTL="3600"
The default output targets dotenv-aware consumers such as Docker Compose and VS Code. Select the Docker dialect for docker run --env-file.
Build-time variables¶
Use --var to generate different configs from one source:
# Development
dotenv-fusion fuse --var ENV=dev --var REGION=eu -o .env.dev
# Production EU
dotenv-fusion fuse --var ENV=prod --var REGION=eu -o .env.prod-eu
# Production US
dotenv-fusion fuse --var ENV=prod --var REGION=us -o .env.prod-us
Build-time variables (--var) are used only for resolving imports and evaluating conditions—they're not written to the output.
Use cases¶
💻 Local Development Compile .env-fuse so VS Code auto-loads your config without plugins.
🚀 CI/CD Pipelines Generate environment-specific .env files during build: one source → dev, staging, prod configs.
🐳 Container Deployment Docker Compose can use the default dialect. Generate a raw Docker dialect for docker run --env-file.
🏢 Multi-Tenant SaaS One .env-fuse template → hundreds of tenant-specific configs with --var TENANT_ID=....
→ See Workflows for tool integrations and Examples for complete configurations.
Command overview¶
# Basic compilation
dotenv-fusion fuse # .env-fuse → .env
dotenv-fusion fuse -f .env-fuse.prod # Custom source
dotenv-fusion fuse -o .env.production # Custom output
# With build-time variables
dotenv-fusion fuse --var ENV=prod # Single variable
dotenv-fusion fuse --var ENV=prod --var REGION=eu # Multiple variables
dotenv-fusion fuse -V ENV=prod -V REGION=eu # Short form
dotenv-fusion fuse --dialect docker -o .env.docker # docker run --env-file
# Compile and emit shell exports
eval "$(dotenv-fusion fuse --load)" # Compile + export via eval
eval "$(dotenv-fusion fuse --load --var ENV=dev)" # With variables
# Output and review options
dotenv-fusion fuse --stdout # Print to stdout
dotenv-fusion fuse --dry-run # Preview without writing
dotenv-fusion fuse --diff # Show redacted diff; exits 1 on drift
dotenv-fusion fuse -o .env.production # Explicit plaintext artifact
dotenv-fusion fuse --strip-comments # No header comments
dotenv-fusion fuse --load --no-override # Preserve existing env vars
dotenv-fusion fuse -v # Verbose mode
# Search parent directories
dotenv-fusion fuse --walk # Search 1 parent (default)
dotenv-fusion fuse --walk-up 3 # Search up to 3 parents
Output dialects¶
fuse keeps its historical quoted output as the default dotenv dialect. This is compatible with dotenv parsers that remove quotes, including Docker Compose.
docker run --env-file uses a different, raw line parser: quotes and backslashes are literal and no interpolation or escape processing occurs. Use an explicit artifact for that consumer:
The Docker dialect preserves spaces, quotes, #, backslashes, dollar signs, and empty values as raw text. It rejects newline characters and NUL bytes because a line-delimited Docker environment file cannot represent them.
Review before writing¶
Use --dry-run to verify what would be compiled without creating or changing any file:
Use --diff in CI to detect drift between .env-fuse and the generated .env artifact. It exits 0 when the target is up to date and 1 when a change is detected. All values from the existing file are redacted because their secret provenance is unknown. New public values remain visible; new secret values are redacted. With source-backed configurations, all new values are also redacted. The check compares content deterministically; it does not infer freshness from file modification times.
Secret sources¶
If the source graph contains #@def ... source=, fuse resolves and validates the secrets before writing the compiled plaintext:
--stdout emits compiled plaintext and --load emits shell exports after writing the file, including resolved secrets. Use dotenv-fusion exec -- ... when you want to pass values directly to an application without creating a dotenv file. --age-identity PATH is repeatable when explicit identities are needed.
Both review modes remain available:
The dry run performs source resolution but writes and prints no value. The diff redacts every assignment value because the previous artifact's secret provenance may no longer be available. Its usual exit status remains 0 for no drift and 1 for drift.
File naming¶
Standard naming convention:
| Source | Compiled |
|---|---|
.env-fuse | .env |
.env-fuse.local | .env.local |
.env-fuse.production | .env.production |
.env-fuse.development | .env.development |
Output permissions¶
On POSIX systems, fuse creates a new output file with mode 0600. When the output already exists, its current permissions are preserved, including modes such as 0640 or 0644. This also applies to files containing resolved secrets.
Variable priority¶
When resolving variables during compilation:
- Build-time variables (
--var) - highest priority - Variables in
.env-fusefiles - System environment variables
- Default values (
${VAR:-default})
Automatic input selection¶
The load command selects the first existing input in its load order:
# Loads .env-fuse, then .env-fuse.local, then .env
eval "$(dotenv-fusion load)"
# Promote .env without removing the other fallbacks
eval "$(dotenv-fusion load --load-order=env)"
# With compilation variables
eval "$(dotenv-fusion load --var ENV=prod --var REGION=eu)"
Default priority: .env-fuse → .env-fuse.local → .env