Find environment-variable drift before your users do.
Your code, .env.example, README, Dockerfile and CI can quietly disagree. envcontract reads the repository locally and tells you what a fresh clone will miss. It never uploads files and never prints secret values.
- Zero runtime dependencies. A tool that runs in CI on every push should not drag its own supply chain along. This one has none.
- Local only, always. No network calls, no account, no telemetry — and it never prints a secret value.
--strictfails your build.--jsonfeeds your dashboard.
npx envcontract .Run it before every push, and a missing variable on the day of the deploy stops being a surprise.
- run: npx envcontract . --strictUse --json for bots and dashboards. The scanner understands JavaScript/TypeScript, Python, Go, Ruby, PHP, Java, Rust, Swift, shell, Docker/Compose, and ${VARIABLE} references. It ignores .git, dependencies and build output.
- uses: tangyuan1129/envcontract@v1
with:
path: .
strict: trueFindings show up as native annotations on the job, and errors / warnings are exposed as step outputs. Set strict: false to report without failing the build.
- Variables referenced in code but missing from
.env.example(and vice versa) - Variables your README or Dockerfile promises but nothing provides
- Mismatches between
.env.exampleand the environment your CI actually builds
Anything that would make a fresh clone fail to start, envcontract catches locally — before your users do.
Linters usually check source code. Dotenv tools usually check one env file. envcontract checks the contract between them — the tiny promise that makes a fresh clone start.
It is deliberately small: zero runtime dependencies, no network access, and a codebase you can read in one sitting. Nothing here should be the reason your CI breaks.
npm test
node bin/envcontract.js . --strictNode 18+.
The repo ships with an MIT License, CI, issue templates and an npm publishing workflow. To release the first version, follow the 3 steps in RELEASE.md.
MIT © envcontract contributors