beginner3 minutesevnx v0.2.1+

evnx diff

Reference documentation for the evnx diff command: compare .env and .env.example with auto-redaction, ordered output, and CI/CD exit codes.

Prerequisites

evnx diff — Command Reference

Compare .env and .env.example files to identify missing, extra, and mismatched variables with security-first defaults and predictable output.

Before you start

Security by Default: Variable values are hidden in output unless --show-values is explicitly passed. Sensitive keys (containing PASSWORD, SECRET, TOKEN, etc.) are auto-redacted even when --show-values is enabled, showing only the first 2 characters followed by ***.


Command signature

Bash
evnx diff [OPTIONS]

Options reference

FlagTypeDefaultDescription
--env, -epath.envPath to the active environment file to compare
--examplepath.env.examplePath to the example/template file to compare against
--show-valuesboolfalseDisplay variable values in output (⚠️ may expose sensitive data)
--format, -fenumprettyOutput format: pretty (colored terminal), json (machine-readable), or patch (unified diff)
--reverse, -rboolfalseReverse comparison direction: compare example → env instead of env → example
--ignore-keyslist[]Comma-separated list of keys to exclude from comparison (e.g., DATABASE_URL,REDIS_URL)
--with-statsboolfalseInclude extended statistics in JSON output (similarity_percent, overlap_count, etc.)
--interactive, -iboolfalseEnable interactive merge mode (only applies when --format patch is used)
--verbose, -vboolfalseEnable detailed debug output to stderr
--help, -hboolfalseDisplay help information

Format values

ValueOutput styleBest for
prettyColored terminal output with icons (+, -, ~)Human review, local development
jsonStructured JSON with missing, extra, different arraysCI/CD pipelines, programmatic consumption
patchUnified diff format with +/- prefixesAutomation, piping to patch or scripts

Exit codes

CodeMeaningUse case
0✅ Files are identical (no differences detected)Success in scripts; proceed with deployment
1⚠️ Differences found (missing, extra, or mismatched values)Fail CI/CD pipeline when drift detected
2+❌ Runtime error (file not found, parse error, permission denied)Debug tooling or environment issues

CI/CD Integration: By default, evnx diff exits with code 1 when any differences are found. Use this behavior in CI pipelines to enforce environment file consistency:

evnx diff && echo "✅ Env files in sync" || echo "❌ Drift detected"


Output structure by format

pretty format (default)

Human-readable output with colored status indicators:

┌─ Comparing .env ↔ .env.example ─────────────────────┐
└──────────────────────────────────────────────────────┘

Missing from .env (present in .env.example):
  + NEW_FEATURE_FLAG

Extra in .env (not in .env.example):
  - DEPRECATED_VAR

Different values:
  ~ DATABASE_URL
    .env.example: postgresql://localhost:5432/dev
    .env: postgresql://prod-server:5432/prod

Summary:
  + 1 missing (add to .env)
  - 1 extra (consider removing or adding to .env.example)
  ~ 1 different values

json format

Machine-readable output for programmatic consumption:

JSON
{
  "missing": ["NEW_FEATURE_FLAG"],
  "extra": ["DEPRECATED_VAR"],
  "different": [
    {
      "key": "DATABASE_URL",
      "example_value": "postgresql://localhost:5432/dev",
      "env_value": "postgresql://prod-server:5432/prod",
      "example_value_redacted": null,
      "env_value_redacted": null
    }
  ],
  "stats": {
    "total_keys_env": 12,
    "total_keys_example": 13,
    "overlap_count": 11,
    "similarity_percent": 84.62
  }
}

The stats field is only included when --with-stats is passed. Redacted value fields appear when the key matches sensitive patterns.

patch format

Unified diff-style output for automation:

patch
# Add these to .env:
+ NEW_FEATURE_FLAG=placeholder

# Remove these from .env:
- DEPRECATED_VAR=old_value

# Update these in .env:
- DATABASE_URL=postgresql://prod-server:5432/prod
+ DATABASE_URL=postgresql://localhost:5432/dev

