What this checks
Paste a .env file and it's parsed the same way the real dotenv npm package parses one — not a simplified approximation, the actual parsing rules, verified line by line against the real package. That matters because dotenv's behavior has a few sharp edges that don't show up until a value comes out wrong at runtime.
The headline one: an unquoted value is cut off at the first #, whether or not there's a space before it. API_PASSWORD=s3cr3t#backup doesn't set the password to s3cr3t#backup — it silently becomes s3cr3t, with #backup discarded as a comment. Wrapping the value in quotes (API_PASSWORD="s3cr3t#backup") is the fix, since quoted values keep # literally.
It also catches a duplicate key (dotenv keeps only the last one — the earlier value is silently gone), a key that isn't a valid identifier (breaks process.env.KEY dot access and shell export loading), an opening quote that's never closed anywhere later in the file (dotenv falls back to treating that line as unquoted rather than erroring), and a quoted value that spans several lines and swallows what look like other KEY=VALUE lines along the way — a real, surprising failure mode when a stray unmatched quote near the top of a file happens to find its match many lines later.
What it doesn't do
This intentionally doesn't support dotenv's obscure KEY: value colon-separator syntax (real, but rare enough that a line written this way is far more likely a typo for = than intentional) — those lines are flagged as missing an = here. It also doesn't expand $VAR references (core dotenv doesn't either — that's what the separate dotenv-expand package is for) or scan for hardcoded secrets; it's a parsing-correctness check, not a security scanner.
FAQ
Why does the # truncation happen even with a space before it?
It doesn't — dotenv's parser truncates at any # in an unquoted value regardless of what's next to it. This tool only warns about the cases where the # is directly attached to the preceding text (no space), since KEY=value # comment with a clear gap is almost always an intentional trailing comment working exactly as intended — flagging that too would just be noise.
Why is a hyphenated key only a warning, not an error?
dotenv itself accepts MY-KEY=value without complaint and sets it under that exact name — it's not invalid dotenv syntax. It only becomes a problem once something else tries to use it: a shell export, or JavaScript's process.env.MY-KEY, which doesn't even parse (it reads as subtraction). Bracket access, process.env["MY-KEY"], still works fine.