Diff Basics — Compare Environment Files
Learn how to use evnx diff to compare .env and .env.example files. Detect missing variables, spot mismatches, and keep your environment in sync.
Prerequisites
Diff Basics — Compare Environment Files
What you'll learn
In this tutorial, you'll learn how to use evnx diff to:
- ›Detect missing, extra, and mismatched variables between
.envand.env.example - ›Understand the three output formats: pretty, json, and patch
- ›Use
--show-valuessafely with auto-redaction for sensitive keys - ›Integrate diff checks into your workflow with exit codes
Before you start
What is diff and why use it?
As your project evolves, .env and .env.example can drift apart:
- ›Missing: New variables added to
.env.examplebut not in your.env - ›Extra: Local-only variables in
.envthat aren't in the template - ›Different: Same variable name, but different values (dev vs. prod)
The diff command compares these files and shows exactly what's out of sync — with security-first defaults.
Values are hidden by default
For security, evnx diff does NOT show variable values unless you pass --show-values. Even then, sensitive keys (like PASSWORD, SECRET, TOKEN) are auto-redacted to ab*** format.
Quick start: Your first diff
Scenario: You just pulled a team update
Step 1: Run diff with default settings
cd my-project
evnx diffStep 2: Read the output
┌─ Comparing .env ↔ .env.example ─────────────────────┐
└──────────────────────────────────────────────────────┘
Missing from .env (present in .env.example):
+ NEW_FEATURE_FLAG
Extra in .env (not in .env.example):
- LOCAL_DEBUG_MODE
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
Step 3: Take action
# Add the missing variable to your .env
echo "NEW_FEATURE_FLAG=true" >> .env
# Run diff again to verify
evnx diff
✓ Files are identical✅ Done! Your environment is back in sync.
Understanding the output
Status indicators
| Icon | Meaning | Color |
|---|---|---|
+ | Variable is missing from .env | 🟢 Green |
- | Variable is extra in .env | 🔴 Red |
~ | Variable has different values | 🟡 Yellow |
✓ | Files are identical | 🟢 Green |
Value display rules
# Default: values hidden
evnx diff
# Output:
# + NEW_API_KEY
# With --show-values: non-sensitive keys show full values
evnx diff --show-values
# Output:
# + NEW_API_KEY = sk_test_abc123
# Sensitive keys are always redacted, even with --show-values
evnx diff --show-values
# Output:
# + DB_PASSWORD = ab***
# + API_TOKEN = to***Sensitive key patterns
Keys containing these substrings (case-insensitive) are auto-redacted: PASSWORD, SECRET, TOKEN, KEY, AUTH, CREDENTIAL, PRIVATE_KEY.
Three output formats
1. Pretty (default) — For humans
Colored, readable output for terminal use:
evnx diffMissing from .env:
+ FEATURE_X_ENABLED
Different values:
~ API_TIMEOUT
.env.example: 30
.env: 60
2. JSON — For automation
Machine-readable output for scripts and CI/CD:
evnx diff --format json{
"missing": ["FEATURE_X_ENABLED"],
"extra": [],
"different": [
{
"key": "API_TIMEOUT",
"example_value": "30",
"env_value": "60",
"example_value_redacted": null,
"env_value_redacted": null
}
]
}Add statistics to JSON
Use --with-stats to include similarity metrics:
evnx diff --format json --with-stats | jq '.stats.similarity_percent'3. Patch — For applying changes
Unified diff format compatible with patch and scripts:
evnx diff --format patch# Add these to .env:
+ FEATURE_X_ENABLED=true
# Update these in .env:
- API_TIMEOUT=60
+ API_TIMEOUT=30Interactive merge
Add --interactive to patch mode for selective application:
evnx diff --format patch --interactive
Prompts: (y)es, (n)o, (s)kip restPractical examples
Check before committing
# Ensure your .env matches the team template
evnx diff && git commit -am "Update feature"
# If diff finds differences, commit is skipped (exit code 1)Compare custom file paths
# Compare production env with example
evnx diff --env .env.production --example .env.example
# Compare in a monorepo subdirectory
evnx diff --env ./packages/api/.env --example ./packages/api/.env.exampleIgnore environment-specific variables
# Skip variables that differ by environment
evnx diff --ignore-keys DATABASE_URL,REDIS_URL,DEPLOY_REGIONReverse comparison direction
# See what's in .env.example but missing from .env (default)
evnx diff
# See what's in .env but missing from .env.example
evnx diff --reverseDebug with verbose output
# See parsing details and internal steps
evnx diff --verbose 2>&1 | grep "verbose"Using diff in CI/CD
Basic pipeline check
# .github/workflows/check-env.yml
- name: Check environment consistency
run: |
evnx diff || {
echo "❌ Environment drift detected!"
echo "Run 'evnx diff' locally to see differences"
exit 1
}JSON output for programmatic checks
# Extract just the missing keys
evnx diff --format json | jq -r '.missing[]'
# Fail if similarity is below threshold
SIMILARITY=$(evnx diff --format json --with-stats | jq '.stats.similarity_percent')
if (( $(echo "$SIMILARITY < 90" | bc -l) )); then
echo "⚠️ Environment similarity too low: ${SIMILARITY}%"
exit 1
fiSuppress colored output for logs
# Disable colors for clean CI logs
NO_COLOR=1 evnx diff --format jsonCommon pitfalls to avoid
Forgetting that values are hidden by default
# ❌ Expecting to see values without the flag
evnx diff | grep "DATABASE_URL"
# Output: ~ DATABASE_URL (no values shown)
# ✅ Add --show-values to see non-sensitive values
evnx diff --show-values | grep "DATABASE_URL"Misinterpreting exit codes
# ❌ Assuming any non-zero exit is an error
evnx diff
if [ $? -ne 0 ]; then
echo "Command failed!" # Wrong: could just mean differences found
fi
# ✅ Check for specific exit codes
evnx diff
case $? in
0) echo "✅ Files identical" ;;
1) echo "⚠️ Differences found (review output above)" ;;
*) echo "❌ Runtime error" ;;
esacUsing --show-values in shared logs
# ❌ Logging sensitive values accidentally
evnx diff --show-values > deploy.log # May leak secrets!
# ✅ Keep values hidden in logs
evnx diff > deploy.log # Safe: values masked by defaultIgnoring key order in patch output
# ❌ Assuming patch output order is arbitrary
# ✅ Order matches file insertion order — use this for predictable diffs
evnx diff --format patch | head -10Troubleshooting
"Files are identical" but I see differences
Check: Are you comparing the correct files?
# Verify file paths
ls -la .env .env.example
# Specify paths explicitly if needed
evnx diff --env ./config/.env --example ./config/.env.exampleSensitive values still visible
Check: Does the key name contain a sensitive pattern?
# ❌ This key won't be redacted (no sensitive pattern)
MY_CUSTOM_SECRET_VALUE=abc123
# ✅ Rename to trigger redaction
MY_CUSTOM_PASSWORD=abc123 # Contains "PASSWORD" → redactedJSON output missing expected fields
Check: Did you include --with-stats for statistics?
# ❌ Stats not included by default
evnx diff --format json | jq '.stats' # null
# ✅ Add --with-stats
evnx diff --format json --with-stats | jq '.stats' # { ... }Interactive mode not prompting
Check: Interactive mode only works with --format patch:
# ❌ Interactive ignored with pretty format
evnx diff --interactive # No prompts
# ✅ Use with patch format
evnx diff --format patch --interactive # Prompts appearNext steps
Now that you can compare environment files:
- ›Sync Basics — Automatically reconcile differences instead of just detecting them
- ›Validate Command — Check for security issues and common mistakes
- ›Team Collaboration — Share
.env.examplesafely with your team - ›CI/CD Integration — Enforce environment consistency in pipelines
You're ready!
You now know how to detect and understand environment drift. Run evnx diff before commits, after pulls, and in CI to keep your project secure and consistent.