Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More โ†’
Socket
Sign inDemoInstall
Socket

@dotenvx/dotenvx

Package Overview
Dependencies
Maintainers
2
Versions
179
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dotenvx/dotenvx

a better dotenvโ€“from the creator of `dotenv`

  • 1.29.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
210K
increased by16.27%
Maintainers
2
Weekly downloads
ย 
Created
Source

dotenvx

a better dotenvโ€“from the creator of dotenv.

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

ย 

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

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

ย 

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

with curl ๐ŸŒ
curl -sfS https://dotenvx.sh | sh
dotenvx help

curl installs

ย 

with brew ๐Ÿบ
brew install dotenvx/brew/dotenvx
dotenvx help

brew installs

ย 

with docker ๐Ÿณ
docker run -it --rm -v $(pwd):/app dotenv/dotenvx help

docker pulls

ย 

with github releases ๐Ÿ™
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

ย 

or with windows ๐ŸŸฆ๐ŸŸฉ๐ŸŸฅ๐ŸŸจ
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

  • TypeScript ๐Ÿ“˜
    // package.json
    {
      "type": "module",
      "dependencies": {
        "chalk": "^5.3.0"
      }
    }
    
    // index.ts
    import chalk from 'chalk'
    console.log(chalk.blue(`Hello ${process.env.HELLO}`))
    
    $ npm install
    $ echo "HELLO=World" > .env
    
    $ dotenvx run -- npx tsx index.ts
    Hello World
    
  • Deno ๐Ÿฆ•
    $ 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.

  • Bun ๐ŸฅŸ
    $ 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
    
  • Python ๐Ÿ
    $ 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

  • PHP ๐Ÿ˜
    $ echo "HELLO=World" > .env
    $ echo '<?php echo "Hello {$_SERVER["HELLO"]}\n";' > index.php
    
    $ dotenvx run -- php index.php
    Hello World
    

    see extended php guide

  • Ruby ๐Ÿ’Ž
    $ echo "HELLO=World" > .env
    $ echo 'puts "Hello #{ENV["HELLO"]}"' > index.rb
    
    $ dotenvx run -- ruby index.rb
    Hello World
    

    see extended ruby guide

  • Go ๐Ÿน
    $ 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

  • Rust ๐Ÿฆ€
    $ 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

  • Java โ˜•๏ธ
    $ 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
    
  • Clojure ๐ŸŒฟ
    $ echo "HELLO=World" > .env
    $ echo '(println "Hello" (System/getenv "HELLO"))' > index.clj
    
    $ dotenvx run -- clojure -M index.clj
    Hello World
    
  • Kotlin ๐Ÿ“
    $ 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
    
  • .NET ๐Ÿ”ต
    $ 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
    
  • Bash ๐Ÿ–ฅ๏ธ
    $ echo "HELLO=World" > .env
    
    $ dotenvx run --quiet -- sh -c 'echo Hello $HELLO'
    Hello World
    
  • Fish ๐Ÿ 
    $ echo "HELLO=World" > .env
    
    $ dotenvx run --quiet -- sh -c 'echo Hello $HELLO'
    Hello World
    
  • Cron โฐ
    # run every day at 8am
    0 8 * * * dotenvx run -- /path/to/myscript.sh
    
  • Frameworks โ–ฒ
    $ dotenvx run -- next dev
    $ dotenvx run -- npm start
    $ dotenvx run -- bin/rails s
    $ dotenvx run -- php artisan serve
    

    see framework guides

  • Docker ๐Ÿณ
    $ docker run -it --rm -v $(pwd):/app dotenv/dotenvx run -- node index.js
    

    Or in any image:

    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

  • CI/CDs ๐Ÿ™
    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

  • Platforms
    # 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

  • Process Managers
    // pm2
    "scripts": {
      "start": "dotenvx run -- pm2-runtime start ecosystem.config.js --env production"
    },
    

    see process manager guides

  • npx
    # alternatively use npx
    $ npx @dotenvx/dotenvx run -- node index.js
    $ npx @dotenvx/dotenvx run -- next dev
    $ npx @dotenvx/dotenvx run -- npm start
    
  • npm
    $ npm install @dotenvx/dotenvx --save
    
    {
      "scripts": {
        "start": "./node_modules/.bin/dotenvx run -- node index.js"
      },
      "dependencies": {
        "@dotenvx/dotenvx": "^0.5.0"
      }
    }
    
    $ npm run start
    
    > start
    > ./node_modules/.bin/dotenvx run -- node index.js
    
    [dotenvx][info] loading env (1) from .env
    Hello World
    
  • asdf
    # use dotenvx with asdf
    $ asdf plugin add dotenvx
    $ asdf install dotenvx latest
    

    thank you @jgburet of Paris ๐Ÿ‡ซ๐Ÿ‡ท

  • Git
    # use as a git submodule
    $ git dotenvx run -- node index.js
    $ git dotenvx run -- next dev
    $ git dotenvx run -- npm start
    
  • Variable Expansion

    Reference and expand variables already on your machine for use in your .env file.

    # .env
    USERNAME="username"
    DATABASE_URL="postgres://${USERNAME}@localhost/my_database"
    
    // index.js
    console.log('DATABASE_URL', process.env.DATABASE_URL)
    
    $ dotenvx run --debug -- node index.js
    [dotenvx@0.14.1] injecting env (2) from .env
    DATABASE_URL postgres://username@localhost/my_database
    
  • Command Substitution

    Add the output of a command to one of your variables in your .env file.

    # .env
    DATABASE_URL="postgres://$(whoami)@localhost/my_database"
    
    // index.js
    console.log('DATABASE_URL', process.env.DATABASE_URL)
    
    $ 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.

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

