Skip to content

Syntax & Directives

All dotenv-fusion directives start with #@ to remain compatible with standard dotenv loaders.

Quick reference

Directive Purpose Example
#@import Import another file #@import database.env prefix=DB_
#@schema Load an external contract #@schema application.env-schema
#@def Define variable constraints #@def PORT type=int default=3000
#@if Conditional block #@if ${ENV} == production
#@ifdef Test if variable exists #@ifdef CI
#@ifndef Test if variable doesn't exist #@ifndef LOCAL
#@else Alternative block #@else
#@endif Close conditional #@endif
#@mode Change processing modes #@mode override=true strict=true

Variable expansion

# Basic syntax
BASE_URL=https://api.example.com
API_URL=${BASE_URL}/v1

# Default values
PORT=${PORT:-3000}

# System environment
HOME_DIR=${HOME}/app

Syntax: ${VAR}, $VAR, ${VAR:-default}

Import directive

# Simple import
#@import database.env

# With prefix
#@import database.env prefix=DB_

# Optional (no error if missing)
#@import .env.local mode=ifexist

# Override existing values
#@import overrides.env override=true

# Dynamic paths
#@import configs/${ENV}.env

Conditionals

# If/else
#@if ${ENV} == production
LOG_LEVEL=error
#@else
LOG_LEVEL=debug
#@endif

# Existence check
#@ifdef CI
CI_MODE=true
#@endif

#@ifndef LOCAL
REMOTE=true
#@endif

Operators: ==, !=, >, <, >=, <=

Variable definitions

# Type system
#@def PORT type=int default=3000
#@def DEBUG type=bool default=false
#@def TAGS type=list
#@def CONFIG type=json
#@def ENV type=enum values=development,staging,production

# Numeric and length constraints
#@def PORT type=int min=1 max=65535
#@def APP_NAME type=str nonempty=true min_length=3 max_length=80

# Local URL validation (no network request or DNS lookup)
#@def API_URL type=str format=url schemes=https

# Validation
#@def EMAIL validate=^[\w.-]+@[\w.-]+\.\w+$

# Required variables
#@def API_KEY required=true

# Secrets (masked in verbose mode)
#@def TOKEN secret=true

# Override a false positive from name-based secret detection
#@def PUBLIC_KEY secret=false

# Lazy variables (kept as ${VAR} in fuse output)
#@def EXTERNAL_TOKEN lazy=true

# Documentation
#@def PORT doc="HTTP listening port"

# Secret sourced from a key in an age-encrypted dotenv bundle
#@def DB_PASSWORD required=true source="age://store/database.env.age#PASSWORD"

Types: int, float, bool, str, list, json, enum

Options: type, default, required, validate, secret, lazy, source, doc, values, min, max, nonempty, min_length, max_length, format, schemes. secret=true forces masking, secret=false disables automatic detection for that variable, and omitting the option keeps name-based detection enabled.

Definitions can stay inline or move to a dedicated schema:

.env-fuse
#@schema application.env-schema
PORT=8080
application.env-schema
PORT type=int min=1 max=65535 required=true

See Define a Shared Schema for the schema grammar, imports, duplicates, confinement, and migration.

source= makes the variable secret and obtains its value from a backend. The first available backend is age:

# Explicit selector
#@def DB_USERNAME source="age://store/database.env.age#USERNAME"

# Without a fragment, the final variable name is the selector
#@def DB_PASSWORD source="age://store/database.env.age"

A sourced definition cannot also use an inline assignment, default=, lazy=true, or secret=false. Variables derived from a source are secret and masked transitively. Sources are not available to #@import paths or conditional directives because resolution happens after the configuration structure is built.

See Get Started with age for store configuration and execution.

Quote behavior

# Double quotes: expansion + escape sequences
MESSAGE="Hello ${NAME}\nWelcome"

# Single quotes: literal (no expansion)
PATTERN='${NOT_EXPANDED}'

# No quotes: expansion + comments removed
DEBUG=true  # Comment removed

Processing modes

# Enable override mode: later definitions override earlier ones
#@mode override=true

# Enable strict mode: undefined variables cause errors
#@mode strict=true

# Combine both on one line
#@mode override=true strict=true

# Reset to defaults
#@mode override=false strict=false

Available modes:

  • override=true/false - When true, variable definitions override existing values (default: no, first-wins)
  • strict=true/false - When true, undefined variables raise errors instead of becoming empty (default: no)

By default, undefined variables become empty strings and first definition wins.


→ See CLI Commands for detailed documentation and all options.