Keep your .env files in sync with .env.example
A lightweight CLI tool and PHP library that detects missing, extra, and empty environment variables by comparing your .env files against .env.example.
- Missing variable detection -- find variables defined in
.env.examplebut absent from.env - Extra variable detection -- spot variables in
.envthat aren't in.env.example - Empty value warnings -- flag variables that have a default in the example but are empty in your env
- Multi-environment support -- check multiple
.envfiles in a single run - Proper
.envparsing -- handles comments, single/double quotes, escape sequences, andexportprefixes - CI-friendly exit codes -- exits
1on issues,0when everything is in sync - Text and JSON output -- machine-readable output for pipelines
composer require --dev kexxt/env-syncRun with no arguments to compare .env.example against .env:
vendor/bin/env-syncWhen everything is in sync:
✅ All variables in sync! (12 variables)
When issues are found:
env-sync: comparing .env.example → .env
❌ Missing variables (2):
STRIPE_SECRET_KEY (line 14 in .env.example)
REDIS_PASSWORD (line 22 in .env.example)
⚠️ Empty values (1):
APP_URL (example default: http://localhost)
ℹ️ Extra variables (1):
DEBUG_MODE (line 8 in .env, not in .env.example)
Summary: 12 expected · 11 present · 2 missing · 1 empty · 1 extra
Compare env files against an example file.
# Basic check
vendor/bin/env-sync check
# Custom example and target files
vendor/bin/env-sync check --example=.env.dist --env=.env.local
# Check multiple environments at once
vendor/bin/env-sync check --env=.env.staging --env=.env.production
# Strict mode: fail on extra variables too
vendor/bin/env-sync check --strict
# Suppress empty value warnings
vendor/bin/env-sync check --no-empty
# Quiet mode: only output problems
vendor/bin/env-sync check --quiet
# JSON output
vendor/bin/env-sync check --format=json
# CI mode: no color, exit 1 on any issue
vendor/bin/env-sync check --ci| Option|-|
|--example|Path to example env file (default: .env.example)|
|--env|Target env file(s), repeatable (default: .env)|
|--strict|Fail on extra variables|
|--no-empty|Don't warn about empty values|
|--format|Output format: text or json (default: text)|
|--ci|CI mode: disables color, exits 1 on any issue|
|--quiet, -q|Only output problems|
Show a full diff between any two env files.
vendor/bin/env-sync diff .env.staging .env.production
vendor/bin/env-sync diff .env.example .env --format=json| Option|-|
|file1 (argument)|First env file (required)|
|file2 (argument)|Second env file (required)|
|--format|Output format: text or json (default: text)|
List all variables in an env file.
# List variable names from .env.example (default)
vendor/bin/env-sync list-vars
# List from a specific file, including values
vendor/bin/env-sync list-vars .env.local --values
# JSON output
vendor/bin/env-sync list-vars --format=json| Option|-|
|file (argument)|Env file to list (default: .env.example)|
|--values|Include variable values in output|
|--format|Output format: text or json (default: text)|
- name: Check env sync
run: vendor/bin/env-sync check --ciFull workflow example:
name: ENV Sync Check
on: [push, pull_request]
jobs:
env-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- run: composer install --no-interaction
- name: Check env sync
run: vendor/bin/env-sync check --ci --format=jsonenv-sync:
stage: test
script:
- composer install --no-interaction
- vendor/bin/env-sync check --ciUse the Comparator class directly in your PHP code:
use EnvSync\Comparator;
use EnvSync\EnvFile;
$example = EnvFile::parse('.env.example');
$target = EnvFile::parse('.env');
$comparator = new Comparator();
$result = $comparator->compare($example, $target);
if ($result->hasMissing()) {
foreach ($result->missing as $var) {
echo "Missing: {$var->key} (line {$var->lineNumber})\n";
}
}
if ($result->hasExtra()) {
foreach ($result->extra as $var) {
echo "Extra: {$var->key}\n";
}
}
if ($result->hasEmpty()) {
foreach ($result->empty as $var) {
echo "Empty: {$var->key}\n";
}
}
// Summary counts
echo "Expected: {$result->expectedCount}, Present: {$result->actualCount}\n";You can also parse env content from a string:
$envFile = EnvFile::parseString("APP_KEY=base64:abc\nDB_HOST=localhost\n");
$keys = $envFile->keys(); // ['APP_KEY', 'DB_HOST']MIT -- see LICENSE for details.