The all-in-one CLI for environment variable validation, drift detection, and deployment safety.
Detect missing .env variables, enforce schema validation, scan your codebase, diff environments, audit git safety — all from one CLI. A zero-config alternative to dotenv-safe and envalid that requires no code changes.
Installation • Quick Start • Commands • Schema Config • CI/CD • Pre-commit Hook • Library Usage • Changelog • Roadmap
npx env-drift-check
✔ Loaded: .env
✔ Base: .env.example
✖ Missing keys:
- DATABASE_URL
- STRIPE_SECRET_KEY
⚠ Unused keys:
- OLD_API_KEY
❌ Validation failed: PORT must be a numberFix everything interactively in one command:
npx env-drift-check -iManaging .env files across a team or across deployment environments (development, staging, production) is one of the most error-prone parts of any project:
- Missing variables cause unexpected runtime crashes in production.
- Wrong types — a string
"false"instead of a boolean — create silent logic bugs. - Onboarding new developers means sharing secrets over Slack or debugging an outdated
.env.examplefor hours. - No visibility into which environment variables your codebase actually uses vs. what is documented.
- Leaked
.envfiles in git history expose secrets permanently.
env-drift-check solves all of this from a single CLI tool — with zero code changes to your application.
A new developer clones the repo and gets cryptic errors. npx env-drift-check -i immediately surfaces every missing variable, prompts them with real-time schema validation, masks secret inputs, and writes the result cleanly to .env. Onboarding goes from hours to seconds.
Add npx env-drift-check --system-env --strict to your GitHub Actions workflow. If any required variable is missing or fails validation, the pipeline exits with code 1 before deployment — blocking the broken build at the gate.
npx env-drift-check scan cross-references every process.env.* reference in your JS/TS source against .env.example. Instantly see which documented variables are dead code and which code references are undocumented.
npx env-drift-check diff .env.staging .env.production shows exactly which variables differ between two environments — the fastest way to debug a "works in staging, fails in prod" incident.
npx env-drift-check audit checks every .env* file against .gitignore, live git tracking, and your full git history. Catches leaks before they become a breach.
- 🔍 Environment Drift Detection — Compares
.envagainst.env.example. Finds missing keys and ghost/extra keys. - 🛡️ Schema Validation — Enforce
string,number,boolean,enum,email,url, andregextypes viaenvwise.config.json. No code changes required. - 🔑 Codebase Scanner — Scans JS/TS source for
process.env.X,const { X } = process.env, andimport.meta.env.X(Vite). Reports undocumented or dead variables. - 📊 Environment Diff — Side-by-side comparison of two
.envfiles showing added, removed, and changed keys. - 🔐 Git Safety Audit — Detects
.envfiles missing from.gitignore, currently tracked by git, or found in git history. - 🧂 Entropy-Based Secret Scoring — Flags low-entropy secrets using Shannon entropy math — not a simple blocklist.
- 🧩 Framework Prefix Safety — Auto-detects Next.js, Vite, and CRA. Warns when
NEXT_PUBLIC_,VITE_, orREACT_APP_prefixed variables look like secrets. - 🔗 Conditional Required Rules —
requiredIfmakes a key required only when another key has a specific value (e.g.S3_BUCKETonly whenSTORAGE=s3). - 📁 Template Generator — Creates or updates
.env.examplefrom your local.env, stripping values and preserving formatting. - 🪄 Interactive Auto-fix Wizard — Prompts for missing variables with live validation and secret masking.
- ⚡ Process Environment Fallback — Validates against
process.env(via--system-env) for containers and serverless. - ⚙️ JSON & SARIF Output —
--format jsonfor toolchain integrations,--format sarifto upload results to the GitHub Security tab. ⚠️ Variable Deprecation — Flag legacy keys with custom migration warnings.- 📑 High-Fidelity Formatting — Preserves inline comments, blank lines, and key order when writing back to
.env. - 🔄 Multi-Environment Support — Check all
.env*files simultaneously with--all. - 👀 Watch Mode —
--watchre-validates automatically on every.envor config file save. - 🚦 CI/CD Ready —
--strictmode exits with code1on any validation failure. - 🐳 Docker Compose Validation — Validates
environment:blocks indocker-compose.ymlagainst your schema. - ☸️ Kubernetes ConfigMap Generator — Splits
.envinto a K8sConfigMap(safe keys) andSecret(sensitive keys).
| Feature | dotenv-safe |
envalid |
dotenv-linter |
dotenvx |
env-drift-check |
|---|---|---|---|---|---|
| Missing key detection | ✅ | ✅ | ✅ | ✅ | |
| Runtime library | ✅ | ✅ | ❌ | ✅ | |
| CI/CD friendly | ✅ | ✅ | ✅ | ✅ | ✅ |
| Encryption | ❌ | ❌ | ❌ | ✅ | ❌ |
| Standalone CLI | ❌ | ❌ | ✅ | ✅ | ✅ |
| Schema validation (no code changes) | ❌ | ❌ | ❌ | ❌ | ✅ |
| Interactive fix wizard | ❌ | ❌ | ❌ | ❌ | ✅ |
| Codebase scanner | ❌ | ❌ | ❌ | ❌ | ✅ |
| Entropy-based secret scoring | ❌ | ❌ | ❌ | ❌ | ✅ |
| Git safety audit | ❌ | ❌ | ❌ | ❌ | ✅ |
| Environment diff | ❌ | ❌ | ✅ | ❌ | ✅ |
| Framework prefix safety | ❌ | ❌ | ❌ | ❌ | ✅ |
| Docker / Kubernetes support | ❌ | ❌ | ❌ | ❌ | ✅ |
graph TD
A[Developer / CI Pipeline] -->|Run env-drift-check| B(Engine)
subgraph Validation Process
B -->|1. Parse| C{.env.example}
B -->|2. Parse| D[Target .env / process.env]
B -->|3. Load Rules| E[envwise.config.json]
C --> F{Drift Detector}
D --> F
F -->|Detect Mismatches| G{Compare Keys & Values}
E -->|Schema Validation| G
end
G -->|Interactive Mode| H[Prompt UI: Auto-fix]
H -->|Update| D
G -->|Strict Mode| I[CI/CD Exit Code 1]
G -->|Report| J[Terminal / JSON Output]
# Install as a dev dependency
npm install --save-dev env-drift-check
# Or use directly without installing
npx env-drift-checkSupported environments: Node.js ≥ 16, npm, pnpm, yarn. Works with Express, Next.js, Vite, Fastify, NestJS, Remix, SvelteKit, and any Node.js project.
Bootstrap a config file and .env.example in your project root:
npx env-drift-check init✅ Created envwise.config.json
✅ Created .env.example
Setup complete! Run 'npx env-drift-check -i' to sync your .env file.
Tip
See the Demo App for a complete real-world integration example.
When you clone a repo or a teammate adds new variables:
npx env-drift-check -inpx env-drift-check initEdit envwise.config.json to add type rules for each variable:
{
"baseEnv": ".env.example",
"rules": {
"PORT": {
"type": "number",
"min": 3000,
"max": 9999,
"description": "HTTP server port"
},
"DATABASE_URL": {
"type": "url",
"required": true
},
"NODE_ENV": {
"type": "enum",
"values": ["development", "staging", "production", "test"]
},
"DEBUG_MODE": {
"type": "boolean",
"mustBeFalseIn": "production"
},
"API_SECRET_KEY": {
"type": "string",
"checkSecretStrength": true,
"description": "Must pass entropy check"
},
"LEGACY_VAR": {
"type": "string",
"deprecated": "Migrate to NEW_CONFIG_VAR."
}
}
}Find every process.env reference in your source code and compare against .env.example:
npx env-drift-check scan🔍 Scanning codebase for process.env references...
Scanned 12 source file(s).
🔑 Found 4 environment variable(s) referenced in code:
- API_SECRET_KEY
- DATABASE_URL
- NODE_ENV
- PORT
❌ Missing in reference template (referenced in code but not in example):
- JWT_SECRET
Auto-append missing keys to .env.example:
npx env-drift-check scan --fixNo .env.example yet? scan still works — it lists every env variable found in your codebase without needing any reference file:
npx env-drift-check scan🔍 Scanning codebase for process.env references...
Scanned 12 source file(s).
🔑 Found 4 environment variable(s) referenced in code:
- API_SECRET_KEY
- DATABASE_URL
- NODE_ENV
- PORT
ℹ️ No reference file found (.env.example). Run with --fix to create one from the keys above.
Run scan --fix to create .env.example from scratch using the keys found in your code:
npx env-drift-check scan --fix🔍 Scanning codebase for process.env references...
Scanned 12 source file(s).
🔑 Found 4 environment variable(s) referenced in code:
- API_SECRET_KEY
- DATABASE_URL
- NODE_ENV
- PORT
✅ Created .env.example with 4 key(s).
When you add new variables locally, regenerate the example template (values are stripped, comments and formatting are preserved):
npx env-drift-check gen-exampleA developer who just cloned the repo runs:
npx env-drift-check -iEvery missing variable is prompted with live validation. Secret inputs are masked. Result is written cleanly to .env.
Validate injected secrets before every deployment:
npx env-drift-check --system-env --strictJSON output for custom integrations (Slack, PagerDuty, dashboards):
npx env-drift-check --system-env --strict --format json{
".env": {
"success": false,
"result": {
"missing": ["DATABASE_URL"],
"errors": [
{ "key": "API_SECRET_KEY", "message": "API_SECRET_KEY must be at least 8 characters long in production" }
],
"warnings": ["LEGACY_VAR is deprecated. Migrate to NEW_CONFIG_VAR."],
"extra": [],
"mismatches": []
}
}
}{
"baseEnv": ".env.example",
"rules": {
"PORT": { "type": "number", "min": 1024, "max": 65535, "description": "HTTP server port" },
"NODE_ENV": { "type": "enum", "values": ["development", "production", "test", "staging"] },
"DEBUG_MODE": { "type": "boolean", "mustBeFalseIn": "production" },
"DATABASE_URL": { "type": "url", "required": true },
"ADMIN_EMAIL": { "type": "email" },
"API_KEY": { "type": "regex", "regex": "^sk_(test|live)_[0-9a-zA-Z]{24}$" },
"JWT_SECRET": { "type": "string", "checkSecretStrength": true },
"OLD_KEY": { "type": "string", "deprecated": "Use NEW_KEY instead." }
}
}| Type | Options | Description |
|---|---|---|
string |
min, max, checkSecretStrength |
Length bounds. Entropy check for secrets. |
number |
min, max |
Numeric range. Rejects non-numeric strings. |
boolean |
mustBeFalseIn |
Must be "true" or "false". Conditional safety check. |
enum |
values: [] |
Restricts to an allowed set of strings. |
email |
— | Standard email format validation. |
url |
— | Valid URI (supports https://, postgres://, etc). |
regex |
regex |
Custom regular expression. |
| Option | Type | Description |
|---|---|---|
required |
boolean |
Defaults to true. Set false to make optional. |
default |
string |
Fallback value when the key is absent. |
description |
string |
Shown in interactive prompts to guide developers. |
checkSecretStrength |
boolean |
Scores entropy. Auto-enabled for keys containing SECRET or PASSWORD. |
mustBeFalseIn |
string |
Environment name where a boolean must be false (e.g. "production"). |
mustBeTrueIn |
string |
Environment name where a boolean must be true (e.g. "production"). |
requiredIf |
Record<string, string> |
Makes the key required only when another key matches a value (e.g. { "STORAGE": "s3" }). |
deprecated |
boolean | string |
Emits a deprecation warning. Provide a string for a migration message. |
| Command | Description |
|---|---|
env-drift-check |
Check .env against .env.example (default) |
env-drift-check -i |
Interactive wizard — prompt for missing variables |
env-drift-check --strict |
Exit code 1 on any issue (for CI/CD) |
env-drift-check --all |
Check all .env* files in the directory |
env-drift-check --system-env |
Validate against process.env (containers/serverless) |
env-drift-check --watch |
Re-validate on every .env or config file save |
env-drift-check --format json |
JSON output for toolchain integration |
env-drift-check --format sarif |
SARIF output for GitHub Security tab |
env-drift-check scan |
Scan codebase for process.env usage vs .env.example |
env-drift-check scan --fix |
Create or append missing keys to .env.example |
env-drift-check diff <a> <b> |
Side-by-side diff of two .env files |
env-drift-check audit |
Check .env files for git tracking and history leaks |
env-drift-check gen-example |
Generate .env.example from your local .env |
env-drift-check gen-configmap |
Split .env into a K8s ConfigMap + Secret YAML |
env-drift-check validate-compose |
Validate docker-compose.yml env blocks against schema |
env-drift-check init |
Scaffold envwise.config.json and .env.example |
Copy the workflow into .github/workflows/env-check.yml (a ready-to-use file is already included in this repo):
name: Environment Validation
on:
push:
branches: [main, develop]
paths:
- '.env.example'
- 'envwise.config.json'
pull_request:
paths:
- '.env.example'
- 'envwise.config.json'
jobs:
env-drift-check:
name: Validate Environment Configuration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Check environment drift
run: npx env-drift-check --system-env --strict --format json
env:
NODE_ENV: production
PORT: ${{ secrets.PORT }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_SECRET_KEY: ${{ secrets.API_SECRET_KEY }}
- name: Scan for undocumented env vars
run: npx env-drift-check scan
- name: Audit .env git safety
run: npx env-drift-check audit
continue-on-error: trueA ready-to-use workflow is already included at
.github/workflows/env-check.yml.
# GitLab CI / Bitbucket Pipelines / CircleCI / Jenkins
npx env-drift-check --system-env --strictAdd your required variables as CI/CD environment secrets and run this command in the validation stage. Exit code 1 fails the build automatically.
Block commits that would introduce drift into your repository.
npm install --save-dev husky
npx husky init
echo "npx env-drift-check --strict" > .husky/pre-commitOnly run the check when .env.example or the config file changes:
npm install --save-dev lint-stagedAdd to package.json:
{
"lint-staged": {
".env.example": "npx env-drift-check --strict",
"envwise.config.json": "npx env-drift-check --strict"
}
}echo "npx lint-staged" > .husky/pre-commitUse env-drift-check as a library to enforce environment health at application startup.
import { checkDrift, loadConfig, parseEnv, report } from 'env-drift-check';
import path from 'path';
const config = loadConfig();
const baseEnv = parseEnv(path.resolve('.env.example'));
const targetEnv = parseEnv(path.resolve('.env'));
const result = checkDrift(baseEnv, targetEnv, config);
if (result.missing.length || result.errors.length) {
console.error('Environment check failed — refusing to start.');
report(result);
process.exit(1);
}Exported API:
| Export | Description |
|---|---|
checkDrift(base, target, config) |
Returns a DriftResult with missing, extra, errors, warnings, mismatches |
validateValue(key, value, rule, env) |
Validates a single value against a rule |
parseEnv(filePath) |
Parses a .env file into a key-value record |
loadConfig() |
Loads envwise.config.json (or returns defaults) |
updateEnvFile(filePath, values) |
Writes values to a .env file preserving formatting |
generateExampleFile(src, dest) |
Creates a .env.example from a .env |
scanCodebase(dir) |
Returns all process.env references found in source files |
- Basic Usage — Minimal file sync example.
- Real-World Demo App — Express app with fail-fast startup validation and CI/CD integration.
| Code | Meaning |
|---|---|
0 |
All checks passed — no drift, no validation errors |
1 |
Missing keys, validation errors, or strict mode triggered |
- Never commit
.env— Add it to.gitignore. Runnpx env-drift-check auditto verify. - Always commit
.env.exampleandenvwise.config.json— These are your team's source of truth. - Use
-ilocally for onboarding and after pulling changes that modify.env.example. - Use
--strict --system-envin CI/CD — Fail the build before deploying a misconfigured environment. - Run
scanregularly — Catch undocumented variables before they reach production. - Auto-prompt on install via
package.json:{ "scripts": { "prepare": "env-drift-check -i" } }
See CHANGELOG.md for the full version history.
See ROADMAP.md for the full adoption roadmap.
Current: v0.4.0 — All Phase 2 features shipped, including framework prefix safety, requiredIf conditional rules, default values, --watch mode, and SARIF output.
Next: v0.4.1 — Small fixes and improvements.
Upcoming: v0.5.0
- GitHub Actions marketplace action (
uses: shashi089/env-drift-check@v1) - Config inheritance / extends for per-environment overrides
- Monorepo support — validate across
packages/*and aggregate results - Secret manager integrations (Doppler, AWS SSM, Vault)
Contributions are welcome!
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit:
git commit -m 'feat: add your feature' - Push:
git push origin feature/your-feature - Open a Pull Request
Please run npm test before submitting. All 47 tests must pass.
MIT — see LICENSE for details.
Built with care for better Developer Experience by Shashidhar Naik
If this tool saves you time, consider giving it a ⭐ on GitHub.


