Source an env file into the current shell
Load variables from a `.env`-style file into the current shell session — for project-specific secrets, dev-mode flags, and tool-version locks.
How to source an env file into the current shell in each shell
source .env`source` and `.` are synonyms (POSIX uses `.`; bash added `source` for readability). The file must be VALID BASH — `KEY=VAL`, optionally `export KEY=VAL`. Lines starting with `#` are comments. Values with spaces need quotes: `KEY="my value"`.
source .envbass source .envFish CANNOT source bash files directly (different syntax). `bass` (`oh-my-fish` plugin) runs the bash file in a subshell, captures exported vars, sets them in fish. For pure-fish env files use `set -gx KEY value` syntax and `source` directly.
. ./.env.ps1pwsh `. file` (dot-sourcing) executes the file IN THE CURRENT SCOPE — variable assignments persist. The file must be VALID pwsh: `$env:KEY = "value"`. For bash-style `.env` files: write a parser `Get-Content .env | ForEach-Object { if ($_ -match "^([^=]+)=(.+)$") { Set-Item "env:$($Matches[1])" $Matches[2] } }`.
for /f "tokens=1,2 delims==" %a in (.env) do set "%a=%b"cmd has no native source. The `for /f` loop parses KEY=VAL lines and `set`s each. Quotes in `.env` are NOT stripped — `KEY="value"` becomes `KEY` = `"value"` (with quotes). Strip first: `set "%a=%b:"=%"`.
Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.
Gotchas & notes
- **bash `.` vs `source`** are 100% equivalent (`.` is the POSIX form, `source` is the bash extension). Both EXECUTE the file in the current shell — meaning anything that file does (cd, alias, function definition, exit) affects YOUR shell. This is dangerous for untrusted env files — `source untrusted.env` can run `rm -rf ~/`. Always inspect first; for production use a dedicated parser (`dotenv` libraries) that READ-ONLY parses KEY=VAL and never executes.
- **fish CANNOT source bash files** — different syntax (`export` doesn't exist in fish; arrays use `set var a b c` not `var=(a b c)`; arithmetic `$((expr))` doesn't exist). The `bass` plugin works around this by running the file in a real bash subshell, dumping `env` after execution, and replaying the diff into fish via `set -gx`. For pure-fish env files: write `set -gx KEY value` directly and `source file.fish`. Many tools (asdf, nvm, rbenv) ship fish-specific files; check for `*.fish` variants before reaching for bass.
- pwsh dot-sourcing (`. file.ps1`) vs running (`./file.ps1`): the dot makes the file execute IN the current scope (vars + funcs persist); without the dot, the file runs in a CHILD scope and its variable assignments evaporate when it returns. Common mistake: `./setup.ps1` "doesn't work" because the script set `$env:FOO` which evaporates — but `$env:` prefixed vars actually persist across child scopes (they're process env vars, not pwsh scope vars). Plain `$VAR =` requires dot-sourcing to persist. Rule: dot-source for "load these definitions into my session"; run normally for "execute this script".
- KEY=VAL parsing edge cases (the reason "just write your own .env loader" is harder than it looks): (1) `KEY="value with spaces"` — strip the quotes; (2) `KEY=value # inline comment` — strip trailing comment but ONLY OUTSIDE quotes (`KEY="hash # inside"` should keep the `#`); (3) `KEY=\\$LITERAL` — preserve literal `$` (don't expand); (4) `KEY=$OTHER` — expand or not? (most `.env` libraries expand; bash `source` always expands); (5) `KEY=` (empty value) — bash creates an empty var, some loaders skip the line; (6) multi-line values via continued `\` at end of line — bash supports, naive parsers don't. The `dotenv` npm package and Python `python-dotenv` handle all of these — for production, lean on them rather than rolling your own.
Related commands
Related tasks
- Prepend a directory to PATH— Add a directory to the FRONT of PATH so commands inside it override system equivalents — for tool-version pinning (node@18 vs system node) and local-bin priorities.
- List all shell aliases— Print every alias currently defined in the shell — for debugging "why does `ls` behave differently here" and auditing dotfiles.
- Show the file path of a command— Print where on the filesystem a command resolves to — for debugging PATH issues, version mismatches, and "which python is this".