Almost every developer has fought .env issues. They're silent, annoying, and they only show up after you deploy or after someone clones the repo.
Here's the exact failure I hit one too many times:
- I add
STRIPE_KEYto my local.env. - I ship code that reads
process.env.STRIPE_KEY. - I forget to add
STRIPE_KEYto the committed.env.example. - A teammate clones, runs the app, and it crashes on a missing variable.
The reverse is just as common: .env.example promises a key you never actually set locally — a silent misconfig waiting to bite.
The two files are supposed to declare the same set of keys. They drift apart constantly. So I built a small guardrail.
dotdrift
Zero dependencies, one command:
npx dotdrift
x drift detected between .env and .env.example
Missing in .env.example (add these so teammates know they're needed):
+ STRIPE_KEY
Tip: run "dotdrift sync" to update .env.example automatically.
It exits non-zero on drift, so it drops straight into CI:
- run: npx dotdrift --strict # --strict also flags empty values
The part I actually wanted: sync
Detecting drift is half the problem. The annoying half is fixing the template by hand. So sync regenerates .env.example from your real .env:
npx dotdrift sync
- values are stripped (
KEY=), - your comments and blank-line grouping are preserved,
- curated placeholders already in the template survive (a hand-written
PORT=3000stays), - it's idempotent — run it twice, nothing changes.
So updating the template is now one command instead of a manual chore.
Make it permanent
npx dotdrift hook
Installs a .git/hooks/pre-commit that blocks commits when things drift. A one-time tool becomes a continuous safety net.
Monorepo
npx dotdrift -r
Scans every subdirectory that has an .env/.env.example pair (skips node_modules, dist, etc.) and reports per service.
Notes
- Zero dependencies — Node stdlib only, ~250 lines.
- It only ever compares key names (and, with
--strict, whether a value is empty). It never prints or transmits your secret values. - Understands
KEY=value,export KEY=value, single/double quotes,KEY=(empty),#comments, and inline comments on unquoted values. - MIT licensed.
Repo: https://github.com/jjdoor/dotdrift
npm: npx dotdrift
If you hit a parsing edge case or the sync output isn't what you'd expect, open an issue — that's exactly the feedback I'm after.
Top comments (0)