env-diff

Key-level .env compare & .env.example generator — entirely in your browser.

Your files never leave the device — this page makes zero network requests. Values are masked until you choose to reveal them.

the file you actually run with
what the project expects

Report

Generate .env.example

Blanks every value in your .env (left) while keeping keys, order, comments and export prefixes — safe to commit.

What env-diff actually checks

env-diff parses both panes with the same conservative dotenv-subset parser the npm package uses, then compares the parsed key sets — so the report ignores line order, comments and quote style (PORT="3000" and PORT=3000 compare as equal). It classifies every key as missing (in the reference but not your file), extra (in your file but undocumented), differing (same key, different value) or in sync, and separately flags duplicate keys (last assignment wins under dotenv semantics) and lines it will not guess at — ${VAR} interpolation, trailing-backslash continuations and malformed keys are reported as unparsed rather than silently dropped.

Values are treated as secrets. The diff core never emits a value for a differing key; the display masks every value to its first two characters until you flip “Reveal values”, and that reveal lives only in this page session — nothing is written to localStorage, cookies or anywhere else. The honest limit: because interpolated values like REDIS_URL=${HOST}:6379 are kept literal and unexpanded, env-diff can’t tell you whether they would resolve to the same value — it flags them instead.

The parser’s honest limits. The .env “format” has no single standard, so env-diff parses the common dotenv subset and is deliberately conservative — it never guesses. It is not a shell parser: it understands KEY=value, export KEY=value and single- or double-quoted values, and that’s it. There is no multiline support (a line ending in a trailing backslash is reported as an unsupported continuation, never joined), no escape-sequence decoding inside quotes (a double-quoted \n stays the two characters \ and n), and no inline comment stripping — a # is a comment only when it is the first non-blank character of a line, so in KEY=val # note the # note stays part of the value rather than the parser guessing where an unquoted value ends. When keys repeat, diffing uses the effective last-assignment-wins value (matching dotenv runtime semantics) while still surfacing the duplicates separately. Anything else lands in the unparsed list with a plain-language reason — the tool would rather tell you it didn’t understand a line than pretend it did.