envtidy
Keep your
.envfiles honest — catch drift, sync examples, find leaks.
Every team has lived this bug: someone adds REDIS_URL to their local .env, forgets to update .env.example, and the next person to clone the repo burns an hour debugging a crash that was really just a missing variable. Or worse — someone's staging.env was never gitignored and ships to GitHub with live credentials inside.
envtidy is a tiny CLI that catches both. Pure Python stdlib, zero dependencies, single-purpose.
Install
pipx install envtidy
# or
pip install envtidy
Usage
envtidy check — catch drift
Compares .env against .env.example (also auto-detects .sample, .template, .dist):
$ envtidy check
envtidy check .env vs .env.example
missing REDIS_URL (in example, not in env)
extra DEBUG (in env, not in example)
empty SMTP_HOST (declared but has no value)
3 issues found (1 missing, 1 extra, 1 empty)
Exits 1 when drift is found, 0 when clean — drop it straight into CI or pre-commit:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/nidhisebastian008/envtidy
rev: v0.2.1
hooks:
- id: envtidy-check # needs .env + .env.example present
- id: envtidy-scan
envtidy sync — regenerate the example file
Rewrites .env.example from your real .env, stripping every value but preserving comments, blank lines, and key order:
$ envtidy sync
created .env.example (4 keys, values stripped)
Use --dry-run to preview without writing.
envtidy scan — find files that leaked (or are about to)
Walks a directory tree, finds every env file, and checks each one against git — including the full git history. Deleting a committed .env doesn't remove it; anyone with a clone can still recover it. scan catches that:
$ envtidy scan
envtidy scan ~/code/myapp
ignored .env
exposed staging.env (not in .gitignore — one `git add .` from leaking)
TRACKED api/.env.production (committed to git — rotate these secrets)
HISTORY old/.env.local (deleted, but still in git history — rotate + scrub)
3 files at risk
hint: scrub history with `git filter-repo --sensitive-data-removal --invert-paths --path <file>`
- ignored — safely gitignored, never committed ✅
- exposed — exists but not gitignored; one
git add .away from a leak - TRACKED — committed right now; treat those secrets as compromised and rotate them
- HISTORY — not in the working tree or index anymore, but recoverable from git history; rotate the secrets and scrub the history
Alternatives
Prior art exists — pick the right tool for your job:
- dotenv-linter — fast Rust linter for
.envstyle (duplicate keys, ordering, quoting), with acomparecommand for key diffs. No git awareness, no example generation. - sync-dotenv — Node tool doing what
envtidy syncdoes. - gitleaks / trufflehog / detect-secrets — heavyweight content-level secret scanners with rules and entropy checks. Use them for full audits; use
envtidy scanfor the quick file-level answer to "are my env files safe in this repo?"
envtidy's niche: all three jobs (drift check, example sync, git-aware leak scan) in one zero-dependency CLI with no config.
Details
- Understands
export KEY=value, quoted values, inline# comments - Respects
NO_COLOR; colors auto-disable when piped - Skips
node_modules,.venv,.git, build dirs while scanning - Exit codes:
0clean ·1issues found ·2usage error
License
MIT
Metadata
Release files for envtidy 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| envtidy-0.2.1.tar.gz | 7.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| envtidy-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.1 kB
Release files / envtidy-0.2.1.tar.gz
| Download URL | envtidy-0.2.1.tar.gz |
|---|---|
| Size | 7.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
737c75cf233af8df4dcb9b6eed7ae3c19c2d7b2966189f6cf81f431b9d59f872
|
|
BLAKE2b-256 checksum How to use checksums |
656568071c92817540fde927f591ad74a8381a01315e9fc9d2507fc07a07d797
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency logRelease files / envtidy-0.2.1-py3-none-any.whl
| Download URL | envtidy-0.2.1-py3-none-any.whl |
|---|---|
| Size | 8.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
94941ff5a1d6f4da5734ad0c769ec92151de94e4487629575d2c8790603e3351
|
|
BLAKE2b-256 checksum How to use checksums |
31b795491f5f00a79fa69d52eb5a3150d63cfb2789a34954c50c9e866cef5d50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 26, 2026.
Transparency log