Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

dotenv

Package Overview
Dependencies
Maintainers
4
Versions
104
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dotenv - npm Package Compare versions

Comparing version
17.4.0
to
17.4.1
+7
-1
CHANGELOG.md

@@ -5,4 +5,10 @@ # Changelog

## [Unreleased](https://github.com/motdotla/dotenv/compare/v17.4.0...master)
## [Unreleased](https://github.com/motdotla/dotenv/compare/v17.4.1...master)
## [17.4.1](https://github.com/motdotla/dotenv/compare/v17.4.0...v17.4.1) (2026-04-05)
### Changed
* Change text `injecting` to `injected` ([#1005](https://github.com/motdotla/dotenv/pull/1005))
## [17.4.0](https://github.com/motdotla/dotenv/compare/v17.3.1...v17.4.0) (2026-04-01)

@@ -9,0 +15,0 @@

+1
-1

@@ -309,3 +309,3 @@ const fs = require('fs')

_log(`injecting env (${keysCount}) from ${shortPaths.join(',')} ${dim(`// tip: ${_getRandomTip()}`)}`)
_log(`injected env (${keysCount}) from ${shortPaths.join(',')} ${dim(`// tip: ${_getRandomTip()}`)}`)
}

@@ -312,0 +312,0 @@

{
"name": "dotenv",
"version": "17.4.0",
"version": "17.4.1",
"description": "Loads environment variables from .env file",

@@ -5,0 +5,0 @@ "main": "lib/main.js",

@@ -39,3 +39,3 @@ <a href="https://dotenvx.com/?utm_source=github&utm_medium=readme&utm_campaign=motdotla-dotenv&utm_content=banner"><img src="https://dotenvx.com/dotenv-banner.png" alt="dotenvx" /></a>

$ node index.js
◇ injecting env (14) from .env
◇ injected env (14) from .env
```

@@ -47,2 +47,17 @@

## Uso con agentes
Instala este repositorio como paquete de habilidad para tu agente:
```sh
npx skills add motdotla/dotenv
```
```sh
# luego dile a Claude/Codex cosas como:
configura dotenv
actualiza dotenv a dotenvx
```
&nbsp;
## Avanzado

@@ -188,3 +203,3 @@

$ dotenvx run --debug -- node index.js
⟐ injecting env (2) from .env · dotenvx@1.59.1
⟐ injected env (2) from .env · dotenvx@1.59.1
DATABASE_URL postgres://username@localhost/my_database

@@ -210,3 +225,3 @@ ```

$ dotenvx run --debug -- node index.js
⟐ injecting env (1) from .env · dotenvx@1.59.1
⟐ injected env (1) from .env · dotenvx@1.59.1
DATABASE_URL postgres://yourusername@localhost/my_database

@@ -227,3 +242,3 @@ ```

$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js
⟐ injecting env (2) from .env.production · dotenvx@1.59.1
⟐ injected env (2) from .env.production · dotenvx@1.59.1
Hello Production

@@ -230,0 +245,0 @@ ```

@@ -39,3 +39,3 @@ <a href="https://dotenvx.com/?utm_source=github&utm_medium=readme&utm_campaign=motdotla-dotenv&utm_content=banner"><img src="https://dotenvx.com/dotenv-banner.png" alt="dotenvx" /></a>

$ node index.js
◇ injecting env (14) from .env
◇ injected env (14) from .env
```

@@ -47,2 +47,17 @@

## Agent Usage
Install this repo as an agent skill package:
```sh
npx skills add motdotla/dotenv
```
```sh
# ask Claude or Codex to do things like:
set up dotenv
upgrade dotenv to dotenvx
```
&nbsp;
## Advanced

@@ -188,3 +203,3 @@

$ dotenvx run --debug -- node index.js
⟐ injecting env (2) from .env · dotenvx@1.59.1
⟐ injected env (2) from .env · dotenvx@1.59.1
DATABASE_URL postgres://username@localhost/my_database

@@ -210,3 +225,3 @@ ```

$ dotenvx run --debug -- node index.js
⟐ injecting env (1) from .env · dotenvx@1.59.1
⟐ injected env (1) from .env · dotenvx@1.59.1
DATABASE_URL postgres://yourusername@localhost/my_database

@@ -227,3 +242,3 @@ ```

$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js
⟐ injecting env (2) from .env.production · dotenvx@1.59.1
⟐ injected env (2) from .env.production · dotenvx@1.59.1
Hello Production

@@ -230,0 +245,0 @@ ```

@@ -8,3 +8,2 @@ ---

Dotenv is a zero-dependency module that loads environment variables from a `.env` file into [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). Storing configuration in the environment separate from code is based on [The Twelve-Factor App](https://12factor.net/config) methodology.

@@ -14,4 +13,4 @@

&nbsp;
## Usage

@@ -36,2 +35,3 @@

```javascript
// index.js
require('dotenv').config() // or import 'dotenv/config' if you're using ES6

@@ -41,7 +41,26 @@ ...

```
```sh
$ node index.js
◇ injected env (14) from .env
```
That's it. `process.env` now has the keys and values you defined in your `.env` file:
That's it. `process.env` now has the keys and values you defined in your `.env` file.
&nbsp;
## Agent Usage
Install this repo as an agent skill package:
```sh
npx skills add motdotla/dotenv
```
```sh
# ask Claude or Codex to do things like:
set up dotenv
upgrade dotenv to dotenvx
```
&nbsp;
## Advanced

@@ -145,3 +164,3 @@

>
> It serves the same purpose (you do not need to require and load dotenv), adds better debugging, and works with ANY language, framework, or platform. – [motdotla](https://mot.la)
> It serves the same purpose (you do not need to require and load dotenv), adds better debugging, and works with ANY language, framework, or platform. – [motdotla](https://not.la)

@@ -188,3 +207,3 @@ You can use the `--require` (`-r`) [command line option](https://nodejs.org/api/cli.html#-r---require-module) to preload dotenv. By doing this, you do not need to require and load dotenv in your application code.

$ dotenvx run --debug -- node index.js
[dotenvx@0.14.1] injecting env (2) from .env
⟐ injected env (2) from .env · dotenvx@1.59.1
DATABASE_URL postgres://username@localhost/my_database

@@ -210,3 +229,3 @@ ```

$ dotenvx run --debug -- node index.js
[dotenvx@0.14.1] injecting env (1) from .env
⟐ injected env (1) from .env · dotenvx@1.59.1
DATABASE_URL postgres://yourusername@localhost/my_database

@@ -227,3 +246,3 @@ ```

$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js
[dotenvx] injecting env (2) from .env.production
⟐ injected env (2) from .env.production · dotenvx@1.59.1
Hello Production

@@ -261,3 +280,3 @@ ```

[more environment examples](https://dotenvx.com/docs/quickstart/environments)
[more environment examples](https://dotenvx.com/docs/quickstart/environments?utm_source=github&utm_medium=readme&utm_campaign=motdotla-dotenv&utm_content=docs-environments)

@@ -330,42 +349,4 @@ </details>

&nbsp;
## Agents
<img src="https://dotenvx.com/assets/img/as2/9.jpg" height="400" alt="dotenvx-as2" align="right"/>
> Software is changing, and dotenv must change with it—that is why I built [agentic secret storage (AS2)](https://dotenvx.com/as2). Agents run code without humans at terminals, so plaintext `.env` files are the wrong primitive.
>
> AS2 is built for autonomous software: encrypted by default, zero console access, and cryptography‑first delivery that keeps operators out of the loop.
>
> It is backed by [Vestauth](https://github.com/vestauth/vestauth), the trusted, pioneering auth layer for agents—giving each agent a cryptographic identity so requests are signed with private keys and verified with public keys. No shared secrets to leak.
>
> It's what I'm using now. - [motdotla](https://mot.la)
### Quickstart
Install vestauth and initialize your agent.
```bash
npm i -g vestauth
vestauth agent init
```
Your agent `set`s secrets with a simple `curl` endpoint:
```bash
vestauth agent curl -X POST https://as2.dotenvx.com/set -d '{"KEY":"value"}'
```
And your agent `get`s secrets with a simple `curl` endpoint:
```bash
vestauth agent curl "https://as2.dotenvx.com/get?key=KEY"
```
That's it! This new primitive unlocks secrets access for agents without human-in-the-loop, oauth flows, or API keys. It's the future for agents.
## FAQ

@@ -517,3 +498,3 @@

Use the [docker prebuild hook](https://dotenvx.com/docs/features/prebuild).
Use the [docker prebuild hook](https://dotenvx.com/docs/features/prebuild?utm_source=github&utm_medium=readme&utm_campaign=motdotla-dotenv&utm_content=docs-prebuild).

@@ -592,4 +573,4 @@ ```bash

&nbsp;
## Docs

@@ -660,3 +641,2 @@

$ node index.js
[dotenv@17.0.0] injecting env (1) from .env
Hello World

@@ -779,4 +759,4 @@ ```

&nbsp;
## CHANGELOG

@@ -786,4 +766,4 @@

&nbsp;
## Who's using dotenv?

@@ -790,0 +770,0 @@

---
name: dotenvx
description: Encrypt .env files, use multiple environments, expand variables, and run any command with environment variables injected using dotenvx. Use when the task involves secret encryption, .env.production or .env.staging setups, variable expansion like ${DATABASE_URL}, running CLI commands with env vars, CI/CD secret management, or migrating beyond basic dotenv. Triggers on requests involving dotenvx, encrypted .env files, multiple environment configs, agentic secret storage, or AS2.
description: Use dotenvx to run commands with environment variables, manage multiple .env files, expand variables, and encrypt env files for safe commits and CI/CD.
---

@@ -8,337 +8,121 @@

*a secure dotenv* — from the creator of [`dotenv`](https://github.com/motdotla/dotenv).
`dotenvx` is a secure dotenv workflow for any language.
* run anywhere (cross-platform)
* multi-environment
* encrypted envs
Use this skill when you need to:
- run commands with env vars from `.env` files
- load multiple environment files (`.env`, `.env.production`, etc.)
- encrypt `.env` files and keep keys out of git
- use env files safely in CI/CD
[Read the whitepaper](https://dotenvx.com/dotenvx.pdf?v=README)
## Quickstart
Install and use it in code just like `dotenv`.
Install:
```sh
npm install @dotenvx/dotenvx --save
# or globally:
# curl -sfS https://dotenvx.sh | sh
# brew install dotenvx/brew/dotenvx
```
Node usage:
```js
// index.js
require('@dotenvx/dotenvx').config()
// or import '@dotenvx/dotenvx/config' // for esm
console.log(`Hello ${process.env.HELLO}`)
// or: import '@dotenvx/dotenvx/config'
```
or install globally — *unlocks dotenv for any language, framework, or platform!*
CLI usage (any language):
```sh
# curl
curl -sfS https://dotenvx.sh | sh
# brew
brew install dotenvx/brew/dotenvx
# docker
docker run -it --rm -v $(pwd):/app dotenv/dotenvx help
# windows
winget install dotenvx
dotenvx run -- node index.js
```
## Run Anywhere
## Core Commands
```sh
$ echo "HELLO=World" > .env
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
Run with default `.env`:
$ node index.js
Hello undefined # without dotenvx
$ dotenvx run -- node index.js
Hello World # with dotenvx
```
Works with TypeScript, Deno, Bun, Python, PHP, Ruby, Go, Rust, Java, .NET, Bash, and more. See [extended quickstart guide](https://dotenvx.com/docs/quickstart).
Framework shortcuts:
```sh
$ dotenvx run -- next dev
$ dotenvx run -- npm start
$ dotenvx run -- bin/rails s
$ dotenvx run -- php artisan serve
dotenvx run -- <command>
```
## Multiple Environments
Load a specific file:
Create a `.env.production` file and use `-f` to load it:
```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
dotenvx run -f .env.production -- <command>
```
Load multiple files (first value wins):
Load multiple files (first wins):
```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
dotenvx run -f .env.local -f .env -- <command>
```
Use `--overload` to make subsequent files win instead:
Make later files win:
```sh
$ dotenvx run -f .env.local -f .env --overload -- node index.js
Hello World
dotenvx run -f .env.local -f .env --overload -- <command>
```
### Convention-based loading
## Encryption Workflow
```sh
# Next.js convention
$ dotenvx run --convention=nextjs -- node index.js
Encrypt:
# dotenv-flow convention
$ dotenvx run --convention=flow -- node index.js
```
## Encryption
Add encryption to your `.env` files with a single command:
```sh
$ dotenvx encrypt
✔ encrypted (.env)
dotenvx encrypt
# or
dotenvx encrypt -f .env.production
```
A `DOTENV_PUBLIC_KEY` (encryption key) and a `DOTENV_PRIVATE_KEY` (decryption key) are generated using the same public-key cryptography as Bitcoin (secp256k1).
Run encrypted envs by supplying private key(s):
Encrypt a specific environment file:
```sh
$ dotenvx encrypt -f .env.production
DOTENV_PRIVATE_KEY_PRODUCTION="<key>" dotenvx run -f .env.production -- <command>
```
Decrypt at runtime by setting the private key (found in `.env.keys`):
Git rule:
```sh
$ DOTENV_PRIVATE_KEY="<key from .env.keys>" dotenvx run -- node index.js
[dotenvx@1.X.X] injecting env (2) from .env
Hello World
```
Per-environment private keys follow the pattern `DOTENV_PRIVATE_KEY_<ENVIRONMENT>`:
```sh
$ DOTENV_PRIVATE_KEY_PRODUCTION="<key>" dotenvx run -- node index.js
# loads .env.production
$ DOTENV_PRIVATE_KEY_CI="<key>" dotenvx run -- node index.js
# loads .env.ci
```
Combine multiple encrypted files:
```sh
$ DOTENV_PRIVATE_KEY="<key>" DOTENV_PRIVATE_KEY_PRODUCTION="<key>" dotenvx run -- node index.js
[dotenvx@1.X.X] injecting env (3) from .env, .env.production
```
**Commit the encrypted `.env` file. Never commit `.env.keys`.**
```sh
# .gitignore
```gitignore
.env.keys
```
## CI/CD
Commit encrypted `.env*` files if needed, but never commit `.env.keys`.
```yaml
# GitHub Actions
- name: Run app
env:
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
run: dotenvx run -f .env.production -- node index.js
```
## Variable Expansion
Install in CI:
Example:
```sh
curl -fsS https://dotenvx.sh/install.sh | sh
```
## Advanced
### Variable Expansion
Reference and expand variables already on your machine:
```ini
# .env
USERNAME="username"
DATABASE_URL="postgres://${USERNAME}@localhost/my_database"
USERNAME="alice"
DATABASE_URL="postgres://${USERNAME}@localhost/mydb"
```
```sh
$ dotenvx run -- node index.js
DATABASE_URL postgres://username@localhost/my_database
```
`dotenvx run` resolves `${...}` expressions at runtime.
### Default Values
## CI/CD Pattern
```ini
# .env
DATABASE_HOST=${DB_HOST:-localhost}
DATABASE_PORT=${DB_PORT:-5432}
```
Set private keys as CI secrets, then run through `dotenvx`:
### Alternate Values
```ini
# .env
NODE_ENV=production
DEBUG_MODE=${NODE_ENV:+false}
```yaml
env:
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
run: dotenvx run -f .env.production -- node index.js
```
### Interpolation Syntax Summary
## Agent Usage
```ini
# Default value - use variable if set/non-empty, otherwise use default
TEST=${DEFINED_VAR:-fallback} # "hello" (if DEFINED_VAR=hello)
TEST=${UNDEFINED_VAR:-fallback} # "fallback"
Install this repo as an agent skill package:
# Default value (no colon) - use variable if set, otherwise use default
TEST=${EMPTY_VAR-fallback} # "" (empty, but set)
TEST=${UNDEFINED_VAR-fallback} # "fallback"
# Alternate value - use alternate if variable is set/non-empty, otherwise empty
TEST=${DEFINED_VAR:+alternate} # "alternate"
TEST=${EMPTY_VAR:+alternate} # "" (empty)
# Alternate value (no colon) - use alternate if variable is set, otherwise empty
TEST=${EMPTY_VAR+alternate} # "alternate" (empty but set counts)
```
### Command Substitution
```ini
# .env
DATABASE_URL="postgres://$(whoami)@localhost/my_database"
```
### `get` — Read a value
```sh
$ echo "HELLO=World" > .env
$ dotenvx get HELLO
World
$ dotenvx get HELLO -f .env.production
production
$ dotenvx get # all key/value pairs as JSON
{"HELLO":"World"}
npx skills add motdotla/dotenv
```
### `set` — Write a value (auto-encrypts if file is encrypted)
Typical requests:
- "set up dotenvx for production"
- "encrypt my .env.production and wire CI"
- "load .env.local and .env safely"
```sh
$ dotenvx set HELLO World
$ dotenvx set HELLO Production -f .env.production
```
## References
### Pre-commit hook — Prevent committing plaintext secrets
```sh
npm i -g @dotenvx/dotenvx
dotenvx precommit --install
```
### `--strict` — Fail on errors
```sh
$ dotenvx run -f .env.missing --strict -- node index.js
[MISSING_ENV_FILE] missing .env.missing file
```
### Quiet / Debug / Log levels
```sh
$ dotenvx run -f .env.production --quiet -- node index.js # suppress output
$ dotenvx run -f .env.production --debug -- node index.js # verbose debug
$ dotenvx run -f .env.production --log-level=error -- node index.js
```
## Agentic Secret Storage (AS2)
> Agents run code without humans at terminals, so plaintext `.env` files are the wrong primitive. AS2 is built for autonomous software: encrypted by default, zero console access, and cryptography‑first delivery.
Install vestauth and initialize your agent:
```bash
npm i -g vestauth
vestauth agent init
```
Set secrets:
```bash
vestauth agent curl -X POST https://as2.dotenvx.com/set -d '{"KEY":"value"}'
```
Get secrets:
```bash
vestauth agent curl "https://as2.dotenvx.com/get?key=KEY"
```
See [dotenvx.com/as2](https://dotenvx.com/as2) for the full specification.
## Comparison: dotenv vs dotenvx
| Feature | dotenv | dotenvx |
|---------|--------|---------|
| Load `.env` | ✅ | ✅ |
| Variable expansion | ❌ | ✅ |
| Command substitution | ❌ | ✅ |
| Encryption | ❌ | ✅ |
| Multiple environments | basic | ✅ |
| Works with any language | ❌ | ✅ |
| Agentic secret storage | ❌ | ✅ |
For basic `.env` loading in Node.js, see the [dotenv skill](../dotenv/SKILL.md).
## FAQ
**Should I commit my `.env` file?**
No — unless you encrypt it with `dotenvx encrypt`. Then yes, commit the encrypted `.env` and keep `.env.keys` out of source control.
**How do I use dotenvx in Docker?**
```sh
FROM node:latest
RUN curl -fsS https://dotenvx.sh/install.sh | sh
CMD ["dotenvx", "run", "--", "node", "index.js"]
```
**How do I handle environment variable precedence in containers?**
By default, existing environment variables take precedence over `.env` files (historic dotenv principle). Use `--overload` to make `.env` files win instead.
```sh
# Env var from cloud provider wins (default)
$ MODEL_REGISTRY=registry.azure.com/v2 dotenvx run -f .env.prod -- node app.js
# .env.prod wins (with --overload)
$ MODEL_REGISTRY=registry.azure.com/v2 dotenvx run -f .env.prod --overload -- node app.js
```
- https://dotenvx.com/docs/quickstart
- https://github.com/dotenvx/dotenvx