$ dotenvx run -f .env.production -- node index.js
[dotenvx][info] loading env (1) from .env.production
Hello production
> ^^

More examples

  • multiple `.env` files
    $ echo "HELLO=local" > .env.local
    
    $ echo "HELLO=World" > .env
    
    $ dotenvx run -f .env.local -f .env -- node index.js
    [dotenvx][info] loading env (1) from .env.local,.env
    Hello local
    
  • `--overload` flag
    $ echo "HELLO=local" > .env.local
    
    $ echo "HELLO=World" > .env
    
    $ dotenvx run -f .env.local -f .env --overload -- node index.js
    [dotenvx][info] loading env (1) from .env.local,.env
    Hello World
    
  • `--verbose` flag
    $ 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][info] loading env (1) from .env.production
    Hello production
    
  • `--debug` flag
    $ 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][info] loading env (1) from .env.production
    Hello production
    
  • `--quiet` flag

    Use --quiet to suppress all output (except errors).

    $ echo "HELLO=production" > .env.production
    
    $ dotenvx run -f .env.production --quiet -- node index.js
    Hello production
    
  • `--log-level` flag

    Set --log-level to whatever you wish. For example, to supress warnings (risky), set log level to error:

    $ 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

  • `--convention` flag

    Load envs using Next.js' convention. Set --convention to nextjs:

    $ 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
    

    (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

  • `.env`
    $ echo "HELLO=World" > .env
    $ dotenvx encrypt
    $ echo "console.log('Hello ' + process.env.HELLO)" > index.js
    
    $ dotenvx run -- node index.js
    [dotenvx] injecting env (2) from .env
    Hello World
    
  • `.env.production`
    $ 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] 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.

  • `.env.ci`
    $ 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] 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?

  • combine multiple encrypted .env files
    $ 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] 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?

  • combine multiple encrypted .env files for monorepo
    $ 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] 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] 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.

  • `--stdout`
    $ echo "HELLO=World" > .env
    $ dotenvx encrypt --stdout
    $ dotenvx encrypt --stdout > .env.encrypted
    
  • other curves

    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.

  • `run` - Variable Expansion

    Reference and expand variables already on your machine for use in your .env file.

    # .env
    USERNAME="username"
    DATABASE_URL="postgres://${USERNAME}@localhost/my_database"
    
    // index.js
    console.log('DATABASE_URL', process.env.DATABASE_URL)
    
    $ dotenvx run --debug -- node index.js
    [dotenvx] injecting env (2) from .env
    DATABASE_URL postgres://username@localhost/my_database
    
  • `run` - Command Substitution

    Add the output of a command to one of your variables in your .env file.

    # .env
    DATABASE_URL="postgres://$(whoami)@localhost/my_database"
    
    // index.js
    console.log('DATABASE_URL', process.env.DATABASE_URL)
    
    $ dotenvx run --debug -- node index.js
    [dotenvx] injecting env (1) from .env
    DATABASE_URL postgres://yourusername@localhost/my_database
    
  • `run` - Shell Expansion

    Prevent your shell from expanding inline $VARIABLES before dotenvx has a chance to inject it. Use a subshell.

    $ dotenvx run --env="HELLO=World" -- sh -c 'echo Hello $HELLO'
    Hello World
    
  • `run` - multiple `-f` flags

    Compose multiple .env files for environment variables loading, as you need.

    $ 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] injecting env (1) from .env.local, .env
    Hello local
    
  • `run --env HELLO=String`

    Set environment variables as a simple KEY=value string pair.

    $ echo "HELLO=World" > .env
    $ echo "console.log('Hello ' + process.env.HELLO)" > index.js
    
    $ dotenvx run --env HELLO=String -f .env -- node index.js
    [dotenvx] injecting env (1) from .env, and --env flag
    Hello String
    
  • `run --overload`

    Override existing env variables. These can be variables already on your machine or variables loaded as files consecutively. The last variable seen will 'win'.

    $ 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] injecting env (1) from .env.local, .env
    Hello World
    
  • `DOTENV_PRIVATE_KEY=key run`

    Decrypt your encrypted .env by setting DOTENV_PRIVATE_KEY before dotenvx run.

    $ 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] injecting env (2) from .env
    Hello encrypted
    
  • `DOTENV_PRIVATE_KEY_PRODUCTION=key run`

    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.

    $ 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] 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.

  • `DOTENV_PRIVATE_KEY_CI=key dotenvx run`

    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.

    $ 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] 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?

  • `DOTENV_PRIVATE_KEY=key DOTENV_PRIVATE_KEY_PRODUCTION=key run` - Combine Multiple

    Decrypt your encrypted .env and .env.production files by setting DOTENV_PRIVATE_KEY and DOTENV_PRIVATE_KEY_PRODUCTION before dotenvx run.

    $ 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] 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] 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.

  • `run --verbose`

    Set log level to verbose. (log levels)

    $ 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] injecting env (1) from .env.production
    Hello production
    
  • `run --debug`

    Set log level to debug. (log levels)

    $ 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] injecting env (1) from .env.production
    executing process command [node index.js]
    expanding process command to [/opt/homebrew/bin/node index.js]
    Hello production
    
  • `run --quiet`

    Use --quiet to suppress all output (except errors). (log levels)

    $ 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
    
  • `run --log-level`

    Set --log-level to whatever you wish. For example, to supress warnings (risky), set log level to error:

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

  • `run --strict`

    Exit with code 1 if any errors are encountered - like a missing .env file or decryption failure.

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

  • `run --ignore`

    Ignore errors like MISSING_ENV_FILE.

    $ echo "console.log('Hello ' + process.env.HELLO)" > index.js
    
    $ dotenvx run -f .env.missing --ignore=MISSING_ENV_FILE -- node index.js
    ...
    
  • `run --convention=nextjs`

    Load envs using Next.js' convention. Set --convention to nextjs:

    $ 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] injecting env (1) from .env.development.local, .env.local, .env.development, .env
    Hello development local
    

    (more conventions available upon request)

  • `get KEY`

    Return a single environment variable's value.

    $ echo "HELLO=World" > .env
    
    $ dotenvx get HELLO
    World
    
  • `get KEY -f`

    Return a single environment variable's value from a specific .env file.

    $ echo "HELLO=World" > .env
    $ echo "HELLO=production" > .env.production
    
    $ dotenvx get HELLO -f .env.production
    production
    
  • `get KEY --env`

    Return a single environment variable's value from a --env string.

    $ dotenvx get HELLO --env HELLO=String -f .env.production
    String
    
  • `get KEY --overload`

    Return a single environment variable's value where each found value is overloaded.

    $ echo "HELLO=World" > .env
    $ echo "HELLO=production" > .env.production
    
    $ dotenvx get HELLO -f .env.production --env HELLO=String -f .env --overload
    World
    
  • `get KEY --strict`

    Exit with code 1 if any errors are encountered - like a missing key, missing .env file, or decryption failure.

    $ dotenvx get DOES_NOT_EXIST --strict
    [MISSING_KEY] missing DOES_NOT_EXIST key
    
  • `get KEY --convention=nextjs`

    Return a single environment variable's value using Next.js' convention. Set --convention to nextjs:

    $ 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
    
  • `get` (json)

    Return a json response of all key/value pairs in a .env file.

    $ echo "HELLO=World" > .env
    
    $ dotenvx get
    {"HELLO":"World"}
    
  • `get --format shell`

    Return a shell formatted response of all key/value pairs in a .env file.

    $ 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
    
  • `get --format eval`

    Return an eval-ready shell formatted response of all key/value pairs in a .env file.

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

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

  • `get --all`

    Return preset machine envs as well.

    $ echo "HELLO=World" > .env
    
    $ dotenvx get --all
    {"PWD":"/some/file/path","USER":"username","LIBRARY_PATH":"/usr/local/lib", ..., "HELLO":"World"}
    
  • `get --all --pretty-print`

    Make the output more readable - pretty print it.

    $ echo "HELLO=World" > .env
    
    $ dotenvx get --all --pretty-print
    {
      "PWD": "/some/filepath",
      "USER": "username",
      "LIBRARY_PATH": "/usr/local/lib",
      ...,
      "HELLO": "World"
    }
    
  • `set KEY value`

    Set an encrypted key/value (on by default).

    $ touch .env
    
    $ dotenvx set HELLO World
    set HELLO with encryption (.env)
    
  • `set KEY value -f`

    Set an (encrypted) key/value for another .env file.

    $ touch .env.production
    
    $ dotenvx set HELLO production -f .env.production
    set HELLO with encryption (.env.production)
    
  • `set KEY "value with spaces"`

    Set a value containing spaces.

    $ touch .env.ci
    
    $ dotenvx set HELLO "my ci" -f .env.ci
    set HELLO with encryption (.env.ci)
    
  • `set KEY -- "- + * รท"`

    If your value starts with a dash (-), then place two dashes instructing the cli that there are no more flag arguments.

    $ touch .env.ci
    
    $ dotenvx set HELLO -f .env.ci -- "- + * รท"
    set HELLO with encryption (.env.ci)
    
  • `set KEY value --plain`

    Set a plaintext key/value.

    $ touch .env
    
    $ dotenvx set HELLO World --plain
    set HELLO (.env)
    
  • `encrypt`

    Encrypt the contents of a .env file to an encrypted .env file.

    $ 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
    
  • `encrypt -f`

    Encrypt the contents of a specified .env file to an encrypted .env file.

    $ 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
    
  • `encrypt -k`

    Specify the key(s) to encrypt by passing --key.

    $ echo "HELLO=World\nHELLO2=Universe" > .env
    
    $ dotenvx encrypt -k HELLO2
    โœ” encrypted (.env)
    

    Even specify a glob pattern.

    $ echo "HELLO=World\nHOLA=Mundo" > .env
    
    $ dotenvx encrypt -k "HE*"
    โœ” encrypted (.env)
    
  • `encrypt -ek`

    Specify the key(s) to NOT encrypt by passing --exclude-key.

    $ echo "HELLO=World\nHELLO2=Universe" > .env
    
    $ dotenvx encrypt -ek HELLO
    โœ” encrypted (.env)
    

    Even specify a glob pattern.

    $ echo "HELLO=World\nHOLA=Mundo" > .env
    
    $ dotenvx encrypt -ek "HO*"
    โœ” encrypted (.env)
    
  • `encrypt --stdout`

    Encrypt the contents of a .env file and send to stdout.

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

    $ echo "HELLO=World" > .env
    $ dotenvx encrypt --stdout > somefile.txt
    
  • `decrypt`

    Decrypt the contents of an encrypted .env file to an unencrypted .env file.

    $ echo "HELLO=World" > .env
    $ dotenvx encrypt
    โœ” encrypted (.env)
    $ dotenvx decrypt
    โœ” decrypted (.env)
    
  • `decrypt -f`

    Decrypt the contents of a specified encrypted .env file to an unencrypted .env file.

    $ 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)
    
  • `decrypt -k`

    Decrypt the contents of a specified key inside an encrypted .env file.

    $ echo "HELLO=World\nHOLA=Mundo" > .env
    $ dotenvx encrypt
    โœ” encrypted (.env)
    $ dotenvx decrypt -k HELLO
    โœ” decrypted (.env)
    

    Even specify a glob pattern.

    $ echo "HELLO=World\nHOLA=Mundo" > .env
    $ dotenvx encrypt
    โœ” encrypted (.env)
    $ dotenvx decrypt -k "HE*"
    โœ” encrypted (.env)
    
  • `decrypt -ek`

    Decrypt the contents inside an encrypted .env file except for an exluded key.

    $ echo "HELLO=World\nHOLA=Mundo" > .env
    $ dotenvx encrypt
    โœ” encrypted (.env)
    $ dotenvx decrypt -ek HOLA
    โœ” decrypted (.env)
    

    Even specify a glob pattern.

    $ echo "HELLO=World\nHOLA=Mundo" > .env
    $ dotenvx encrypt
    โœ” encrypted (.env)
    $ dotenvx decrypt -ek "HO*"
    โœ” encrypted (.env)
    
  • `decrypt --stdout`

    Decrypt the contents of an encrypted .env file and send to stdout.

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

    $ dotenvx decrypt --stdout > somefile.txt
    
  • `keypair`

    Print public/private keys for .env file.

    $ echo "HELLO=World" > .env
    $ dotenvx encrypt
    
    $ dotenvx keypair
    {"DOTENV_PUBLIC_KEY":"<publicKey>","DOTENV_PRIVATE_KEY":"<privateKey>"}
    
  • `keypair -f .env.production`

    Print public/private keys for .env.production file.

    $ 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>"}
    
  • `keypair DOTENV_PRIVATE_KEY`

    Print specific keypair for .env file.

    $ echo "HELLO=World" > .env
    $ dotenvx encrypt
    
    $ dotenvx keypair DOTENV_PRIVATE_KEY
    <privateKey>
    
  • `keypair --format shell`

    Print a shell formatted reponse of public/private keys.

    $ echo "HELLO=World" > .env
    $ dotenx encrypt
    
    $ dotenvx keypair --format shell
    DOTENV_PUBLIC_KEY=<publicKey> DOTENV_PRIVATE_KEY=<privateKey>
    
  • `ls`

    Print all .env files in a tree structure.

    $ touch .env
    $ touch .env.production
    $ mkdir -p apps/backend
    $ touch apps/backend/.env
    
    $ dotenvx ls
    โ”œโ”€ .env.production
    โ”œโ”€ .env
    โ””โ”€ apps
       โ””โ”€ backend
          โ””โ”€ .env
    
  • `ls directory`

    Print all .env files inside a specified path to a directory.

    $ touch .env
    $ touch .env.production
    $ mkdir -p apps/backend
    $ touch apps/backend/.env
    
    $ dotenvx ls apps/backend
    โ””โ”€ .env
    
  • `ls -f`

    Glob .env filenames matching a wildcard.

    $ 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
    
  • `ls -ef`

    Glob .env filenames excluding a wildcard.

    $ 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
    
  • `help`

    Output help for dotenvx.

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

    $ 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] injecting env (1) from .env
      Hello World
    
  • `--version`

    Check current version of dotenvx.

    $ dotenvx --version
    X.X.X
    

Extensions ๐Ÿ”Œ

  • `ext genexample`

    In one command, generate a .env.example file from your current .env file contents.

    $ echo "HELLO=World" > .env
    
    $ dotenvx ext genexample
    โœ” updated .env.example (1)
    
    # .env.example
    HELLO=""
    
  • `ext genexample -f`

    Pass multiple .env files to generate your .env.example file from the combination of their contents.

    $ echo "HELLO=World" > .env
    $ echo "DB_HOST=example.com" > .env.production
    
    $ dotenvx ext genexample -f .env -f .env.production
    โœ” updated .env.example (2)
    
    # .env.example
    HELLO=""
    DB_HOST=""
    
  • `ext genexample directory`

    Generate a .env.example file inside the specified directory. Useful for monorepos.

    $ echo "HELLO=World" > .env
    $ mkdir -p apps/backend
    $ echo "HELLO=Backend" > apps/backend/.env
    
    $ dotenvx ext genexample apps/backend
    โœ” updated .env.example (1)
    
    # apps/backend/.env.example
    HELLO=""
    
  • `ext gitignore`

    Gitignore your .env files.

    $ dotenvx ext gitignore
    โœ” ignored .env* (.gitignore)
    
  • `ext gitignore --pattern`

    Gitignore specific pattern(s) of .env files.

    $ dotenvx ext gitignore --pattern .env.keys
    โœ” ignored .env.keys (.gitignore)
    
  • `ext precommit`

    Prevent .env files from being committed to code.

    $ dotenvx ext precommit
    [dotenvx][precommit] .env files (1) protected (encrypted or gitignored)
    
  • `ext precommit --install`

    Install a shell script to .git/hooks/pre-commit to prevent accidentally committing any .env files to source control.

    $ dotenvx ext precommit --install
    [dotenvx][precommit] dotenvx ext precommit installed [.git/hooks/pre-commit]
    
  • `ext prebuild`

    Prevent .env files from being built into your docker containers.

    Add it to your Dockerfile.

    # Dockerfile
    RUN curl -fsS https://dotenvx.sh | sh
    
    ...
    
    RUN dotenvx ext prebuild
    CMD ["dotenvx", "run", "--", "node", "index.js"]
    
  • `ext scan`

    Use gitleaks under the hood to scan for possible secrets in your code.

    $ dotenvx ext scan
    
        โ—‹
        โ”‚โ•ฒ
        โ”‚ โ—‹
        โ—‹ โ–‘
        โ–‘    gitleaks
    
    100 commits scanned.
    no leaks found
    

config() ๐Ÿ“ฆ

  • `config()`

    Use directly in node.js code.

    # .env
    HELLO="World"
    
    // index.js
    require('@dotenvx/dotenvx').config()
    
    console.log(`Hello ${process.env.HELLO}`)
    
    $ node index.js
    [dotenvx@1.24.5] injecting env (1) from .env
    Hello World
    

    It defaults to looking for a .env file.

  • `config(path: ['.env.local', '.env'])` - multiple files

    Specify path(s) to multiple .env files.

    # .env.local
    HELLO="Me"
    
    # .env
    HELLO="World"
    
    // index.js
    require('@dotenvx/dotenvx').config({path: ['.env.local', '.env']})
    
    console.log(`Hello ${process.env.HELLO}`)
    
    $ node index.js
    [dotenvx@1.24.5] injecting env (1) from .env.local, .env
    Hello Me
    
  • `config(overload: true)` - overload

    Use overload to overwrite the prior set value.

    # .env.local
    HELLO="Me"
    
    # .env
    HELLO="World"
    
    // index.js
    require('@dotenvx/dotenvx').config({path: ['.env.local', '.env'], overload: true})
    
    console.log(`Hello ${process.env.HELLO}`)
    
    $ node index.js
    [dotenvx@1.24.5] injecting env (1) from .env.local, .env
    Hello World
    
  • `config(strict: true)` - strict

    Use strict to throw if an error is encountered - like a missing .env file.

    # .env
    HELLO="World"
    
    // index.js
    require('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], strict: true})
    
    console.log(`Hello ${process.env.HELLO}`)
    
    $ node index.js
    Error: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)
    
  • `config(ignore:)` - ignore

    Use ignore to suppress specific errors like MISSING_ENV_FILE.

    # .env
    HELLO="World"
    
    // index.js
    require('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], ignore: ['MISSING_ENV_FILE']})
    
    console.log(`Hello ${process.env.HELLO}`)
    
    $ node index.js
    [dotenvx@1.24.5] injecting env (1) from .env.local, .env
    Hello World
    
  • `parse(src)`

    Parse a .env string directly in node.js code.

    // index.js
    const dotenvx = require('@dotenvx/dotenvx')
    const src = 'HELLO=World'
    const parsed = dotenvx.parse(src)
    console.log(`Hello ${parsed.HELLO}`)
    
    $ node index.js
    Hello World
    
  • `parse(src, {processEnv:})`

    Sometimes, you want to run parse without it accessing process.env. (You can pass a fake processEnv this way as well - sometimes useful.)

    // index.js
    const dotenvx = require('@dotenvx/dotenvx')
    const src = 'USER=Me'
    const parsed = dotenvx.parse(src, { processEnv: {} })
    console.log(`Hello ${parsed.USER}`)
    
    $ node index.js
    Hello Me
    
  • `parse(src, {privateKey:})`

    Decrypt an encrypted .env string with privateKey.

    // 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}`)
    
    $ node index.js
    Hello World
    

ย 

Guides

Go deeper into using dotenvx with detailed framework and platform guides.

ย 

FAQ

Why am I getting the error node: .env: not found?

You are using Node 20 or greater and it adds a differing implementation of --env-file flag support. Rather than warn on a missing .env file (like dotenv has historically done), it raises an error: node: .env: not found.

This fix is easy. Replace --env-file with -f.

# from this:
./node_modules/.bin/dotenvx run --env-file .env -- yourcommand
# to this:
./node_modules/.bin/dotenvx run -f .env -- yourcommand

more context

What happened to the .env.vault file?

I've decided we should sunset it as a technological solution to this.

The .env.vault file got us far, but it had limitations such as:

  • Pull Requests - it was difficult to tell which key had been changed
  • Security - there was no mechanism to give a teammate the ability to encrypt without also giving them the ability to decrypt. Sometimes you just want to let a contractor encrypt a new value, but you don't want them to know the rest of the secrets.
  • Conceptual - it takes more mental energy to understand the .env.vault format. Encrypted values inside a .env file is easier to quickly grasp.
  • Combining Multiple Files - there was simply no mechanism to do this well with the .env.vault file format.

That said, the .env.vault tooling will still stick around for at least 1 year under dotenvx vault parent command. I'm still using it in projects as are many thousands of other people.

How do I migrate my .env.vault file(s) to encrypted .env files?

Run $ dotenvx ext vault migrate and follow the instructions.

ย 

Contributing

You can fork this repo and create pull requests or if you have questions or feedback:

Keywords

FAQs

Package last updated on 09 Dec 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc