Skip to content

One documented home for every setting

Keep configuration in the environment, and document every variable in a committed example file.

EngineersSystem designersvercelawsdockerkubernetesnodepython

Configuration is the part of a system that differs between environments, which makes it the part most likely to be wrong in the one you cannot see. An undocumented variable is discovered by a crash in production; a committed example file turns the same discovery into a diff. It is also the single fastest way to make a repository set-up-able by someone who did not build it.

What goes wrong: A deploy that boots and then fails on the first request because one variable nobody documented was never set.

You are violating it when

  • No `.env.example` or equivalent is committed.
  • A new environment is configured by copying from an old one.
  • Settings live in three places and the precedence is folklore.

The usual objection: That configuration belongs in a config file in the repo. Anything that differs per environment cannot live in a file that is the same in every environment.

A repository needs one obvious contract for runtime knobs: the names, expected shape, and safe example values of everything the process reads from its environment. Real values can live in the deployment platform, a local shell, a secrets manager, or a developer-only file, but the list of variables belongs in version control so changes are reviewed like any other interface change.

This works because configuration is where environments intentionally diverge. Code can be promoted from development to staging to production unchanged, while the environment supplies different URLs, feature flags, credentials, regions, and limits. A committed example file makes missing or renamed variables visible in a pull request instead of at boot time or on the first production request.

The misconception is that configuration belongs in a config file in the repo. That is only safe for values that are truly the same everywhere. Once a value changes by deploy, committing it either leaks a secret, couples the codebase to one environment, or creates a shadow system of overrides that nobody can reason about.

When an agent is writing code, the documented example file becomes part of the promptable interface of the repo. It gives the agent a place to add a new variable name without inventing a secret, and it reduces the chance that the agent hardcodes a value, creates a second configuration mechanism, or leaves setup knowledge only in generated prose.

Install it

npx klay practices add config-in-one-place
  • .env.examplecreate
    # Klay practice: config-in-one-place
    # https://klaylearn.com/practices/config-in-one-place
    #
    # This file is COMMITTED. `.env` is not — see .gitignore.
    #
    # Its job is to ENUMERATE, not to provision. Every variable the application
    # reads appears here, with a one-line note on what it is for and what happens
    # when it is missing. Never a real value: not a test key, not a "throwaway"
    # token, not a staging password.
    #
    # The test of this file: someone who has never seen the repository copies it to
    # .env, fills in the blanks, and the application starts.
    
    # ── required — the app will not start without these ─────────────────────────

The previews are the first lines of each file; the command writes them in full. Existing files are never overwritten.

How you know it stuck

npx klay practices audit reports this check for this practice:

  • env-example-present

Where this comes from

  1. The Twelve-Factor AppThe Twelve-Factor App · Official docsCanonical definition: config varies by deploy and environment variables keep it out of code.
  2. Best practices for working with environment variables in Docker ComposeDocker Docs · Official docsAdds the practical committed-file workflow and warns about silent precedence conflicts.
  3. Environment variablesVercel Docs · Official docsShows a current platform model where values differ remotely but can be pulled locally.
  4. [DL.EAC.4] Implement continuous configuration for enhanced application management - DevOps GuidanceAWS Well-Architected · Official docsFrames separated configuration as operational architecture and cautions against sprawling configuration surfaces.
  5. Security-Focused Guide for AI Code Assistant InstructionsOpenSSF Best Practices · Engineering blogTranslates the practice into standing instructions that AI coding assistants can follow.

Questions

Do I put real values in .env.example?
Never. Names, a one-line comment on what each is for, and a safe placeholder. The file's job is to enumerate, not to provision.