.env file: definition and meaning
A .env file is a plain text file of KEY=value pairs that a library, framework, or tool loads into a process’s environment at startup. Each tool defines its own rules, so quoting, expansion, and precedence depend on whatever reads it.
What it is
A .env file holds configuration as KEY=value pairs, usually one per line, kept next to the code but out of version control. A library or tool reads it at startup and adds the pairs to the process’s environment. The Node.js package dotenv does this for process.env, and Node.js itself can load a file with --env-file. The Twelve-Factor App advises storing config in the environment, strictly separate from code, and a .env file is a common way to fill that environment during development.
The file does nothing on its own. Something has to read it, and editing it has no effect on a process that is already running.
Parsers disagree
Each tool documents its own rules for quotes, comments, $VARIABLE references, and values that already exist in the environment, and those rules differ. Take this two-line file:
HOST_NAME=example.test
URL=http://${HOST_NAME}:3000| Reader | Value of URL |
|---|---|
Node.js 22.22.0, --env-file | http://${HOST_NAME}:3000 |
| python-dotenv 1.2.3 | http://example.test:3000 |
bash, set -a; . ./.env | http://example.test:3000 |
Swap the two lines and python-dotenv returns http://:3000, because it has not read HOST_NAME yet. These results come from a local run with those versions, and the bash row runs the file as shell code, so it is a reference point rather than a .env parser. In the same run, Node.js kept a HOST_NAME already set in the shell instead of the file’s value, which matches its documentation: when a variable is set in both places, the environment wins.
What to commit
The dotenv project’s FAQ answers no to committing a plaintext .env, with one exception: a file encrypted with dotenvx. Commit a .env.example that lists every key with a safe placeholder, and keep the real .env out of Git. A new teammate copies the example and fills in the values.
Keep secrets out of client bundles as well. By default, Vite exposes only variables prefixed VITE_ to your client code through import.meta.env. Treat anything exposed that way as public, because client code ships to the browser.
In Rig
env_diffcompares key names only, never values. It takes the first example file it finds from.env.example,.env.sample, and.env.template, and compares it with the keys in.env.local,.env, and the active env profile. When the project has acatalogId, it also compares against the cloud vault.fill_env_examplecopies missing keys, with the example’s default values, into.env. It never overwrites a key that already exists, mirrors the new keys into the active profile, and needs an approval click in Rig.- Env profiles are plain files at
<project>/.rig/env/{local,staging,production}.env. The local profile is seeded from.env.localor.env. - Env profiles are local only.
sync_secretsencrypts them on your machine and pushes ciphertext to the cloud vault.pull_secretsfetches the latest ciphertext, decrypts it on your machine, and writes the local profiles. Both need the project linked to the cloud catalog, full MCP access mode, and a click on Approve in Rig.
Related terms
Sources
- dotenv on GitHub
- Node.js documentation: Command-line API (--env-file)
- Node.js documentation: Environment Variables (.env file format)
- python-dotenv documentation
- The Twelve-Factor App: Config
- Vite guide: Env variables and modes
- Vite configuration: Shared options (envPrefix)
- Rig documentation: Masked env manager (env_diff, fill_env_example, and env profiles confirmed in Rig’s source code)
See how Rig fits in
Rig is a Mac app that starts, stops, and watches the processes in a project from one window. The knowledge base explains each part in plain language.