Skip to content

/flags/deno/deno-run-env-file

deno run --env-file: load a .env file into Deno.env

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
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

bash
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 NotCapable

Output

--- 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

FormEffect
--env-fileLoad .env from the current directory
--env-file=.env.localLoad the given file
--env-file=.env --env-file=.env.localLoad both; the later file overrides keys from the earlier one
--allow-envRequired to read any variable with Deno.env.get()
--allow-env=PORT,GREETINGAllow 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

json
{
  "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 .env in CI or drop the flag there.
  • Values are strings; DEBUG=false is the non-empty string "false".
  • --env-file must come before the script name, like every Deno flag; after it, the text ends up in Deno.args.
  • The older std/dotenv module (jsr:@std/dotenv/load) does the same from code and also needs --allow-read for the file; the flag avoids that read permission.
  • Without --allow-env the program fails with NotCapable: 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.

Sources