envdoc.
Keep .env and .env.example honest, and catch secrets before they ship.
Every project has a .env.example that was right once. Then someone adds a key to their own .env, the code starts depending on it, and the next person to clone the repo gets an app that fails for no visible reason. Or worse, someone “updates the example” with cp .env .env.example and commits every credential.
envdoc compares three sources of truth: your .env, your .env.example, and the variables your code actually reads. It tells you what’s missing, fills the gaps without copying secrets, and stops env files and dumps from being committed.
Zero dependencies, Python 3.9+. It works with Laravel, Node/Vite and Python projects, and runs entirely on your machine.
Sample run
A real run on a small Laravel-style app:
$ envdoc check
.env:8: error [missing-in-example] DB_SSLMODE is set in .env but not documented in .env.example
.env:9: error [missing-in-example] STRIPE_SECRET is set in .env but not documented in .env.example
config/billing.php:5: error [undocumented-required] STRIPE_WEBHOOK_SECRET is read with no fallback but is not in .env.example
envdoc: 3 errors
$ envdoc sync
added (value kept): DB_SSLMODE
added (value withheld): STRIPE_SECRET
envdoc: updated .env.example (2 change(s))
DB_SSLMODE=require is generic, so its value was kept. The Stripe key became STRIPE_SECRET=. The webhook secret is still reported because no .env sets it, so only a person can document it.
What it does
envdoc checkfinds keys set in.envbut not documented, keys the code reads with no fallback, and real-looking secrets in the example. It exits 1 on errors and can print GitHub annotations or JSON.envdoc syncadds missing keys to.env.example, next to their family (DB_SSLMODEafter the otherDB_*keys), keeping comments, order and quoting. Secrets become blank.envdoc scanfinds env files and database dumps that git tracks or doesn’t ignore, across every repo in a folder.envdoc hookinstalls a pre-commit hook that blocks env files, dumps and leaked secrets, reading the staged content, not the working copy.envdoc initsets up.gitignore,.env.exampleand the hook in one safe step.
Install
pip install git+https://github.com/hassixmalik/envdoc.git
envdoc init
In CI:
- run: pip install git+https://github.com/hassixmalik/envdoc.git
- run: envdoc check --format github
Built with
Plain Python, no dependencies, MIT licensed. It reads env('X'), process.env.X, import.meta.env.X and os.environ patterns, and knows which Laravel config keys are optional on purpose.
Changelog
v0.1.0First release: check, sync, scan, hook and init. · 2026-10-30