Developer Tools
envdiff
Built by Reymart Dalisay
A small command-line tool that compares environment files across environments and tells you what is missing before you deploy.
Builder email verified
Verification

- Type
- Personal
- Category
- Developer Tools
- Published
- Jul 25, 2026
- Updated
- Jul 25, 2026
About this project
- What I built & why
I built this after the third time in a year that a deploy failed because a variable existed in staging and not in production. It's always a five-minute fix and always at a bad hour, and the checks people write for it are usually a grep in a shell script that nobody maintains. I wanted something I could run in CI that would fail the build with a readable message naming the missing key. It took a weekend for the first version and I've been adding to it slowly for about two years since.
- The problem
It solves a narrow problem: environment configuration drifts between environments and you find out at the worst possible moment. envdiff reads two or more env files or a running process's configuration, compares the key sets rather than the values, and reports what's missing, what's extra and what's empty. It's for backend and platform engineers who deploy more than once a week — which is to say people who hit this often enough to be annoyed but not often enough to build a tool for it. It deliberately never prints values, so it's safe to run in a CI log.
- What I owned
It's entirely mine — about 2,500 lines of Go including tests. I wrote the comparison logic, the output formats, the CI-friendly exit codes, and the Homebrew tap. I also wrote the documentation, which took longer than the second version of the tool did. I've merged eleven contributions from other people, mostly around supporting formats I don't use, and I've turned down about as many that would have made it a general configuration manager, which it isn't.
- Technical & product decisions
The decision that shaped everything is that it never reads or prints values, only keys. Several people have asked for value comparison and I keep saying no — the moment it can print a secret, nobody can safely run it in CI, and CI is the entire point. I wrote it in Go so it ships as one binary with no runtime, because the audience is people already fighting environment problems and asking them to install a Python version would be absurd. I also made the default output human-readable and put machine-readable JSON behind a flag, which is backwards from what I'd normally do, but the primary reader is a person staring at a failed build.
- Hardest challenge
The awkward part was ordering. Env files aren't sorted, they have comments and blank lines that carry meaning to whoever wrote them, and my first version's output was a wall of unordered differences that was technically correct and useless. I rewrote the reporting twice. What finally worked was grouping by a prefix convention — most projects namespace their variables — and showing missing keys next to their nearest present sibling, so you can see the shape of the gap rather than a list. That took longer than the comparison engine.
- Result & impact
I use it in every project I work on, and it's caught real problems on three client engagements — one of them a missing key that would have taken down a payment webhook on a Friday deploy. It's a small tool with a small audience: a few hundred Homebrew installs and a modest number of GitHub stars, nothing that would impress anyone. The result I actually care about is that I've stopped having that particular bad hour.
- Who else worked on it
It's mostly a solo thing, but eleven people have contributed and two of them meaningfully. One added support for a configuration format I'd never used and then stayed to fix three bugs in my parser that only showed up with real files. Another rewrote my Homebrew formula after telling me, correctly, that mine only worked on his machine by accident. A colleague also reviewed the decision not to read values before I committed to it, and pushed me to write that reasoning into the README rather than just declining feature requests.