包详细信息

@dotenvx/dotenvx

dotenvx1.9mBSD-3-Clause1.45.1

a better dotenv–from the creator of dotenv

dotenv, env

自述文件

dotenvx

a better dotenv–from the creator of dotenv.

  • run anywhere (cross-platform)
  • multi-environment
  • encrypted envs

Read the whitepaper

 

Quickstart npm version downloads test suite

Install and use it in code just like dotenv.

npm install @dotenvx/dotenvx --save
// index.js
require('@dotenvx/dotenvx').config()
// or import '@dotenvx/dotenvx/config' // for esm

console.log(`Hello ${process.env.HELLO}`)

 

or install globally - unlocks dotenv for any language, framework, or platform!

<summary>with curl 🌐 </summary>
sh curl -sfS https://dotenvx.sh | sh dotenvx help curl installs  
<summary>with brew 🍺</summary>
sh brew install dotenvx/brew/dotenvx dotenvx help brew installs  
<summary>with docker 🐳</summary>
sh docker run -it --rm -v $(pwd):/app dotenv/dotenvx help docker pulls  
<summary>with github releases 🐙</summary>
sh curl -L -o dotenvx.tar.gz "https://github.com/dotenvx/dotenvx/releases/latest/download/dotenvx-$(uname -s)-$(uname -m).tar.gz" tar -xzf dotenvx.tar.gz ./dotenvx help github releases  
<summary>or windows 🪟</summary>
sh winget install dotenvx dotenvx help

 

Run Anywhere

$ echo "HELLO=World" > .env
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ node index.js
Hello undefined # without dotenvx

$ dotenvx run -- node index.js
Hello World # with dotenvx
> :-D

see extended quickstart guide

More examples

  • <summary>TypeScript 📘</summary>
    json // package.json { "type": "module", "dependencies": { "chalk": "^5.3.0" } } js // index.ts import chalk from 'chalk' console.log(chalk.blue(`Hello ${process.env.HELLO}`)) sh $ npm install $ echo "HELLO=World" > .env $ dotenvx run -- npx tsx index.ts Hello World
  • <summary>Deno 🦕</summary>
    sh $ echo "HELLO=World" > .env $ echo "console.log('Hello ' + Deno.env.get('HELLO'))" > index.ts $ deno run --allow-env index.ts Hello undefined $ dotenvx run -- deno run --allow-env index.ts Hello World > [!WARNING] > Some of you are attempting to use the npm module directly with deno run. Don't, because deno currently has incomplete support for these encryption ciphers. > > > $ deno run -A npm:@dotenvx/dotenvx encrypt > Unknown cipher > > > Instead, use dotenvx as designed, by installing the cli as a binary - via curl, brew, etc.
  • <summary>Bun 🥟</summary>
    sh $ echo "HELLO=Test" > .env.test $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ bun index.js Hello undefined $ dotenvx run -f .env.test -- bun index.js Hello Test
  • <summary>Python 🐍</summary>
    sh $ echo "HELLO=World" > .env $ echo 'import os;print("Hello " + os.getenv("HELLO", ""))' > index.py $ dotenvx run -- python3 index.py Hello World see extended python guide
  • <summary>PHP 🐘</summary>
    sh $ echo "HELLO=World" > .env $ echo '<?php echo "Hello {$_SERVER["HELLO"]}\n";' > index.php $ dotenvx run -- php index.php Hello World see extended php guide
  • <summary>Ruby 💎</summary>
    sh $ echo "HELLO=World" > .env $ echo 'puts "Hello #{ENV["HELLO"]}"' > index.rb $ dotenvx run -- ruby index.rb Hello World see extended ruby guide
  • <summary>Go 🐹</summary>
    sh $ echo "HELLO=World" > .env $ echo 'package main; import ("fmt"; "os"); func main() { fmt.Printf("Hello %s\n", os.Getenv("HELLO")) }' > main.go $ dotenvx run -- go run main.go Hello World see extended go guide
  • <summary>Rust 🦀</summary>
    sh $ echo "HELLO=World" > .env $ echo 'fn main() {let hello = std::env::var("HELLO").unwrap_or("".to_string());println!("Hello {hello}");}' > src/main.rs $ dotenvx run -- cargo run Hello World see extended rust guide
  • <summary>Java ☕️</summary>
    sh $ echo "HELLO=World" > .env $ echo 'public class Index { public static void main(String[] args) { System.out.println("Hello " + System.getenv("HELLO")); } }' > index.java $ dotenvx run -- java index.java Hello World
  • <summary>Clojure 🌿</summary>
    sh $ echo "HELLO=World" > .env $ echo '(println "Hello" (System/getenv "HELLO"))' > index.clj $ dotenvx run -- clojure -M index.clj Hello World
  • <summary>Kotlin 📐</summary>
    sh $ echo "HELLO=World" > .env $ echo 'fun main() { val hello = System.getenv("HELLO") ?: ""; println("Hello $hello") }' > index.kt $ kotlinc index.kt -include-runtime -d index.jar $ dotenvx run -- java -jar index.jar Hello World
  • <summary>.NET 🔵</summary>
    sh $ dotnet new console -n HelloWorld -o HelloWorld $ cd HelloWorld $ echo "HELLO=World" | Out-File -FilePath .env -Encoding utf8 $ echo 'Console.WriteLine($"Hello {Environment.GetEnvironmentVariable("HELLO")}");' > Program.cs $ dotenvx run -- dotnet run Hello World
  • <summary>Bash 🖥️</summary>
    sh $ echo "HELLO=World" > .env $ dotenvx run --quiet -- sh -c 'echo Hello $HELLO' Hello World
  • <summary>Fish 🐠</summary>
    sh $ echo "HELLO=World" > .env $ dotenvx run --quiet -- sh -c 'echo Hello $HELLO' Hello World
  • <summary>Cron ⏰</summary>
    sh # run every day at 8am 0 8 * * * dotenvx run -- /path/to/myscript.sh
  • <summary>Frameworks ▲</summary>
    sh $ dotenvx run -- next dev $ dotenvx run -- npm start $ dotenvx run -- bin/rails s $ dotenvx run -- php artisan serve see framework guides
  • <summary>Docker 🐳</summary>
    sh $ docker run -it --rm -v $(pwd):/app dotenv/dotenvx run -- node index.js Or in any image: sh FROM node:latest RUN echo "HELLO=World" > .env && echo "console.log('Hello ' + process.env.HELLO)" > index.js RUN curl -fsS https://dotenvx.sh/install.sh | sh CMD ["dotenvx", "run", "--", "echo", "Hello $HELLO"] see docker guide
  • <summary>CI/CDs 🐙</summary>
    yaml name: build on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 - run: curl -fsS https://dotenvx.sh/install.sh | sh - run: dotenvx run -- node build.js env: DOTENV_KEY: ${{ secrets.DOTENV_KEY }} see github actions guide
  • <summary>Platforms</summary>
    sh # heroku heroku buildpacks:add https://github.com/dotenvx/heroku-buildpack-dotenvx # docker RUN curl -fsS https://dotenvx.sh/install.sh | sh # vercel npm install @dotenvx/dotenvx --save see platform guides
  • <summary>Process Managers</summary>
    js // pm2 "scripts": { "start": "dotenvx run -- pm2-runtime start ecosystem.config.js --env production" }, see process manager guides
  • <summary>npx</summary>
    sh # alternatively use npx $ npx @dotenvx/dotenvx run -- node index.js $ npx @dotenvx/dotenvx run -- next dev $ npx @dotenvx/dotenvx run -- npm start
  • <summary>npm</summary>
    sh $ npm install @dotenvx/dotenvx --save json { "scripts": { "start": "./node_modules/.bin/dotenvx run -- node index.js" }, "dependencies": { "@dotenvx/dotenvx": "^0.5.0" } } sh $ npm run start > start > ./node_modules/.bin/dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.production Hello World
  • <summary>asdf</summary>
    sh # use dotenvx with asdf $ asdf plugin add dotenvx $ asdf install dotenvx latest thank you @jgburet of Paris 🇫🇷
  • <summary>Git</summary>
    sh # use as a git submodule $ git dotenvx run -- node index.js $ git dotenvx run -- next dev $ git dotenvx run -- npm start
  • <summary>Variable Expansion</summary>
    Reference and expand variables already on your machine for use in your .env file. ini # .env USERNAME="username" DATABASE_URL="postgres://${USERNAME}@localhost/my_database" js // index.js console.log('DATABASE_URL', process.env.DATABASE_URL) sh $ dotenvx run --debug -- node index.js [dotenvx@0.14.1] injecting env (2) from .env DATABASE_URL postgres://username@localhost/my_database
  • <summary>Command Substitution</summary>
    Add the output of a command to one of your variables in your .env file. ini # .env DATABASE_URL="postgres://$(whoami)@localhost/my_database" js // index.js console.log('DATABASE_URL', process.env.DATABASE_URL) sh $ dotenvx run --debug -- node index.js [dotenvx@0.14.1] injecting env (1) from .env DATABASE_URL postgres://yourusername@localhost/my_database

 

Multiple Environments

Create a .env.production file and use -f to load it. It's straightforward, yet flexible. ```sh $ echo "HELLO=production" > .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ dotenvx run -f .env.production -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.production Hello production

^^ ```

More examples

  • <summary>multiple .env files</summary>
    sh $ echo "HELLO=local" > .env.local $ echo "HELLO=World" > .env $ dotenvx run -f .env.local -f .env -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.local,.env Hello local Note subsequent files do NOT override pre-existing variables defined in previous files or env. This follows historic principle. For example, above local wins – from the first file.
  • <summary>--overload flag</summary>

    $ echo "HELLO=local" > .env.local
    
    $ echo "HELLO=World" > .env
    
    $ dotenvx run -f .env.local -f .env --overload -- node index.js
    [dotenvx@1.X.X] injecting env (1) from .env.local,.env
    Hello World
    

    Note that with --overload subsequent files DO override pre-existing variables defined in previous files.

  • <summary>--verbose flag</summary>

    $ echo "HELLO=production" > .env.production
    
    $ dotenvx run -f .env.production --verbose -- node index.js
    [dotenvx][verbose] injecting env from /path/to/.env.production
    [dotenvx][verbose] HELLO set
    [dotenvx@1.X.X] injecting env (1) from .env.production
    Hello production
    
  • <summary>--debug flag</summary>
    sh $ echo "HELLO=production" > .env.production $ dotenvx run -f .env.production --debug -- node index.js [dotenvx][debug] configuring options [dotenvx][debug] {"envFile":[".env.production"]} [dotenvx][verbose] injecting env from /path/to/.env.production [dotenvx][debug] reading env from /path/to/.env.production [dotenvx][debug] parsing env from /path/to/.env.production [dotenvx][debug] {"HELLO":"production"} [dotenvx][debug] writing env from /path/to/.env.production [dotenvx][verbose] HELLO set [dotenvx][debug] HELLO set to production [dotenvx@1.X.X] injecting env (1) from .env.production Hello production
  • <summary>--quiet flag</summary>
    Use --quiet to suppress all output (except errors). sh $ echo "HELLO=production" > .env.production $ dotenvx run -f .env.production --quiet -- node index.js Hello production
  • <summary>--log-level flag</summary>
    Set --log-level to whatever you wish. For example, to suppress warnings (risky), set log level to error: sh $ echo "HELLO=production" > .env.production $ dotenvx run -f .env.production --log-level=error -- node index.js Hello production Available log levels are error, warn, info, verbose, debug, silly
  • <summary>--convention flag</summary>
    Load envs using Next.js' convention or dotenv-flow convention. Set --convention to nextjs or flow: sh $ echo "HELLO=development local" > .env.development.local $ echo "HELLO=local" > .env.local $ echo "HELLO=development" > .env.development $ echo "HELLO=env" > .env $ dotenvx run --convention=nextjs -- node index.js Hello development local $ dotenvx run --convention=flow -- node index.js Hello development local (more conventions available upon request)

 

Encryption

Add encryption to your .env files with a single command. Use dotenvx encrypt.

$ dotenvx encrypt
✔ encrypted (.env)

encrypted .env

A DOTENV_PUBLIC_KEY (encryption key) and a DOTENV_PRIVATE_KEY (decryption key) are generated using the same public-key cryptography as Bitcoin.

More examples

  • <summary>.env</summary>
    sh $ echo "HELLO=World" > .env $ dotenvx encrypt $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (2) from .env Hello World
  • <summary>.env.production</summary>
    sh $ echo "HELLO=Production" > .env.production $ dotenvx encrypt -f .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (2) from .env.production Hello Production Note the DOTENV_PRIVATE_KEY_PRODUCTION ends with _PRODUCTION. This instructs dotenvx run to load the .env.production file.
  • <summary>.env.ci</summary>
    sh $ echo "HELLO=Ci" > .env.ci $ dotenvx encrypt -f .env.ci $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ DOTENV_PRIVATE_KEY_CI="<.env.ci private key>" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (2) from .env.ci Hello Ci Note the DOTENV_PRIVATE_KEY_CI ends with _CI. This instructs dotenvx run to load the .env.ci file. See the pattern?
  • <summary>combine multiple encrypted .env files</summary>
    sh $ dotenvx set HELLO World -f .env $ dotenvx set HELLO Production -f .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ DOTENV_PRIVATE_KEY="<.env private key>" DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (3) from .env, .env.production Hello World Note the DOTENV_PRIVATE_KEY instructs dotenvx run to load the .env file and the DOTENV_PRIVATE_KEY_PRODUCTION instructs it to load the .env.production file. See the pattern?
  • <summary>combine multiple encrypted .env files for monorepo</summary>
    sh $ mkdir app1 $ mkdir app2 $ dotenvx set HELLO app1 -f app1/.env.ci $ dotenvx set HELLO app2 -f app2/.env.ci $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ DOTENV_PRIVATE_KEY_CI="<app1/privat ci key>,<app2/private ci key>" dotenvx run -f app1/.env.ci -f app2/.env.ci -- node index.js [dotenvx@1.X.X] injecting env (2) from app1/.env.ci,app2/.env.ci Hello app1 $ DOTENV_PRIVATE_KEY_CI="<app1/privat ci key>,<app2/private ci key>" dotenvx run -f app1/.env.ci -f app2/.env.ci --overload -- node index.js [dotenvx@1.X.X] injecting env (2) from app1/.env.ci,app2/.env.ci Hello app2 Note the DOTENV_PRIVATE_KEY_CI (and any DOTENV_PRIVATE_KEY*) can take multiple private keys by simply comma separating them.
  • <summary>--stdout</summary>
    sh $ echo "HELLO=World" > .env $ dotenvx encrypt --stdout $ dotenvx encrypt --stdout > .env.encrypted
  • <summary>other curves</summary>
    > secp256k1 is a well-known and battle tested curve, in use with Bitcoin and other cryptocurrencies, but we are open to adding support for more curves. > > If your organization's compliance department requires NIST approved curves or other curves like curve25519, please reach out at security@dotenvx.com.

 

Advanced

Become a dotenvx power user.

CLI 📟

Advanced CLI commands.

  • <summary>run - Variable Expansion</summary>
    Reference and expand variables already on your machine for use in your .env file. ini # .env USERNAME="username" DATABASE_URL="postgres://${USERNAME}@localhost/my_database" js // index.js console.log('DATABASE_URL', process.env.DATABASE_URL) sh $ dotenvx run --debug -- node index.js [dotenvx@1.X.X] injecting env (2) from .env DATABASE_URL postgres://username@localhost/my_database
  • <summary>run - Command Substitution</summary>
    Add the output of a command to one of your variables in your .env file. ini # .env DATABASE_URL="postgres://$(whoami)@localhost/my_database" js // index.js console.log('DATABASE_URL', process.env.DATABASE_URL) sh $ dotenvx run --debug -- node index.js [dotenvx@1.X.X] injecting env (1) from .env DATABASE_URL postgres://yourusername@localhost/my_database
  • <summary>run - Shell Expansion</summary>
    Prevent your shell from expanding inline $VARIABLES before dotenvx has a chance to inject it. Use a subshell. sh $ dotenvx run --env="HELLO=World" -- sh -c 'echo Hello $HELLO' Hello World
  • <summary>run - Multiline</summary>
    Dotenvx supports multiline values. This is particularly useful in conjunction with Docker - which does not support multiline values. ini # .env MULTILINE_PEM="-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNl1tL3QjKp3DZWM0T3u LgGJQwu9WqyzHKZ6WIA5T+7zPjO1L8l3S8k8YzBrfH4mqWOD1GBI8Yjq2L1ac3Y/ bTdfHN8CmQr2iDJC0C6zY8YV93oZB3x0zC/LPbRYpF8f6OqX1lZj5vo2zJZy4fI/ kKcI5jHYc8VJq+KCuRZrvn+3V+KuL9tF9v8ZgjF2PZbU+LsCy5Yqg1M8f5Jp5f6V u4QuUoobAgMBAAE= -----END PUBLIC KEY-----" js // index.js console.log('MULTILINE_PEM', process.env.MULTILINE_PEM) sh $ dotenvx run -- node index.js MULTILINE_PEM -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNl1tL3QjKp3DZWM0T3u LgGJQwu9WqyzHKZ6WIA5T+7zPjO1L8l3S8k8YzBrfH4mqWOD1GBI8Yjq2L1ac3Y/ bTdfHN8CmQr2iDJC0C6zY8YV93oZB3x0zC/LPbRYpF8f6OqX1lZj5vo2zJZy4fI/ kKcI5jHYc8VJq+KCuRZrvn+3V+KuL9tF9v8ZgjF2PZbU+LsCy5Yqg1M8f5Jp5f6V u4QuUoobAgMBAAE= -----END PUBLIC KEY-----
  • <summary>run - Contextual Help</summary>
    Unlike other dotenv libraries, dotenvx attempts to unblock you with contextual help. For example, when missing a custom .env file: sh $ dotenvx run -f .env.missing -- echo $HELLO [MISSING_ENV_FILE] missing .env.missing file (/Users/scottmotte/Code/dotenvx/playground/apr-16/.env.missing) [MISSING_ENV_FILE] https://github.com/dotenvx/dotenvx/issues/484 and re-run [dotenvx run -- echo] or when missing a KEY: sh $ echo "HELLO=World" > .env $ dotenvx get GOODBYE [MISSING_KEY] missing GOODBYE key
  • <summary>run - multiple -f flags</summary>
    Compose multiple .env files for environment variables loading, as you need. sh $ echo "HELLO=local" > .env.local $ echo "HELLO=World" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.local -f .env -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.local, .env Hello local Note subsequent files do NOT override pre-existing variables defined in previous files or env. This follows historic principle. For example, above local wins – from the first file.
  • <summary>run --env HELLO=String</summary>
    Set environment variables as a simple KEY=value string pair. sh $ echo "HELLO=World" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run --env HELLO=String -f .env -- node index.js [dotenvx@1.X.X] injecting env (1) from .env, and --env flag Hello String
  • <summary>run --overload</summary>
    Override existing env variables. These can be variables already on your machine or variables loaded as files consecutively. The last variable seen will 'win'. sh $ echo "HELLO=local" > .env.local $ echo "HELLO=World" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.local -f .env --overload -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.local, .env Hello World Note that with --overload subsequent files DO override pre-existing variables defined in previous files.
  • <summary>DOTENV_PRIVATE_KEY=key run</summary>
    Decrypt your encrypted .env by setting DOTENV_PRIVATE_KEY before dotenvx run. sh $ touch .env $ dotenvx set HELLO encrypted $ echo "console.log('Hello ' + process.env.HELLO)" > index.js # check your .env.keys files for your privateKey $ DOTENV_PRIVATE_KEY="122...0b8" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (2) from .env Hello encrypted
  • <summary>DOTENV_PRIVATE_KEY_PRODUCTION=key run</summary>
    Decrypt your encrypted .env.production by setting DOTENV_PRIVATE_KEY_PRODUCTION before dotenvx run. Alternatively, this can be already set on your server or cloud provider. sh $ touch .env.production $ dotenvx set HELLO "production encrypted" -f .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js # check .env.keys for your privateKey $ DOTENV_PRIVATE_KEY_PRODUCTION="122...0b8" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (2) from .env.production Hello production encrypted Note the DOTENV_PRIVATE_KEY_PRODUCTION ends with _PRODUCTION. This instructs dotenvx run to load the .env.production file.
  • <summary>DOTENV_PRIVATE_KEY_CI=key dotenvx run</summary>
    Decrypt your encrypted .env.ci by setting DOTENV_PRIVATE_KEY_CI before dotenvx run. Alternatively, this can be already set on your server or cloud provider. sh $ touch .env.ci $ dotenvx set HELLO "ci encrypted" -f .env.ci $ echo "console.log('Hello ' + process.env.HELLO)" > index.js # check .env.keys for your privateKey $ DOTENV_PRIVATE_KEY_CI="122...0b8" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (2) from .env.ci Hello ci encrypted Note the DOTENV_PRIVATE_KEY_CI ends with _CI. This instructs dotenvx run to load the .env.ci file. See the pattern?
  • <summary>DOTENV_PRIVATE_KEY=key DOTENV_PRIVATE_KEY_PRODUCTION=key run - Combine Multiple</summary>
    Decrypt your encrypted .env and .env.production files by setting DOTENV_PRIVATE_KEY and DOTENV_PRIVATE_KEY_PRODUCTION before dotenvx run. sh $ touch .env $ touch .env.production $ dotenvx set HELLO encrypted $ dotenvx set HELLO "production encrypted" -f .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js # check .env.keys for your privateKeys $ DOTENV_PRIVATE_KEY="122...0b8" DOTENV_PRIVATE_KEY_PRODUCTION="122...0b8" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (3) from .env, .env.production Hello encrypted $ DOTENV_PRIVATE_KEY_PRODUCTION="122...0b8" DOTENV_PRIVATE_KEY="122...0b8" dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (3) from .env.production, .env Hello production encrypted Compose any encrypted files you want this way. As long as a DOTENV_PRIVATE_KEY_${environment} is set, the values from .env.${environment} will be decrypted at runtime.
  • <summary>run --verbose</summary>
    Set log level to verbose. (log levels) sh $ echo "HELLO=production" > .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.production --verbose -- node index.js loading env from .env.production (/path/to/.env.production) HELLO set [dotenvx@1.X.X] injecting env (1) from .env.production Hello production
  • <summary>run --debug</summary>
    Set log level to debug. (log levels) sh $ echo "HELLO=production" > .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.production --debug -- node index.js process command [node index.js] options: {"env":[],"envFile":[".env.production"]} loading env from .env.production (/path/to/.env.production) {"HELLO":"production"} HELLO set HELLO set to production [dotenvx@1.X.X] injecting env (1) from .env.production executing process command [node index.js] expanding process command to [/opt/homebrew/bin/node index.js] Hello production
  • <summary>run --quiet</summary>
    Use --quiet to suppress all output (except errors). (log levels) sh $ echo "HELLO=production" > .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.production --quiet -- node index.js Hello production
  • <summary>run --log-level</summary>
    Set --log-level to whatever you wish. For example, to suppress warnings (risky), set log level to error: sh $ echo "HELLO=production" > .env.production $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.production --log-level=error -- node index.js Hello production Available log levels are error, warn, info, verbose, debug, silly (source)
  • <summary>run --strict</summary>
    Exit with code 1 if any errors are encountered - like a missing .env file or decryption failure. sh $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.missing --strict -- node index.js [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing) [MISSING_ENV_FILE] ? add one with [echo "HELLO=World" > .env.missing] This can be useful in ci scripts where you want to fail the ci if your .env file could not be decrypted at runtime.
  • <summary>run --ignore</summary>
    Ignore errors like MISSING_ENV_FILE. sh $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -f .env.missing --ignore=MISSING_ENV_FILE -- node index.js ...
  • <summary>run --convention=nextjs</summary>
    Load envs using Next.js' convention. Set --convention to nextjs: sh $ echo "HELLO=development local" > .env.development.local $ echo "HELLO=local" > .env.local $ echo "HELLO=development" > .env.development $ echo "HELLO=env" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run --convention=nextjs -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.local, .env.development, .env Hello development local (more conventions available upon request)
  • <summary>run --convention=flow</summary>
    Load envs using dotenv-flow's convention. Set --convention to flow: sh $ echo "HELLO=development local" > .env.development.local $ echo "HELLO=development" > .env.development $ echo "HELLO=local" > .env.local $ echo "HELLO=env" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ NODE_ENV=development dotenvx run --convention=flow -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.development, .env.local, .env Hello development local Further, we recommend using DOTENV_ENV over NODE_ENV– as dotenvx works everywhere, not just node. sh $ DOTENV_ENV=development dotenvx run --convention=flow -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.development, .env.local, .env Hello development local
  • <summary>run -fk</summary>
    Specify path to .env.keys. This is useful with monorepos. sh $ mkdir -p apps/app1 $ touch apps/app1/.env $ dotenvx set HELLO world -fk .env.keys -f apps/app1/.env $ dotenvx run -fk .env.keys -f apps/app1/.env -- yourcommand
  • <summary>get KEY</summary>
    Return a single environment variable's value. sh $ echo "HELLO=World" > .env $ dotenvx get HELLO World
  • <summary>get KEY -f</summary>
    Return a single environment variable's value from a specific .env file. sh $ echo "HELLO=World" > .env $ echo "HELLO=production" > .env.production $ dotenvx get HELLO -f .env.production production
  • <summary>get KEY -fk</summary>
    Specify path to .env.keys. This is useful with monorepos. sh $ mkdir -p apps/app1 $ touch apps/app1/.env $ dotenvx set HELLO world -fk .env.keys -f apps/app1/.env $ dotenvx get HELLO -fk .env.keys -f apps/app1/.env world
  • <summary>get KEY --env</summary>
    Return a single environment variable's value from a --env string. sh $ dotenvx get HELLO --env HELLO=String -f .env.production String
  • <summary>get KEY --overload</summary>
    Return a single environment variable's value where each found value is overloaded. sh $ echo "HELLO=World" > .env $ echo "HELLO=production" > .env.production $ dotenvx get HELLO -f .env.production --env HELLO=String -f .env --overload World
  • <summary>get KEY --strict</summary>
    Exit with code 1 if any errors are encountered - like a missing key, missing .env file, or decryption failure. sh $ dotenvx get DOES_NOT_EXIST --strict [MISSING_KEY] missing DOES_NOT_EXIST key
  • <summary>get KEY --convention=nextjs</summary>
    Return a single environment variable's value using Next.js' convention. Set --convention to nextjs: sh $ echo "HELLO=development local" > .env.development.local $ echo "HELLO=local" > .env.local $ echo "HELLO=development" > .env.development $ echo "HELLO=env" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx get HELLO --convention=nextjs development local
  • <summary>get KEY --convention=flow</summary>
    Return a single environment variable's value using dotenv-flow's convention. Set --convention to flow: sh $ echo "HELLO=development local" > .env.development.local $ echo "HELLO=development" > .env.development $ echo "HELLO=local" > .env.local $ echo "HELLO=env" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ NODE_ENV=development dotenvx get HELLO --convention=flow development local Further, we recommend using DOTENV_ENV over NODE_ENV– as dotenvx works everywhere, not just node. sh $ DOTENV_ENV=development dotenvx get HELLO --convention=flow development local
  • <summary>get (json)</summary>
    Return a json response of all key/value pairs in a .env file. sh $ echo "HELLO=World" > .env $ dotenvx get {"HELLO":"World"}
  • <summary>get --format shell</summary>
    Return a shell formatted response of all key/value pairs in a .env file. sh $ echo "HELLO=World" > .env $ echo "KEY=value" >> .env $ dotenvx get --format shell HELLO=World KEY=value This can be useful when combined with env on the command line. $ echo "console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)" > index.js $ env $(dotenvx get --format=shell) node index.js Hello value World or with export. $ echo "console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)" > index.js $ export $(dotenvx get --format=shell) $ node index.js Hello value World
  • <summary>get --format eval</summary>
    Return an eval-ready shell formatted response of all key/value pairs in a .env file. sh $ echo "HELLO=World" > .env $ echo "KEY=value" >> .env $ dotenvx get --format eval HELLO="World" KEY="value" Note that this exports newlines and quoted strings. This can be useful for more complex .env values (spaces, escaped characters, quotes, etc) combined with eval on the command line. sh $ echo "console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)" > index.js $ eval $(dotenvx get --format=eval) node index.js Hello value World Be careful with eval as it allows for arbitrary execution of commands. Prefer dotenvx run -- but in some cases eval is a sharp knife that is useful to have.
  • <summary>get --all</summary>
    Return preset machine envs as well. sh $ echo "HELLO=World" > .env $ dotenvx get --all {"PWD":"/some/file/path","USER":"username","LIBRARY_PATH":"/usr/local/lib", ..., "HELLO":"World"}
  • <summary>get --all --pretty-print</summary>
    Make the output more readable - pretty print it. sh $ echo "HELLO=World" > .env $ dotenvx get --all --pretty-print { "PWD": "/some/filepath", "USER": "username", "LIBRARY_PATH": "/usr/local/lib", ..., "HELLO": "World" }
  • <summary>set KEY value</summary>
    Set an encrypted key/value (on by default). sh $ touch .env $ dotenvx set HELLO World set HELLO with encryption (.env)
  • <summary>set KEY value -f</summary>
    Set an (encrypted) key/value for another .env file. sh $ touch .env.production $ dotenvx set HELLO production -f .env.production set HELLO with encryption (.env.production)
  • <summary>set KEY value -fk</summary>
    Specify path to .env.keys. This is useful with monorepos. sh $ mkdir -p apps/app1 $ touch apps/app1/.env $ dotenvx set HELLO world -fk .env.keys -f apps/app1/.env set HELLO with encryption (.env) Put it to use. sh $ dotenvx get -fk .env.keys -f apps/app1/.env Use it with a relative path. sh $ cd apps/app1 $ dotenvx get -fk ../../.env.keys -f .env
  • <summary>set KEY "value with spaces"</summary>
    Set a value containing spaces. sh $ touch .env.ci $ dotenvx set HELLO "my ci" -f .env.ci set HELLO with encryption (.env.ci)
  • <summary>set KEY -- "- + * ÷"</summary>
    If your value starts with a dash (-), then place two dashes instructing the cli that there are no more flag arguments. sh $ touch .env.ci $ dotenvx set HELLO -f .env.ci -- "- + * ÷" set HELLO with encryption (.env.ci)
  • <summary>set KEY value --plain</summary>
    Set a plaintext key/value. sh $ touch .env $ dotenvx set HELLO World --plain set HELLO (.env)
  • <summary>encrypt</summary>
    Encrypt the contents of a .env file to an encrypted .env file. sh $ echo "HELLO=World" > .env $ dotenvx encrypt ✔ encrypted (.env) ✔ key added to .env.keys (DOTENV_PRIVATE_KEY) ⮕ next run [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys ⮕ next run [DOTENV_PRIVATE_KEY='122...0b8' dotenvx run -- yourcommand] to test decryption locally
  • <summary>encrypt -f</summary>
    Encrypt the contents of a specified .env file to an encrypted .env file. sh $ echo "HELLO=World" > .env $ echo "HELLO=Production" > .env.production $ dotenvx encrypt -f .env.production ✔ encrypted (.env.production) ✔ key added to .env.keys (DOTENV_PRIVATE_KEY_PRODUCTION) ⮕ next run [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys ⮕ next run [DOTENV_PRIVATE_KEY='bff...bc4' dotenvx run -- yourcommand] to test decryption locally
  • <summary>encrypt -fk</summary>
    Specify path to .env.keys. This is useful with monorepos. sh $ mkdir -p apps/app1 $ echo "HELLO=World" > apps/app1/.env $ dotenvx encrypt -fk .env.keys -f apps/app1/.env ✔ encrypted (apps/app1/.env) Put it to use. sh $ dotenvx run -fk .env.keys -f apps/app1/.env Use with a relative path. sh $ cd apps/app1 $ dotenvx run -fk ../../.env.keys -f .env
  • <summary>encrypt -k</summary>
    Specify the key(s) to encrypt by passing --key. sh $ echo "HELLO=World\nHELLO2=Universe" > .env $ dotenvx encrypt -k HELLO2 ✔ encrypted (.env) Even specify a glob pattern. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt -k "HE*" ✔ encrypted (.env)
  • <summary>encrypt -ek</summary>
    Specify the key(s) to NOT encrypt by passing --exclude-key. sh $ echo "HELLO=World\nHELLO2=Universe" > .env $ dotenvx encrypt -ek HELLO ✔ encrypted (.env) Even specify a glob pattern. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt -ek "HO*" ✔ encrypted (.env)
  • <summary>encrypt --stdout</summary>
    Encrypt the contents of a .env file and send to stdout. sh $ echo "HELLO=World" > .env $ dotenvx encrypt --stdout #/-------------------[DOTENV_PUBLIC_KEY]--------------------/ #/ public-key encryption for .env files / #/ [how it works](https://dotenvx.com/encryption) / #/----------------------------------------------------------/ DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45" # .env HELLO="encrypted:BDqDBibm4wsYqMpCjTQ6BsDHmMadg9K3dAt+Z9HPMfLEIRVz50hmLXPXRuDBXaJi/LwWYEVUNiq0HISrslzQPaoyS8Lotg3gFWJTsNCdOWnqpjF2xNUX2RQiP05kAbEXM6MWVjDr" or send to a file: sh $ echo "HELLO=World" > .env $ dotenvx encrypt --stdout > somefile.txt
  • <summary>decrypt</summary>
    Decrypt the contents of an encrypted .env file to an unencrypted .env file. sh $ echo "HELLO=World" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx decrypt ✔ decrypted (.env)
  • <summary>decrypt -f</summary>
    Decrypt the contents of a specified encrypted .env file to an unencrypted .env file. sh $ echo "HELLO=World" > .env $ echo "HELLO=Production" > .env.production $ dotenvx encrypt -f .env.production ✔ encrypted (.env.production) $ dotenvx decrypt -f .env.production ✔ decrypted (.env.production)
  • <summary>decrypt -fk</summary>
    Specify path to .env.keys. This is useful with monorepos. sh $ mkdir -p apps/app1 $ echo "HELLO=World" > apps/app1/.env $ dotenvx encrypt -fk .env.keys -f apps/app1/.env ✔ encrypted (apps/app1/.env) $ dotenvx decrypt -fk .env.keys -f apps/app1/.env ✔ decrypted (apps/app1/.env)
  • <summary>decrypt -k</summary>
    Decrypt the contents of a specified key inside an encrypted .env file. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx decrypt -k HELLO ✔ decrypted (.env) Even specify a glob pattern. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx decrypt -k "HE*" ✔ encrypted (.env)
  • <summary>decrypt -ek</summary>
    Decrypt the contents inside an encrypted .env file except for an excluded key. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx decrypt -ek HOLA ✔ decrypted (.env) Even specify a glob pattern. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx decrypt -ek "HO*" ✔ encrypted (.env)
  • <summary>decrypt --stdout</summary>
    Decrypt the contents of an encrypted .env file and send to stdout. sh $ dotenvx decrypt --stdout #/-------------------[DOTENV_PUBLIC_KEY]--------------------/ #/ public-key encryption for .env files / #/ [how it works](https://dotenvx.com/encryption) / #/----------------------------------------------------------/ DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45" # .env HELLO="World" or send to a file: sh $ dotenvx decrypt --stdout > somefile.txt
  • <summary>keypair</summary>
    Print public/private keys for .env file. sh $ echo "HELLO=World" > .env $ dotenvx encrypt $ dotenvx keypair {"DOTENV_PUBLIC_KEY":"<publicKey>","DOTENV_PRIVATE_KEY":"<privateKey>"}
  • <summary>keypair -f</summary>
    Print public/private keys for .env.production file. sh $ echo "HELLO=Production" > .env.production $ dotenvx encrypt -f .env.production $ dotenvx keypair -f .env.production {"DOTENV_PUBLIC_KEY_PRODUCTION":"<publicKey>","DOTENV_PRIVATE_KEY_PRODUCTION":"<privateKey>"}
  • <summary>keypair -fk</summary>
    Specify path to .env.keys. This is useful for printing public/private keys for monorepos. sh $ mkdir -p apps/app1 $ echo "HELLO=World" > apps/app1/.env $ dotenvx encrypt -fk .env.keys -f apps/app1/.env $ dotenvx keypair -fk .env.keys -f apps/app1/.env {"DOTENV_PUBLIC_KEY":"<publicKey>","DOTENV_PRIVATE_KEY":"<privateKey>"}
  • <summary>keypair DOTENV_PRIVATE_KEY</summary>
    Print specific keypair for .env file. sh $ echo "HELLO=World" > .env $ dotenvx encrypt $ dotenvx keypair DOTENV_PRIVATE_KEY <privateKey>
  • <summary>keypair --format shell</summary>
    Print a shell formatted response of public/private keys. sh $ echo "HELLO=World" > .env $ dotenx encrypt $ dotenvx keypair --format shell DOTENV_PUBLIC_KEY=<publicKey> DOTENV_PRIVATE_KEY=<privateKey>
  • <summary>ls</summary>
    Print all .env files in a tree structure. sh $ touch .env $ touch .env.production $ mkdir -p apps/backend $ touch apps/backend/.env $ dotenvx ls ├─ .env.production ├─ .env └─ apps └─ backend └─ .env
  • <summary>ls directory</summary>
    Print all .env files inside a specified path to a directory. sh $ touch .env $ touch .env.production $ mkdir -p apps/backend $ touch apps/backend/.env $ dotenvx ls apps/backend └─ .env
  • <summary>ls -f</summary>
    Glob .env filenames matching a wildcard. sh $ touch .env $ touch .env.production $ mkdir -p apps/backend $ touch apps/backend/.env $ touch apps/backend/.env.prod $ dotenvx ls -f **/.env.prod* ├─ .env.production └─ apps └─ backend └─ .env.prod
  • <summary>ls -ef</summary>
    Glob .env filenames excluding a wildcard. sh $ touch .env $ touch .env.production $ mkdir -p apps/backend $ touch apps/backend/.env $ touch apps/backend/.env.prod $ dotenvx ls -ef '**/.env.prod*' ├─ .env └─ apps └─ backend └─ .env
  • <summary>rotate</summary>
    Rotate public/private keys for .env file and re-encrypt all encrypted values. sh $ echo "HELLO=World" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx rotate ✔ rotated (.env)
  • <summary>rotate -f</summary>
    Rotate public/private keys for a specified encrypted .env file and re-encrypt all encrypted values. sh $ echo "HELLO=World" > .env $ echo "HELLO=Production" > .env.production $ dotenvx encrypt -f .env.production ✔ encrypted (.env.production) $ dotenvx rotate -f .env.production ✔ rotated (.env.production)
  • <summary>rotate -fk</summary>
    Specify path to .env.keys. This is useful with monorepos. sh $ mkdir -p apps/app1 $ echo "HELLO=World" > apps/app1/.env $ dotenvx encrypt -fk .env.keys -f apps/app1/.env ✔ encrypted (apps/app1/.env) $ dotenvx rotate -fk .env.keys -f apps/app1/.env ✔ rotated (apps/app1/.env)
  • <summary>rotate -k</summary>
    Rotate the contents of a specified key inside an encrypted .env file. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx rotate -k HELLO ✔ rotated (.env) Even specify a glob pattern. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx rotate -k "HE*" ✔ rotated (.env)
  • <summary>rotate -ek</summary>
    Rotate the encrypted contents inside an encrypted .env file except for an excluded key. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx rotate -ek HOLA ✔ rotated (.env) Even specify a glob pattern. sh $ echo "HELLO=World\nHOLA=Mundo" > .env $ dotenvx encrypt ✔ encrypted (.env) $ dotenvx rotate -ek "HO*" ✔ rotated (.env)
  • <summary>rotate --stdout</summary>
    Rotate the contents of an encrypted .env file and send to stdout. sh $ dotenvx rotate --stdout #/-------------------[DOTENV_PUBLIC_KEY]--------------------/ #/ public-key encryption for .env files / #/ [how it works](https://dotenvx.com/encryption) / #/----------------------------------------------------------/ DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45" # .env HELLO="encrypted:12345" or send to a file: sh $ dotenvx rotate --stdout > somefile.txt
  • <summary>help</summary>
    Output help for dotenvx. sh $ dotenvx help Usage: dotenvx run -- yourcommand a better dotenv–from the creator of `dotenv` Options: -l, --log-level <level> set log level (default: "info") -q, --quiet sets log level to error -v, --verbose sets log level to verbose -d, --debug sets log level to debug -V, --version output the version number -h, --help display help for command Commands: run inject env at runtime [dotenvx run -- yourcommand] get [KEY] return a single environment variable set <KEY> <value> set a single environment variable encrypt convert .env file(s) to encrypted .env file(s) decrypt convert encrypted .env file(s) to plain .env file(s) keypair [KEY] print public/private keys for .env file(s) ls [directory] print all .env files in a tree structure Advanced: pro 🏆 pro ext 🔌 extensions You can get more detailed help per command with dotenvx help COMMAND. sh $ dotenvx help run Usage: @dotenvx/dotenvx run [options] inject env at runtime [dotenvx run -- yourcommand] Options: -e, --env <strings...> environment variable(s) set as string (example: "HELLO=World") (default: []) -f, --env-file <paths...> path(s) to your env file(s) (default: []) -fv, --env-vault-file <paths...> path(s) to your .env.vault file(s) (default: []) -o, --overload override existing env variables --convention <name> load a .env convention (available conventions: ['nextjs']) -h, --help display help for command Examples: $ dotenvx run -- npm run dev $ dotenvx run -- flask --app index run $ dotenvx run -- php artisan serve $ dotenvx run -- bin/rails s Try it: $ echo "HELLO=World" > .env $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ dotenvx run -- node index.js [dotenvx@1.X.X] injecting env (1) from .env Hello World
  • <summary>--version</summary>
    Check current version of dotenvx. sh $ dotenvx --version X.X.X

Extensions 🔌

CLI extensions.

  • <summary>ext genexample</summary>
    In one command, generate a .env.example file from your current .env file contents. sh $ echo "HELLO=World" > .env $ dotenvx ext genexample ✔ updated .env.example (1) ini # .env.example HELLO=""
  • <summary>ext genexample -f</summary>
    Pass multiple .env files to generate your .env.example file from the combination of their contents. sh $ echo "HELLO=World" > .env $ echo "DB_HOST=example.com" > .env.production $ dotenvx ext genexample -f .env -f .env.production ✔ updated .env.example (2) ini # .env.example HELLO="" DB_HOST=""
  • <summary>ext genexample directory</summary>
    Generate a .env.example file inside the specified directory. Useful for monorepos. sh $ echo "HELLO=World" > .env $ mkdir -p apps/backend $ echo "HELLO=Backend" > apps/backend/.env $ dotenvx ext genexample apps/backend ✔ updated .env.example (1) ini # apps/backend/.env.example HELLO=""
  • <summary>ext gitignore</summary>
    Gitignore your .env files. sh $ dotenvx ext gitignore ✔ ignored .env* (.gitignore)
  • <summary>ext gitignore --pattern</summary>
    Gitignore specific pattern(s) of .env files. sh $ dotenvx ext gitignore --pattern .env.keys ✔ ignored .env.keys (.gitignore)
  • <summary>ext precommit</summary>
    Prevent .env files from being committed to code. sh $ dotenvx ext precommit [dotenvx][precommit] .env files (1) protected (encrypted or gitignored)
  • <summary>ext precommit --install</summary>
    Install a shell script to .git/hooks/pre-commit to prevent accidentally committing any .env files to source control. sh $ dotenvx ext precommit --install [dotenvx][precommit] dotenvx ext precommit installed [.git/hooks/pre-commit]
  • <summary>ext precommit directory</summary>
    Prevent .env files from being committed to code inside a specified path to a directory. sh $ echo "HELLO=World" > .env $ mkdir -p apps/backend $ echo "HELLO=Backend" > apps/backend/.env $ dotenvx ext precommit apps/backend [dotenvx][precommit] apps/backend/.env not protected (encrypted or gitignored)
  • <summary>ext prebuild</summary>
    Prevent .env files from being built into your docker containers. Add it to your Dockerfile. sh # Dockerfile RUN curl -fsS https://dotenvx.sh | sh ... RUN dotenvx ext prebuild CMD ["dotenvx", "run", "--", "node", "index.js"]
  • <summary>ext prebuild directory</summary>
    Prevent .env files from being built into your docker containers inside a specified path to a directory. Add it to your Dockerfile. sh # Dockerfile RUN curl -fsS https://dotenvx.sh | sh ... RUN dotenvx ext prebuild apps/backend CMD ["dotenvx", "run", "--", "node", "apps/backend/index.js"]
  • <summary>ext scan</summary>
    Scan for leaked secrets. sh $ dotenvx ext scan 100 commits scanned. no leaks found Uses gitleaks under the hood.

Library 📦

Use dotenvx directly in code.

  • <summary>config()</summary>
    Use directly in node.js code. ini # .env HELLO="World" js // index.js require('@dotenvx/dotenvx').config() console.log(`Hello ${process.env.HELLO}`) sh $ node index.js [dotenvx@1.X.X] injecting env (1) from .env Hello World It defaults to looking for a .env file.
  • <summary>config(path: ['.env.local', '.env']) - multiple files</summary>
    Specify path(s) to multiple .env files. ini # .env.local HELLO="Me" ini # .env HELLO="World" js // index.js require('@dotenvx/dotenvx').config({path: ['.env.local', '.env']}) // esm // import dotenvx from "@dotenvx/dotenvx"; // dotenvx.config({path: ['.env.local', '.env']}); console.log(`Hello ${process.env.HELLO}`) sh $ node index.js [dotenvx@1.X.X] injecting env (1) from .env.local, .env Hello Me
  • <summary>config(overload: true) - overload</summary>
    Use overload to overwrite the prior set value. ini # .env.local HELLO="Me" ini # .env HELLO="World" js // index.js require('@dotenvx/dotenvx').config({path: ['.env.local', '.env'], overload: true}) // esm // import dotenvx from "@dotenvx/dotenvx"; // dotenvx.config({path: ['.env.local', '.env'], overload: true}); console.log(`Hello ${process.env.HELLO}`) sh $ node index.js [dotenvx@1.X.X] injecting env (1) from .env.local, .env Hello World
  • <summary>config(strict: true) - strict</summary>
    Use strict to throw if an error is encountered - like a missing .env file. ini # .env HELLO="World" js // index.js require('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], strict: true}) // esm // import dotenvx from "@dotenvx/dotenvx"; // dotenvx.config({path: ['.env.missing', '.env'], strict: true}); console.log(`Hello ${process.env.HELLO}`) sh $ node index.js Error: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)
  • <summary>config(ignore:) - ignore</summary>
    Use ignore to suppress specific errors like MISSING_ENV_FILE. ini # .env HELLO="World" js // index.js require('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], ignore: ['MISSING_ENV_FILE']}) // esm // import dotenvx from "@dotenvx/dotenvx"; // dotenvx.config({path: ['.env.missing', '.env'], ignore: ['MISSING_ENV_FILE']}); console.log(`Hello ${process.env.HELLO}`) sh $ node index.js [dotenvx@1.X.X] injecting env (1) from .env Hello World
  • <summary>config(envKeysFile:) - envKeysFile</summary>
    Use envKeysFile to customize the path to your .env.keys file. This is useful with monorepos. ini # .env HELLO="World" js // index.js require('@dotenvx/dotenvx').config({path: ['.env'], envKeysFile: '../../.env.keys'})
  • <summary>parse(src)</summary>
    Parse a .env string directly in node.js code. js // index.js const dotenvx = require('@dotenvx/dotenvx') const src = 'HELLO=World' const parsed = dotenvx.parse(src) console.log(`Hello ${parsed.HELLO}`) sh $ node index.js Hello World
  • <summary>parse(src, {processEnv:})</summary>
    Sometimes, you want to run parse without it accessing process.env. (You can pass a fake processEnv this way as well - sometimes useful.) js // index.js const dotenvx = require('@dotenvx/dotenvx') const src = 'USER=Me' const parsed = dotenvx.parse(src, { processEnv: {} }) console.log(`Hello ${parsed.USER}`) sh $ node index.js Hello Me
  • <summary>parse(src, {privateKey:})</summary>
    Decrypt an encrypted .env string with privateKey. js // index.js const dotenvx = require('@dotenvx/dotenvx') const src = 'HELLO="encrypted:BE9Y7LKANx77X1pv1HnEoil93fPa5c9rpL/1ps48uaRT9zM8VR6mHx9yM+HktKdsPGIZELuZ7rr2mn1gScsmWitppAgE/1lVprNYBCqiYeaTcKXjDUXU5LfsEsflnAsDhT/kWG1l"' const parsed = dotenvx.parse(src, { privateKey: 'a4547dcd9d3429615a3649bb79e87edb62ee6a74b007075e9141ae44f5fb412c' }) console.log(`Hello ${parsed.HELLO}`) sh $ node index.js Hello World
  • <summary>set(KEY, value)</summary>
    Programmatically set an environment variable. js // index.js const dotenvx = require('@dotenvx/dotenvx') dotenvx.set('HELLO', 'World', { path: '.env' })
  • <summary>get(KEY) - Decryption at Access</summary>
    Programmatically get an environment variable at access/runtime. js // index.js const dotenvx = require('@dotenvx/dotenvx') const decryptedValue = dotenvx.get('HELLO') console.log(decryptedValue) This is known as Decryption at Access and is written about in the whitepaper.

Pro 🏆

Dotenvx Pro is a commercial extension for dotenvx.

Secrets Manager for Env Files.

  • <summary>pro keypair</summary>
    Print fully managed public/private keys for .env file. sh $ echo "HELLO=World" > .env $ dotenvx encrypt $ dotenvx pro push $ dotenvx pro keypair {"DOTENV_PUBLIC_KEY":"<publicKey>","DOTENV_PRIVATE_KEY":"<privateKey>"}
  • <summary>pro keypair -f</summary>
    Print fully managed public/private keys for .env.production file. sh $ echo "HELLO=Production" > .env.production $ dotenvx encrypt -f .env.production $ dotenvx pro push $ dotenvx pro keypair -f .env.production {"DOTENV_PUBLIC_KEY_PRODUCTION":"<publicKey>","DOTENV_PRIVATE_KEY_PRODUCTION":"<privateKey>"}
  • <summary>pro keypair DOTENV_PRIVATE_KEY</summary>
    Print specific fully managed keypair for .env file. sh $ echo "HELLO=World" > .env $ dotenvx encrypt $ dotenvx pro push $ dotenvx pro keypair DOTENV_PRIVATE_KEY <privateKey>
  • <summary>pro settings org</summary>
    Print organization. sh $ dotenvx pro settings org motdotla
  • <summary>pro settings orgpublickey</summary>
    Print organization public key–used for encrypting project private keys. sh $ dotenvx pro settings orgpublickey 02761eccd2a442ebbfa14ac2e72762d885a1e96b8949428deea62db305947d6408
  • <summary>pro settings orgprivatekey</summary>
    Print masked organization private key–used for decrypting project private keys. sh $ dotenvx pro settings orgprivatekey 322c004*********************************************************
  • <summary>pro settings orgprivatekey --unmask</summary>
    Print unmasked organization private key–used for decrypting project private keys. sh $ dotenvx pro settings orgprivatekey --unmask 322c004271ac6ad1b548df3f316ff4e8f08e17e0b15f459db64f3f3b48b0efb7
  • <summary>pro settings orgteam</summary>
    Print team status in tabular format. sh $ dotenvx pro settings orgteam ╔═══════════╤════════╗ ║ username │ synced ║ ╟───────────┼────────╢ ║ motdotla │ ✔ ║ ╟───────────┼────────╢ ║ motdotenv │ ✔ ║ ╚═══════════╧════════╝
  • <summary>pro settings storetree</summary>
    Print encrypted store tree–backing your dotenvx pro installation. sh $ dotenvx pro settings storetree ├─ .env └─ pro.dotenvx.com ├─ user-1-organization-1.json ├─ user-1-private-key.json └─ user-1.json

 

Whitepaper

Dotenvx: Reducing Secrets Risk with Cryptographic Separation

Abstract. An ideal secrets solution would not only centralize secrets but also contain the fallout of a breach. While secrets managers offer centralized storage and distribution, their design creates a large blast radius, risking exposure of thousands or even millions of secrets. We propose a solution that reduces the blast radius by splitting secrets management into two distinct components: an encrypted secrets file and a separate decryption key.

...

Read the whitepaper

 

Guides

Go deeper with dotenvx – detailed framework and platform guides.

更新日志

Changelog

All notable changes to this project will be documented in this file. See standard-version for commit guidelines.

Unreleased

1.45.1

Changed

  • Include setLogName and setLogVersion in config (#613)

1.45.0

Added

  • Add logger.setName and logger.setVersion for customization of logger (#612)

1.44.2

Changed

  • Clarify license is BSD-3.

1.44.1

Changed

  • Patch SetOutput type (#597)

1.44.0

Added

  • Add armv7 support (#593)

1.43.0

Removed

  • Remove errorv, errornocolor, blank from logger options (#584)

Changed

  • Replace instances of console.error with logger.error (#584)

1.42.2

Changed

  • Fix --force flag work with ?force=true (2776715)

1.42.1

Added

  • Add --force flag to install.sh (0b8d21c)

1.42.0

Added

  • Add ability to override the os and arch via install.sh and dotenvx.sh (3ded752)

1.41.0

Added

  • Add [directory] argument to precommit and prebuild (#572)

1.40.1

Changed

  • Patch ext scan command (#570)

1.40.0

Added

  • Smarter ext precommit and ext prebuild – catch duplicate KEYs in the same .env file where one is mistakenly left unencrypted (#567)

1.39.1

Added

  • Add version to homebrew formula (#564)

1.39.0

Added

  • Add --convention flow option to dotenvx run (#551)

Changed

1.38.5

Added

  • 🐞 Add config.d.ts file to fix type error when loading dotenvx/dotenvx/config with dynamic import (#547)

1.38.4

Changed

  • 🐞 Fix blank line disappearing after encrypting empty value (#542)

1.38.3

Changed

  • 🐞 Fix self-referencing expansion when key exists already in process.env (#536)

1.38.2

Added

  • Add typescript types for main.get.

1.38.1

Changed

  • Support encrypt when mutliline contains windows CRLF (\r\n) (#534)

Note: dotenvx will convert these \r\n newlines to \n. Our recommendation is to stop using CRLF - its origin is from typewriter days. Instead, set your editor or gitattributes to use LF.

1.38.0

Changed

  • Command substitution failures no longer halt further processing of keys in a .env file (#533)
  • A more helpful error is raised if a command substitution failure occurs (#533)

1.37.0

Added

  • add dotenvx rotate command 🎉 (#530)

also: our whitepaper is released as a draft.

1.36.0

Changed

  • --strict flag respects (doesn't throw) anything in --ignore flag (#527)

1.35.0

Added

  • npx dotenvx precommit support as a convenience (#523)
  • main.get method (#524)

The addition of main.get facilitates what we term Decryption at Access, a concept explored in greater detail in our whitepaper.

1.34.0

Added

  • main.set method now writes to files (#517)

1.33.0

Added

  • support ESM import convenience import '@dotenvx/dotenvx/config' (#508)

1.32.1

Changed

  • remove duplicated help messages (#504)

1.32.0

Added

  • add encrypted check support for ext prebuild (#501)

Changed

  • modify ext precommit to check git modified state as well as git staged state - useful for using dotenvx ext precommit without the --install flag in automated scripts and ci. (#499)

Removed

  • remove internal logger methods errorvp, errorvpb, warnv, warnvp, warnvpb, successvp, successvpb, help2 (#501)

1.31.3

Changed

  • adjust wingetcreate to use powershell when parsing version

1.31.2

Changed

  • use wingetcreate for releasing to WinGet (#498)

1.31.1

Changed

  • 🐞 fix encryption of values containing explicit \n newlines (#495)

1.31.0

Added

  • expose main.set function (#492)
  • add missing types for main.config (#491)

1.30.1

Added

  • support complex command substitution combining variable expansion (#490)

1.30.0

Added

  • add -fk (--env-keys-file) flag to customize the path to your .env.keys file with run, get, set, encrypt, decrypt, and keypair 🎉 (#486)

This is great for monorepos. Maintain one .env.keys file across all your apps.

$ dotenvx encrypt -fk .env.keys -f apps/backend/.env
$ dotenvx encrypt -fk .env.keys -f apps/frontend/.env

$ tree -a .
├── .env.keys
└── apps
    ├── backend
    │   └── .env
    └── frontend
        └── .env

$ dotenvx get -fk .env.keys -f apps/backend/.env

1.29.0

Added

  • add --ignore flag to suppress specified errors. example: dotenvx run --ignore=MISSING_ENV_FILE (#485)

1.28.0

Changed

  • .env.keys file is generated WITHOUT quotes going forward. This is to minimize friction around Docker gotchas to developers - old versions of Docker do not support --env-file containing quoted keys/values. (#480) (additional note)

1.27.0

Added

  • add support for \t expansion when double quoted. (e.g. TAB="hi\tfriend" becomes hi friend) (#479)

1.26.2

Changed

  • build binaries with bytecode option (#477)

1.26.1

Added

  • add typescript type definitions for main.parse method (#475)

1.26.0

Added

  • add privateKey option to main.parse method (#474)

1.25.2

Added

  • for binaries add pre-build step using esbuild (#471)

Removed

  • remove types for functions that were removed a while back (2aa660)

1.25.1

Changed

  • improve helpful error messaging around decryption failures by specifying specific key and private key name (#463)

1.25.0

Added

  • add run --strict flag to exit with code 1 if any errors are encountered - like a missing .env file or decryption failure (#460)
  • add get --strict flag to exit with code 1 if any errors are encountered - like a missing .env file or decryption failure (#461)
  • add strict option to config() to throw for any errors (#459)

Changed

  • log MISSING_ENV_FILE and DECRYPTION_FAILED errors to stderr (prior was stdout as a warning) (#459)

Removed

  • remove dotenvx.get() function from lib/main.js. (parse already historically exists for this purpose) (#461)

1.24.5

Changed

  • 🐞 do not expand prior literal values (#458)

1.24.4

Changed

  • do not expand command substitution (#456)

1.24.3

Changed

  • 🐞 fix command substitution for more complex commands (#455)

1.24.2

Changed

  • treat pre-existing expandable values as literal in process.env (#450)

1.24.1

Changed

1.24.0

Added

  • support progressive append/update (#445)
FOO=foo
FOO=${FOO}bar
# foobar
  • support alternate value expansion (#445)

image

Changed

  • dotenvx.parse now maps to dotenvx's internal parser. (prior it was mapping to dotenv's)

Removed

  • removed dotenvx.configDotenv(). use dotenvx.config() (#445)

1.23.0

Added

  • deeper variable expansion support and protection against self-referencing variables 🛡️ (#439)

1.22.2

Changed

  • more lenient handling of -- separator and better error messaging when flags are ambiguous (#438)

1.22.1

Changed

  • 🐞 patch loading order issue with single quotes (#436)

1.22.0

Added

  • add --pattern argument to ext gitignore (dotenvx ext gitignore --pattern .env.keys) (#430)

Changed

  • clarify next steps after first time encrypting (#430)

1.21.1

Changed

  • for --convention nextjs ignore .env.local for TEST environment (#425)
  • for precommit redirect missing dotenvx command using POSIX compliant redirection (#424)
  • make parent dotenvx help command less noisy by removing [options]. run dotenvx COMMAND -h to list all available options like always (#429)

1.21.0

Changed

  • treat single quotes literally (#423)
  • respect user chosen quotes (#423 #377)

🎓 now if you choose to single quote, double quote, no quote, or backtick your value it will be respected - including for encrypted values. this more intuitively handles complex cases like escaped characters, literals, and json.

1.20.1

Changed

  • update eciesjs (#421)
  • remove default values for ts interface - no longer permitted by latest ts (#419)

1.20.0

Changed

  • respect process.env.DOTENV_PRIVATE_KEY and/or process.env.DOTENV_PUBLIC_KEY on set (#401)
  • respect process.env.DOTENV_PRIVATE_KEY and/or process.env.DOTENV_PUBLIC_KEY on encrypt (#411)
  • respect process.env.DOTENV_PRIVATE_KEY on decrypt (#412)
  • change logger.help to use brighter blue (#414)

Removed

  • remove main.decrypt,encrypt,set (#410)

1.19.3

Changed

  • 🐞 fix decrypt re-encrypt of values containing backslashes (#406)

1.19.2

Changed

  • forward additional signals like SIGUSR2 (#403)

1.19.1

Changed

  • if SIGTERM or SIGINT sent, don't bubble wrapped process error (#402)

1.19.0

Added

  • support key glob filtering for encrypt and decrypt. example: dotenvx encrypt -ek "NEXT_PUBLIC_*" (#397)

1.18.1

Added

  • escape user inputted regex groupings like $1 or $2. (#396)

1.18.0

Added

  • set and encrypt preserve leading spaces (#395)
     HELLO=world

Changed

  • improve escape and quote handling for set, encrypt, and decrypt (#395)
  • 🐞 fix encrypt, then decrypt, then encrypt on a json value (#377)

Note: the underlying replace engine to support these changes now wraps your values in single quotes. the prior replace engine wrapped in double quotes.

So where your .env used to look like this with double quotes:

HELLO="encrypted:1234"
API_KEY="encrypted:5678"

It will now begin looking like this with single quotes:

HELLO='encrypted:1234'
API_KEY='encrypted:5678'

It's an aesthetic side effect only. Your values will continue to be decrypted and encrypted correctly.

1.17.0

Added

  • add --format=eval option for get (#393)

1.16.1

Changed

  • suppress stderr using options.stdio (#391)

1.16.0

Changed

  • for dotenvx keypair call out to dotenvx pro keypair if pro installed (#390)

1.15.0

Added

  • add --format=shell option for keypair (#389)

1.14.2

Changed

  • swap process.stdout.write for console.log to patch up npx edge case (#387)

1.14.1

Changed

  • run precommit hook only on staged files (#380)

1.14.0

Added

  • add dotenvx keypair command for printing your public/private keypairs (#375)

1.13.3

Changed

  • exit code 1 when decrypt fails in any way (#374)

1.13.2

Added

  • expose getColor and bold to lib/main.js (#369)

1.13.1

Added

  • expose logger and setLogLevel to lib/main.js - const = { logger, setLogLevel } = require('@dotenvx/dotenvx') (#368)

1.13.0

Changed

  • move ls to core commands (#367)

1.12.1

Changed

  • return without quotations for dotenvx get --format shell (#366)

1.12.0

Added

  • add dotenvx get --format shell option (#363)

1.11.5

Changed

  • revert tinyexec for execa - to support usage in bun

1.11.4

Changed

  • bump tinyexec and add postrelease-bunx check (#362)

1.11.3

Changed

  • fallback to process.env.TERM for color depth where deno and bun do not support it (#360)

1.11.2

Added

  • detect encoding when reading .env* file on run/get (#359)

1.11.1

Changed

  • support encryption of export KEY variables and preserve #!shebangs (#357)

1.11.0

Added

  • add --exclude-env-file (-ef) to ext ls (#356)

Changed

  • ext precommit ignores tests/ directory (and similar) (#356)

1.10.4

Changed

  • fix pro display in help command

1.10.3

Added

  • ci: automate publishing to winget (#354)

1.10.2

Changed

  • default config to empty [] array so that DOTENV_KEY_${environment} looks up correctly (#352)

1.10.1

Changed

  • check subfolders on dotenvx ext precommit hook (#350)

1.10.0

Removed

  • remove dotenvx ext vault, replace with dotenvx-ext-vault (install there to continue using ext vault) (#351)

1.9.1

Added

  • warn if private key is missing or blank (#349)

1.9.0

Added

  • add --exclude-key (-ek) option to dotenvx encrypt and dotenvx decrypt (#344)

Changed

  • preserve comments and spacing on first-time generation of .env.example file (#346)

Removed

  • removed winston - logger simplified to use console.log going forward (#347)

1.8.0

Added

  • warn when decryption fails on run (#339)
  • decrypt expanded values as necessary (#336)

Changed

  • use ansi colors over rgb - for wider terminal coverage (#340)
  • replace chalk with picocolors and color-name - cutting down on 5 dependencies (#335)
  • replace execa with tinyexec - cutting down on 15 dependencies (#328)
  • optimize Ls._filepaths (#317)

Removed

  • remove picocolors and color-name - cutting down on 2 dependencies (#340)
  • remove ext hub from extension list (you can still install it as an extension here) (#337)

1.7.0

Removed

  • remove ext settings command (and conf along with it) (#323)

1.6.5

Changed

  • 🐞 patch chomp for interpolation. strip ending newline (was stripping first found newline) (#322)

1.6.4

Changed

  • fix dotenvx help (command was missing)

1.6.3

Changed

  • adjust dotenvx pro to be dynamic if dotenvx-pro is installed user's machine

1.6.2

Added

  • add more detailed type definitions (#313)

1.6.1

Added

  • add support for .env1 (.env*) file format. (private key expands to DOTENV_PRIVATE_KEY_DEVELOPMENT1) (#312)

1.6.0

Added

  • add dotenvx decrypt command. works inversely to dotenvx encrypt. same flags. (#294)
  • add --stdout option to dotenvx decrypt. example: dotenvx decrypt -f .env.production --stdout > somefile.txt (#298)
  • add --stdout option to dotenvx encrypt. example: dotenvx encrypt -f .env.production --stdout > somefile.txt (#298)

Changed

  • smarter private key finder. if you rename your file to secrets.txt it can still decrypt from DOTENV_PRIVATE_KEY by seeking out the invert of the DOTENV_PUBLIC_KEY inside secrets.txt (#302)

Removed

  • remove dotenvx convert - still at dotenvx encrypt
  • remove dotenvx vault - still at dotenvx ext vault

1.5.0

Added

  • add help text for dashed values on set. example: dotenvx set KEY -- "- + * ÷" (#293)

Changed

  • replace @inquirer/confirm and ora (#285)

Removed

  • remove dotenvx ext hub, replace with dotenvx-ext-hub (install there to continue using hub) (#291)

1.4.0

Removed

  • remove update notice. let users decide what version they want without nagging them to update (#288)
  • remove dotenvx hub. still available at dotenvx ext hub (#290)

1.3.2

Changed

  • 🐞 remove risky prepare and postinstall scripts and replace with npm run patch for development and binary building (#286)

1.3.1

Changed

  • 🐞 make patch-package only run locally with prepare (#283)

1.3.0

Added

  • encrypt specified keys with --key option - dotenvx encrypt -k HELLO (#281)

1.2.0

Added

  • handle nested dotenvx invocations - dotenvx run -- dotenvx run -- env (#279)

Changed

  • replace glob with faster approach (#278)

1.1.0

Added

  • add TypeScript type definitions (#272)

1.0.1

Changed

  • 🐞 fix expansion when preset on process.env and/or with --overload (#271)

1.0.0

🎉 dotenvx has made it to 1.0.0. There are BREAKING CHANGES ⚠️ .

Added

  • added dotenvx set KEY value --plain to set plain text values
  • added dotenvx ext 🔌 as a location to place extensions like gititgnore, precommit, ls, and more. better than cluttering up core features like run, get/set, and encrypt.
  • added dotenvx pro 🏆 command with coming soon and link to GitHub issue (if you wish to be notified of progress. will provide tooling/features for teams)

Changed

  • BREAKING ⚠️
    • turned on encryption by default for dotenvx set (use dotenvx set KEY value --plain to set plain values)
    • renamed dotenvx encrypt to dotenvx ext vault encrypt (for managing .env.vault files)
    • renamed dotenvx convert to dotenvx encrypt
    • moved ls to dotenvx ext ls
    • moved genexample to dotenvx ext genexample
    • moved gitignore to dotenvx ext gitignore
    • moved prebuild to dotenvx ext prebuild
    • moved precommit to dotenvx ext precommit
    • moved scan to dotenvx ext scan
    • moved hub to dotenvx ext hub
    • moved vault to dotenvx ext vault
    • moved settings to dotenvx ext settings

(for many of these moved commands, for example dotenvx genexample, still work in 1.0.0 but with a large deprecated notice - DEPRECATION NOTICE: [genexample] has moved to [dotenvx ext genexample]. Please change your muscle memory to dotenvx ext genexample, as these deprecated command paths will be removed in a later minor version. importantly dotenvx encrypt was not able to be preserved because as it is now in use for encrypted .env files rather than .env.vault files)

This is a BIG release that sets the tone for dotenvx's core offering and features while maintaining room for growth. Thank you everyone for your support and usage of dotenvx 🙏.

blog post: "From dotenv to dotenvx: Next Generation Config Management"

0.45.0

Changed

  • Rename dotenvx vault convert to dotenvx vault migrate (#251)
  • Update install.sh regex version check to be sh compatible (not just bash)

0.44.6

Added

  • Added checksums.txt as part of each release

0.44.5

Changed

  • Removed .github folder from published binaries on npm (example: npm code)
  • Add help message to install.sh

0.44.4

Changed

  • Automated deployment of install.sh along with sanity checks (#250)

0.44.3

Added

  • Include CHANGELOG.md in npm release
  • Include install.sh in package release

0.44.2

Changed

  • Fix license in package.json to match project's license BSD-3.

0.44.1

Changed

  • Respect decryption of zero length strings - dotenvx set HELLO '' --encrypt (#236)

0.44.0

Added

  • Added options.debug, options.verbose, options.quiet, and options.logLevel to .config() (#233)

0.43.2

Changed

  • Patch replace when replacing double, single, or backticked quoted at anywhere in the .env file. (#232)

0.43.1

Changed

  • Improved replace function regex - to handle more edge case scenarios with replacing KEY/values (#227)

0.43.0

Added

  • Support require('@dotenvx/dotenvx').config() for DOTENV_PRIVATE_KEY decryption (#225)

0.42.0

Added

  • Added .env.vault deprecated warning when using DOTENV_KEY. Provide instructions to convert to encrypted .env files. (#224)

0.41.0

Added

  • Added vault convert command to list convert instructions for converting .env.vault to encrypted .env files (#222)
To convert your .env.vault file to encrypted .env file(s):

  1. Run [dotenvx vault decrypt]
  2. Run [ls -a .env*]

Lastly, convert each .env(.environment) file:

  3. Run [dotenvx convert -f .env.production]

For example:

  $ dotenvx convert -f .env
  $ dotenvx convert -f .env.ci
  $ dotenvx convert -f .env.production

Afterward:

Update production with your new DOTENV_PRIVATE_KEY_PRODUCTION located in .env.keys

Learn more at [https://dotenvx.com/docs/quickstart#add-encryption]

Changed

  • Rename encryptme to convert (#222)

0.40.1

Added

  • Support encryption replacement of multiline values (#220)

0.40.0

Added

  • Added dotenvx encryptme command to convert an entire .env file to an encrypted .env file. (#213)

Changed

  • Made precommit smart enough to check if a .env* file is encrypted or not. If fully encrypted, then allow precommit check to pass (#211)

Removed

  • Do not warn of missing files for conventions (too noisy) (#216)

0.39.0

Added

  • Add --convention flag to get

Removed

  • Removed help messages like 'in production' and 'in ci'. Too specific and could lead to confusion.

0.38.0

Changed

  • ⚠️ DEPRECATION NOTICE: the following commands are being moved. Please, update any code and muscle memory you have related to these:
    • dotenvx encrypt => dotenvx vault encrypt
    • dotenvx decrypt => dotenvx vault decrypt
    • dotenvx status => dotenvx vault status
  • ⚠️ DEPRECATION NOTICE: the beta hub commands are being completely deprecated (they will be fully removed in upcoming 1.0.0 release). We will provide .env.keys tooling at a later time (replacing hub) but in the context of the new --encrypt flag functionality below

Added

  • Add encryption to your .env files with a single command. Pass the --encrypt flag. 🎉
$ dotenvx set HELLO World --encrypt
set HELLO with encryption (.env)

A DOTENV_PUBLIC_KEY (encryption key) and a DOTENV_PRIVATE_KEY (decryption key) is generated using the same public-key cryptography as Bitcoin.

Further notes:

  • DOTENV_PUBLIC_KEY lives in the .env file. You can safely share this with whomever you wish.
  • DOTENV_PRIVATE_KEY lives in your .env.keys file. Share this only with those you trust to decrypt your secrets.
  • If using encrypted .env files like this it is safe to commit them to source code. This makes reviewing PRs that contain secrets much easier.
  • Tell your contributors to contribute a secret using the command dotenvx set HELLO world --encrypt.
  • Set your DOTENV_PRIVATE_KEY on your server to decrypt these values using dotenvx run -- yourcommand
  • You can repeat all this per environment by modifying your set command to dotenvx set HELLO production -f .env.production --encrypt (for example)
  • In time we will add better tooling for sharing the private keys living in .env.keys, but until then safely share with team members you trust.
  • This mechanism should be particularly useful for open source projects that want to permit secrets contributions without handing out the decryption keys. Now anyone can contribute a secret and only you can decrypt it to see what was changed.
  • This solution is brand new, but I intend it to be the future for .env files. It has many benefits over .env.vault files. We will be sunsetting the .env.vault mechanism but its tooling will stay around in dotenvx for at least 1 year to come - under dotenvx vault parent command.
  • Be patient as we update our documentation to prioritize this improved encryption format for .env files.

0.37.1

  • warn when running dotenvx status against any untracked (not in .env.vault) files (#196)

0.37.0

  • add --convention nextjs flag to dotenvx run (#193)
  • improve status error message when decrypt fails or no .env* files (#192)

0.36.1

  • handle SIGTERM (#191)

0.36.0

  • add dotenvx status command (#186)
  • add dotenvx decrypt [directory] argument option (#186)
  • add dotenvx decrypt --environment flag option (#186)
  • normalize windows \ paths (#186)

0.35.1

Changed

  • exit code 1 if get KEY not found/undefined (#185)

0.35.0

Added

  • added set command, and optionally pass --env-file flag(s) to set usage: dotenvx set HELLO World (#182)

0.34.0

Changed

  • make hub push more forgiving by permitting full filepath like hub push directory/.env.keys (#180)
  • add note on generated .env.example (#181)

0.33.1

Changed

  • patch injection around falsy values (#177)

0.33.0

Added

  • add .env.vault support for .env.something.something (useful for Next.js pattern of .env.development.local) (#174)

0.32.0

Changed

  • quiet exit code 1 message (#173)

0.31.1

Changed

  • improve error messages (#171)

0.31.0

Added

  • add hub logout command (#170)

0.30.2

Changed

  • small fixes for windows users related to hub open and hub push (#169)

0.30.1

Changed

  • remove windows warnings related to missing git or git origin (#166 #167)

0.30.0

Added

  • dotenvx get --quiet will display the value no matter what (adds a blank0 logger level) (#161)

Changed

  • refactor dotenvx get to use run under the hood

0.29.2

Changed

  • fix broken hub login and hub open (#160)

0.29.1

Changed

  • patch situation where DOTENV_KEY is present and --env-file flag is set. assume to still look for .env.vault file as first in line (#157)

0.29.0

Changed

  • respect order for --env-vault-file, --env-file and --env flags (for example: dotenvx run --env "HELLO=one" --env-file=.env will prioritize --env flag. Add --overload here to prioritize --env-file or reverse the order.). you can now mix and match multiple flags in any complex order you wish and dotenvx will respect it. (#155)

0.28.0

Added

  • add dotenvx settings command to list your current settings. in the future we'll provide ways to modify these settings as dotenvx's functionality grows (#153)

0.27.2

Added

  • add windows postrelease step to check that dotenvx.exe is functional immediately after release (#141)

Changed

  • replace package-json with undici (#146)
  • prune redundant packages (#148)
  • return current version if remote version fails (#149)
  • switch to our own update notice mechanism (eliminating multiple deps) (#151)

0.27.1

Added

  • provide .zip download option for windows executable (#140)

Removed

  • remove got from top level deps (#139)

0.27.0

Changed

  • move update-notifier into lib/helpers for more control over got lib (#138)
  • move clipboardy into lib/helpers for more control and to support commonjs going forward (sindre has dropped support and many mature systems still require commonjs for their infra and have need of dotenvx). (#137)

0.26.0

Added

  • add hub pull command to pull a repo's .env.keys down. (#129)

0.25.1

Changed

  • 🐞 patch bug with evaluate commands. do not attempt to evaluate risky preset envs in process.env. evaluate only what's set in a .env* file (#125)

0.25.0

Added

  • expand hub push with [directory] option. use for monorepos. for example: dotenvx hub push apps/backend (#121)

0.24.0

Added

  • add command substitution. for example DATABASE_URL="postgres://$(whoami)@localhost/my_database" (#113)

0.23.0

Added

  • support personal environment variables. anything after the comment # personal.dotenvx.com will be considered personal and will not be encrypted to .env.vault (#110)

0.22.0

Added

  • require('@dotenvx/dotenvx').config() expands/interpolates variables. this matches the behavior of run. (note that this behavior differs from the original require('dotenv').config() (#107)

0.21.0

Added

  • expose genexample function on lib/main.js for export convenience (#102)

Changed

  • rely on which npm module to find system command path for user inputted command(s) (#105)

Removed

  • remove main.inject function (#102)

0.20.2

Added

  • added support for --env flag on the .env.vault decryption portion of run (#101)

0.20.1

Changed

  • use system command path (#98)

0.20.0

Changed

  • added --env flag. for example, dotenvx --env="HELLO=World" -- yourcommand (#94)

0.19.1

Changed

  • patched up the precommit command (#91)

0.19.0

Added

  • added scan command to scan for possible leaked secrets in your code (#90)

0.18.0

Added

  • added get command, optionally pass --env-file flag(s) to get, optionally pass --overload, and optionally pass --pretty-print. usage: dotenvx get HELLO => World (#89)

0.17.1

Changed

  • expose main.encrypt and main.ls functions

0.17.0

Added

  • added [directory] argument to encrypt. for example, in your nx repo from root dotenvx encrypt apps/backend will encrypt .env* files in that directory and manage the .env.keys and .env.vault in that directory as well (#82)

0.16.1

Changed

  • bumped dotenv version to fix encrypt bug

0.16.0

Added

  • added ls command to list all your .env* files (#80)
  • added --env-file option ls (#82)
  • optionally specify --env-vault-file path to .env.vault (defaults to .env.vault) (#73)

0.15.4

Changed

  • 🐞 patch --overload flag logic (#66)

0.15.3

Changed

  • 🐞 fix undici readablestream error (#65)

0.15.2

Changed

  • switch from axios to undici (#59)
  • bump dotenv-expand (#63)

0.15.1

Changed

  • use improved dotenv expansion (#62)

0.15.0

Added

  • add expansion (#60)
  • use dotenvx.com (#56)

0.14.1

Changed

  • patch esm issue. use update-notifier ^5.1.0

0.14.0

Added

  • Added genexample command. Generate .env.example from your .env file. (#49)
  • couple security patches (#50, #51)

0.13.0

Added

  • Added decrypt command. Decrypt .env.vault to prospective .env* files. .env.keys must be present. (#48)

0.12.0

Added

  • Append to .gitignore with gitignore command (also .dockerignore, .npmignore, and .vercelignore if existing) (#47)

0.11.0

Removed

  • no longer append to *ignore files automatically. too invasive. will provide as separate cli command (#45)

0.10.6

Changed

  • Improve error message when decryption fails (#40)

0.10.5

Changed

  • Rename predockerbuild command to prebuild (#36)

0.10.4

Added

  • Add predockerbuild command to prevent including .env file in your docker builds (#35)

0.10.3

Changed

  • If dotenvx is missing tell user how to install it from pre-commit (#34)
  • Add help notice for ci (when .env file not present) (#33)

0.10.2

Changed

  • Improve error message when custom --env-file passed (#32)

0.10.1

Changed

  • Adjust precommit verbosity and coloring
  • Add --install flag to precommit - installs to .git/hooks/pre-commit (#31)

0.10.0

Added

  • Added dotenvx precommit command and instructions for git pre-commit hook (#30)

0.9.0

Changed

  • Remove .flaskenv from appends (#27)
  • Improved error message when .env file is missing (#28)

0.8.4

Changed

Load axios with a try/catch depending on context 🐞 (#24)

0.8.3

Changed

Patched helpers.guessEnvironment bug when filepath contained a . in the folder name. 🐞 (#23)

0.8.2

Changed

Change path to axios in attempt for pkg to build correctly.

0.8.1

Added

Add axios (missing) to package-lock.json

0.8.0

Added

Added hub support. 🎉 (#16)

0.7.4

Changed

Create binaries with root:root defaults. (#21)

0.7.3

Added

Tell user about undefined subprocess with additional debug logs (#19)

0.7.2

Added

debug other signals send to execa process (#18)

0.7.1

Changed

Fix missed package.json#version

0.7.0

Added

handle SIGINT (#17)

0.6.13

write to /latest only for releases repo (#15)

0.6.12

Changed

do not package README alongside binary. adds noise to a user's machine. keep their machine shiny. (#14)

0.6.11

Added

tell user what to do next (#13)

0.6.10

Patched

do not log when error code is 0 (#12)

0.6.9

Added

tell user when no changes to re-encrypt (#11)

0.6.8

Added

added help text when user's command fails. include link to report issue (#10)

0.6.7

Added

added next step help message when running dotenvx run with no argument (#9)

0.6.6

Added

help includes a command example as well as a full working 'try it out' example (#8)

0.6.5

Changed

made the info messaging more succinct (#7)

0.6.4

Added

added tagged images to hub.docker.com/u/dotenv

0.6.3

Changed

fixed the .env.keys file comment. spacing was off. (#6)

0.6.2

Added

added help text to encrypt. (#5)

0.6.1

Changed

removed the pad on the logging level. didn't look good when running in default INFO mode. (#4)

0.6.0

Added

prevent committing a .env* file to code. append to .gitignore, .dockerignore, .vercelignore, and .npmignore 🗂️ (#3)

0.5.0

Added

run support for .env.vault files 🔑 (#2)

0.4.0

Added

encrypt 🔐 (#1)

0.3.9 and prior

Please see commit history.