dotenv-linter
dotenv-linter Tool Analysis
Overview
dotenv-linter is a fast, Rust-based linter and fixer
for .env files. It detects common mistakes such as duplicate keys, lowercase keys,
incorrect delimiters, unordered keys, and stray whitespace, and can auto-fix most of
them in place. This analysis documents Lintro’s wrapper implementation and how it maps
onto the core tool.
Core Tool Capabilities
dotenv-linter (v4.0.0) is invoked through subcommands:
dotenv-linter check <files>— report issues (exit code1when problems are found).dotenv-linter fix <files>— auto-fix issues in place (creates.env.bakbackups unless--no-backupis passed;--dry-runprints the fixed content instead).dotenv-linter diff <files>— compare key sets across files.
Checks include: DuplicatedKey, EndingBlankLine, ExtraBlankLine,
IncorrectDelimiter, KeyWithoutValue, LeadingCharacter, LowercaseKey,
QuoteCharacter, SchemaViolation, SpaceCharacter, SubstitutionKey,
TrailingWhitespace, UnorderedKey, and ValueWithoutQuotes.
Output format
check --plain emits one diagnostic per line plus a header and summary:
Checking .env
.env:2 LowercaseKey: The foo key should be in uppercase
.env:3 KeyWithoutValue: The BAR key should be with a value or have an equal sign
.env:4 LeadingCharacter: Invalid leading character detected
Found 3 problems
Diagnostic lines follow the shape filename:line CheckName: message. There is no
column component, and (as of v4.0.0) no SARIF or JSON output in any released
version.
Parser Choice: Native Parser
Following the SARIF ingestion evaluation guidance (issue #1066 / PR #1140): the shared
SARIF parser is only used when a tool emits SARIF losslessly. dotenv-linter emits no
SARIF or structured output at all — only plain-text (--plain) or ANSI-colored
diagnostics. A native line parser is therefore required.
lintro/parsers/dotenv_linter/dotenv_linter_parser.py parses the plain-text lines with
a single regex, strips ANSI codes defensively, and ignores the Checking … header and
Found N problems / No problems found summary lines. It captures the check name
(code), line number, and message with full fidelity. Because there is no upstream
SARIF, nothing is “dropped” relative to a SARIF path — the native parser is strictly
more faithful than any SARIF ingestion would be.
Lintro Implementation Analysis
Preserved Features
- Check mode: runs
dotenv-linter check --plainper file and parses all findings. - Fix mode: runs
dotenv-linter fix --no-backup --plainper file, bracketed by a pre-fix check and a post-fix re-check so theinitial == fixed + remainingToolResult invariant holds even for checks that cannot be auto-fixed. - Check name as code: each issue carries the dotenv-linter check name, surfaced in
the unified table’s
codecolumn. - Documentation links:
doc_url()converts a CamelCase check name to the snake_case anchor used by the docs site, e.g.LowercaseKey→https://dotenv-linter.github.io/#/checks/lowercase_key. - Options:
recursive,exclude,skip_checks(maps to--ignore-checks), andschema(maps to--schema).
Notable Behaviors
- No column data: dotenv-linter does not report columns, so the
columnfield is always0(rendered as-). - Backups suppressed: fix always passes
--no-backupso Lintro does not leave.env.bakartifacts in the working tree. - Severity: dotenv-linter treats all findings uniformly; Lintro maps them to the
warningseverity level.
Installation
- Homebrew:
brew install dotenv-linter - Cargo:
cargo install dotenv-linter - Binary release: https://github.com/dotenv-linter/dotenv-linter/releases (v4.0.0+)
File Targeting
Lintro discovers .env, .env.*, and *.env files. Note that repositories commonly
.gitignore real .env files; Lintro’s own .lintro-ignore also excludes
test_samples/, so the bundled sample fixtures are only exercised via the binary-gated
integration tests.