Detect drift between .env files — missing, extra, and unset keys
Project description
dotdrift
Detect drift between your
.envfiles — locally, in CI, and against your live environment.
Install
pip install dotdrift
Or via npm (requires Python 3.11+ on $PATH):
npx dotdrift
Quick start
# Compare .env against .env.example (the defaults)
dotdrift check
# Compare two specific files
dotdrift check .env .env.staging
# Fail the build if any extra, undocumented keys exist
dotdrift check --strict
# Pipe JSON output into jq
dotdrift check --json | jq .missing
# Generate a redacted .env.example from your real .env
dotdrift sync .env --output .env.example
# Check the live process environment against a reference
dotdrift live .env.example
# Re-run check every time .env changes (Ctrl+C to stop)
dotdrift watch
Python API
from envdiff import compare, parse
# Programmatic diff — accepts file paths, raw strings, or plain dicts
result = compare(".env", ".env.example", strict=True, check_conflicts=True)
if not result.is_clean():
print("Missing keys:", result.missing)
print("Unset keys: ", result.unset)
print("Conflicts: ", result.conflicts)
print(result.summary())
# Parse a .env file directly
parsed = parse(".env")
for key, entry in parsed.entries.items():
print(f"{key} = {entry.value!r} (line {entry.line_number})")
Commands
check
dotdrift check [SOURCE] [REFERENCE] [OPTIONS]
Compare SOURCE (default: .env) against REFERENCE (default: .env.example)
and report missing, extra, unset, or conflicting keys.
| Option | Description |
|---|---|
--strict |
Exit 2 when extra (undocumented) keys exist |
--ignore KEY |
Exclude KEY from all comparisons (repeatable) |
--conflicts |
Also detect keys that differ in value |
--json |
Emit JSON parseable by jq |
--quiet / -q |
Suppress all output; only set exit code |
Exit codes: 0 clean · 1 missing/unset · 2 strict+extra · 3 file not found
sync
dotdrift sync [SOURCE] [OPTIONS]
Generate a .env.example from SOURCE with every value redacted (set to "").
A header comment block is prepended automatically.
| Option | Description |
|---|---|
--output / -o |
Output file path (default: .env.example) |
--overwrite |
Allow overwriting an existing file |
--dry-run |
Print to stdout; write nothing |
live
dotdrift live [REFERENCE] [OPTIONS]
Compare os.environ (the live running environment) against REFERENCE.
Useful in Docker entrypoints and CI environments to verify all required
variables are injected before the application starts.
| Option | Description |
|---|---|
--ignore KEY |
Exclude KEY (repeatable) |
--json |
JSON output |
watch
dotdrift watch [SOURCE] [REFERENCE] [OPTIONS]
Poll SOURCE for file changes and re-run check on every save.
Uses stat().st_mtime — no external dependencies.
| Option | Description |
|---|---|
--interval |
Poll interval in seconds (default: 2) |
--json |
JSON output per check |
Press Ctrl+C to stop cleanly (exit 0).
CI integration
Add this step to your workflow to gate merges on a clean env:
- name: Check .env drift
run: |
pip install dotdrift
dotdrift check .env.ci .env.example --strict
Or pipe JSON results into a downstream step:
- name: Env drift report
run: dotdrift check --json --quiet > env_report.json
Why not just use python-dotenv?
python-dotenv loads .env files into os.environ. dotdrift audits
them — it tells you what is missing, what is undocumented, and what has drifted
between environments. They solve different problems and work well together.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dotdrift-0.1.0.tar.gz.
File metadata
- Download URL: dotdrift-0.1.0.tar.gz
- Upload date:
- Size: 21.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
658dc63e23c64d5aeeed2a8b69f22cf7dae2fb5c9ead72009fdea269596bc87f
|
|
| MD5 |
3ef4840360ca89e8413e54f9e375cea0
|
|
| BLAKE2b-256 |
e37c626d530dddfdbee735f42af33e35107831e746a9562fbd311365bd8aa2e4
|
Provenance
The following attestation bundles were made for dotdrift-0.1.0.tar.gz:
Publisher:
publish.yml on Wombatfreak6/envdiff
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dotdrift-0.1.0.tar.gz -
Subject digest:
658dc63e23c64d5aeeed2a8b69f22cf7dae2fb5c9ead72009fdea269596bc87f - Sigstore transparency entry: 2048179865
- Sigstore integration time:
-
Permalink:
Wombatfreak6/envdiff@2fe100fc355f95acf11cb4c717e01a0162a78d4c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Wombatfreak6
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2fe100fc355f95acf11cb4c717e01a0162a78d4c -
Trigger Event:
push
-
Statement type:
File details
Details for the file dotdrift-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dotdrift-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35168eb4b8a509efbb167f406b17d0f8017b49c727df54c71c3e0a11a5e9c20f
|
|
| MD5 |
0bac30d81de810fcaf53e918a7fd4003
|
|
| BLAKE2b-256 |
2e22a1d33e12575bf2f2c0968f399d66cf9e15bafef6d576a06fdbe139e6d348
|
Provenance
The following attestation bundles were made for dotdrift-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Wombatfreak6/envdiff
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dotdrift-0.1.0-py3-none-any.whl -
Subject digest:
35168eb4b8a509efbb167f406b17d0f8017b49c727df54c71c3e0a11a5e9c20f - Sigstore transparency entry: 2048180153
- Sigstore integration time:
-
Permalink:
Wombatfreak6/envdiff@2fe100fc355f95acf11cb4c717e01a0162a78d4c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Wombatfreak6
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2fe100fc355f95acf11cb4c717e01a0162a78d4c -
Trigger Event:
push
-
Statement type: