deno run --env-file: load a .env file into Deno.env
- tool
- Deno
- command
- deno run
- flag
- --env-file[=FILE]
- default
- off; without a value the flag reads .env from the current directory
- since
- 1.38.0
deno run --env-file --allow-env main.ts reads KEY=value lines from .env in the current directory and adds them to the environment before the program starts, so Deno.env.get("KEY") returns them. Pass a path (--env-file=.env.local) to load another file. The flag does not grant any permission: reading the variables still needs --allow-env. Variables that are already set in the shell take precedence over the file.
Example
cat > .env <<'EOF'
# comment
PORT=8080
GREETING="hello world"
EOF
cat > main.ts <<'EOF'
console.log(Deno.env.get("PORT"), Deno.env.get("GREETING"));
EOF
echo "--- without --env-file"
npx --yes deno@2 run --allow-env main.ts
echo "--- with --env-file"
npx --yes deno@2 run --env-file=.env --allow-env main.ts
echo "--- the shell wins over the file"
PORT=9000 npx --yes deno@2 run --env-file=.env --allow-env main.ts
echo "--- --env-file without --allow-env"
npx --yes deno@2 run --no-prompt --env-file=.env main.ts 2>&1 | grep -m1 NotCapableOutput
--- without --env-file undefined undefined --- with --env-file 8080 hello world --- the shell wins over the file 9000 hello world --- --env-file without --allow-env error: Uncaught (in promise) NotCapable: Requires env access to "PORT", run again with the --allow-env flag
Without the flag both values are undefined. With it, quotes around values are removed and comments are skipped. Without --allow-env the variables are loaded but the program is not allowed to read them.
Options
| Form | Effect |
|---|---|
| --env-file | Load .env from the current directory |
| --env-file=.env.local | Load the given file |
| --env-file=.env --env-file=.env.local | Load both; the later file overrides keys from the earlier one |
| --allow-env | Required to read any variable with Deno.env.get() |
| --allow-env=PORT,GREETING | Allow only these names (recommended) |
The flag works with deno run, deno serve, deno test, deno task and deno compile. With deno compile, the file is read when the binary is built: the values are embedded into the executable, so keep credentials out of files you compile.
Inside deno.json tasks
{
"tasks": {
"dev": "deno run --watch --env-file --allow-env=PORT,GREETING --allow-net main.ts"
}
}Scoping --allow-env to the names in the file keeps the security model useful: a dependency that tries to read other variables still fails. Permission flags are explained in Deno permission flags.
Pitfalls
- A missing file is an error when you name it explicitly; create an empty
.envin CI or drop the flag there. - Values are strings;
DEBUG=falseis the non-empty string"false". --env-filemust come before the script name, like every Deno flag; after it, the text ends up inDeno.args.- The older
std/dotenvmodule (jsr:@std/dotenv/load) does the same from code and also needs--allow-readfor the file; the flag avoids that read permission. - Without
--allow-envthe program fails withNotCapable: Requires env access, the env counterpart of Requires read access.
Node.js has an equivalent flag with the same precedence rules: node --env-file.
FAQ
Do I still need --allow-env with --env-file?
Yes. --env-file only puts the variables into the process environment. Reading them with Deno.env.get() is still an env access, so the program needs --allow-env (ideally scoped to the names it reads) or it fails with NotCapable.
Which file does --env-file load without a value?
The file .env in the current working directory. Pass a path to load another file, and repeat the flag to load several files; a later file overrides an earlier one.
Do variables in the shell override the .env file?
Yes. A variable that is already set in the environment keeps its value; the file only fills in variables that are missing, the same rule Node.js --env-file follows.