TL;DR
- .env files are executable configuration, not throwaway text files, so they deserve the same validation discipline as application code.
- Many production bugs come from silent env mistakes: duplicate keys, missing example entries, bad formatting, or values copied into the wrong environment.
- A useful env linter separates hard failures from warnings, so teams get guardrails without killing velocity.
- The best implementation runs automatically on push and pull instead of relying on developers to remember another command.
Why linting .env files matters
Teams lint TypeScript, format Markdown, type-check API schemas, and validate build outputs. Then they leave their most sensitive configuration format completely unvalidated. That mismatch is strange once you look closely at how much production behavior depends on environment variables.
An env file controls database connections, auth providers, third-party billing, feature flags, S3 buckets, signing keys, and deployment mode. If a code file is wrong, you usually get a compiler error or a failed test. If an env file is wrong, the application may still boot and only fail after a partial deploy, a flaky worker restart, or a weekend incident.
The bug is often not "the value is missing." The bug is "the wrong value looked plausible enough to survive code review."
The failures a linter can catch
Good env linting is not about style policing. It is about catching the awkward class of problems that humans routinely miss in flat key-value files.
Formatting and parser problems
- invalid
KEY=VALUEsyntax - unquoted values with spaces or shell-sensitive characters
- duplicate keys where the later entry silently overrides the first
- lowercase or inconsistent key names that diverge from team conventions
Operational problems
- a key exists in
.envbut not in.env.example, so new developers do not know it is required - a key is empty in production-bound config but non-empty locally
- a very long value suggests someone pasted a certificate or credential blob into the wrong place
- plaintext secret patterns appear where the team expected encrypted or referenced values
Error, warning, and info rules
The most useful lint model is severity-based. Not every problem should block a push, but some absolutely should.
- Error rules block the operation because the file is malformed, ambiguous, or obviously unsafe.
- Warning rules surface likely mistakes that deserve attention but may be intentional.
- Info rules suggest consistency and documentation improvements without interrupting the workflow.
$ slickenv push
✗ Error: lowercase key name: database_url
✗ Error: duplicate key: API_KEY
⚠ Warning: STRIPE_SECRET_KEY missing from .env.example
⚠ Warning: REDIS_URL has empty value
ℹ Info: consider adding @type and @visibility annotations
Push blocked: 2 errors, 2 warnings, 1 infoThis severity split matters because it keeps the tool credible. If everything blocks deploys, developers stop trusting it. If nothing blocks deploys, the tool becomes a dashboard nobody reads.
What good lint output looks like
Lint output should explain the problem and the likely fix, not just name the rule. Developers should not have to read the docs every time the checker fails.
# Bad
duplicate-key
# Better
✗ Error: duplicate key "DATABASE_URL"
First defined at line 4
Redefined at line 19
Result: most dotenv parsers will keep the later value only
Suggested fix:
remove one definition or rename the environment-specific keyThe ideal env linter feels more like a deployment reviewer than a syntax checker. It explains what operational risk the mistake creates.
Why env linting belongs in the normal workflow
Manual lint commands do not survive real engineering teams. People forget them. They skip them under deadline pressure. They assume CI will catch the problem later. The best place for env linting is inside the commands developers already run.
- run linting on
slickenv pushbefore new values are synchronized - run compatibility checks on
slickenv pullso local files do not drift silently from remote state - combine env linting with pre-commit secret protection and CI scanning
- pair it with version history for environment variables so mistakes are auditable and reversible
This is especially important for teams onboarding non-experts, contractors, or product-minded builders who are now shipping code through AI tools. The env file is often the least reviewed and most dangerous configuration surface in the repo.
For baseline conventions, the Twelve-Factor App env guidance is still worth revisiting: 12factor.net/config. Then bring that philosophy into a workflow that enforces the boring but expensive details.