Sensitive key auto-redaction

Keys matching these patterns (case-insensitive) have values auto-redacted in output:

PatternExample keysRedacted output
PASSWORD, PASSWD, PWDDB_PASSWORD, ADMIN_PWDab***
SECRETSECRET_KEY, APP_SECRETsu***
TOKENAPI_TOKEN, AUTH_TOKENto***
KEY, API_KEY, APIKEYAWS_ACCESS_KEY, STRIPE_APIKEYAK***
PRIVATE_KEYRSA_PRIVATE_KEYpr***
AUTH, CREDENTIALOAUTH_SECRET, DB_CREDENTIALoa***

Redaction behavior:

  • Default mode (--show-values not set): All values shown as ***
  • With --show-values: Non-sensitive keys show full values; sensitive keys show first 2 chars + ***
  • JSON output: Includes both original (example_value) and redacted (example_value_redacted) fields when applicable

Key order preservation

Output order matches insertion order from the source files (not hash order):

Bash
# .env.example contents (insertion order):
Z_LAST=value
A_FIRST=value
M_MIDDLE=value

# Output shows missing/extra keys in file order:
Missing from .env:
  + Z_LAST
  + A_FIRST
  + M_MIDDLE

This ensures predictable, reproducible output for:

  • ✅ Code review diffs
  • ✅ CI/CD log comparison
  • ✅ Automated patch application

Interactive merge mode (--format patch --interactive)

When both --format patch and --interactive are specified, evnx prompts for selective change application:

🔧 Interactive Merge Mode
Prompts: (y)es, (n)o, (s)kip rest

➕ Add NEW_FEATURE_FLAG=placeholder? [y/n/s]: y
   ✓ Queued: + NEW_FEATURE_FLAG=placeholder

✏️  Update DATABASE_URL?
   - postgresql://prod-server:5432/prod
   + postgresql://localhost:5432/dev? [y/n/s]: n
   ✗ Skipped

📋 Applied changes:
  + NEW_FEATURE_FLAG=placeholder

💡 Tip: Save output and apply with: patch -p1 < changes.patch

Interactive mode only works with --format patch. Other formats ignore the --interactive flag.


Statistics reference (--with-stats)

When --with-stats is passed with --format json, the output includes a stats object:

FieldTypeDescription
total_keys_envintegerTotal variable count in the .env file
total_keys_exampleintegerTotal variable count in the .env.example file
overlap_countintegerKeys present in both files
similarity_percentfloatSørensen-Dice coefficient: 2×overlap / (env + example) × 100

Similarity interpretation:

  • 100.0: Files have identical key sets
  • 50.0: Half the keys overlap (e.g., 1 shared key out of 2 total each)
  • 0.0: No keys in common

Environment variables

VariableValuesDefaultDescription
NO_COLOR1, truefalseDisable colored output for terminals or log files
CI1, truefalseAuto-enable non-interactive behavior (affects interactive mode)

Troubleshooting

"Failed to parse" error

✗ Failed to parse .env: Invalid format at line 5: missing '=' separator

Solution: Check the indicated line for malformed KEY=value syntax. Comments (#) and blank lines are allowed; export prefix is supported.

No output despite expected differences

✓ Files are identical

Check:

  1. Are you comparing the correct files? Use --env and --example to specify paths explicitly
  2. Are keys being filtered by --ignore-keys? Remove the flag or verify the key list
  3. Is --reverse changing the comparison direction unexpectedly?

Sensitive values still visible in output

  + DB_PASSWORD = mysecretpassword123

Solution:

  • Omit --show-values to hide all values: evnx diff
  • Or ensure the key name contains a sensitive pattern: rename DB_PASSWORDDATABASE_PASSWORD (still matches)

JSON output missing stats field

JSON
{
  "missing": [...],
  "extra": [...],
  "different": [...]
  // stats field absent
}

Solution: Add --with-stats flag: evnx diff --format json --with-stats


See also