dotenvx
MUST USE for any task involving the dotenvx CLI tool — encrypting .env files, running commands with injected env vars, managing secrets across environments, and decrypting at runtime. Use this skill whenever the user mentions dotenvx, dotenv encryption, DOTENV_PRIVATE_KEY, encrypted .env files, or the dotenvx encrypt/run/set/get/decrypt/keypair commands. Also trigger when the user wants to: commit .env files safely to git, stop sharing secrets over Slack/chat, encrypt environment variables with public-key cryptography, set up multi-environment .env configs (production/staging/ci), manage secrets in a monorepo with -fk flag, migrate from python-dotenv or plain dotenv to encrypted envs, inject env vars into any process across any language (Node, Python, Ruby, Go, Rust, etc.), or configure CI/CD pipelines (GitHub Actions, Docker) with encrypted env files. This skill contains the authoritative CLI reference — without it, responses will hallucinate non-existent commands and flags.
NPX Install
npx skill4agent add narasaka/skills dotenvxTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →dotenvx CLI
dotenvrun- — inject env vars into any command, any language
dotenvx run - — encrypt
dotenvx encryptfiles with public-key cryptography (secp256k1).env - /
dotenvx set— manage individual env varsget - — decrypt
dotenvx decryptfiles back to plaintext.env - Multi-environment support via flag and
-fconventionDOTENV_PRIVATE_KEY_*
Installation
# npm (local to project)
npm install @dotenvx/dotenvx --save
# global installs
curl -sfS https://dotenvx.sh | sh # curl
brew install dotenvx/brew/dotenvx # brew
winget install dotenvx # windows
docker run -it --rm -v $(pwd):/app dotenv/dotenvx help # dockerrequire('@dotenvx/dotenvx').config()
// or: import '@dotenvx/dotenvx/config'Core Commands
dotenvx run
dotenvx run.envdotenvx run -- <command>| Flag | Description |
|---|---|
| Specify env file(s). Repeatable. Default: |
| Set inline env var |
| Later files/values override earlier ones (default: first wins) |
| Exit code 1 on any error (missing file, decrypt failure) |
| Ignore specific errors (e.g., |
| Load files using Next.js or dotenv-flow convention |
| Specify path to |
| Suppress all output except errors |
| Verbose logging |
| Debug-level logging |
| Set log level: |
# Basic usage
dotenvx run -- node index.js
# Specific env file
dotenvx run -f .env.production -- node index.js
# Multiple env files (first file's values win by default)
dotenvx run -f .env.local -f .env -- node index.js
# Override: last file wins
dotenvx run -f .env.local -f .env --overload -- node index.js
# Inline env var (overrides file values)
dotenvx run --env HELLO=String -f .env -- node index.js
# Any language works
dotenvx run -- python3 app.py
dotenvx run -- ruby index.rb
dotenvx run -- go run main.go
dotenvx run -- cargo run
dotenvx run -- php artisan serve
dotenvx run -- next dev
# Shell expansion (use subshell to prevent premature expansion)
dotenvx run --env="HELLO=World" -- sh -c 'echo Hello $HELLO'
# Strict mode for CI
dotenvx run -f .env.ci --strict -- node build.js- By default, env vars already set in the shell take precedence over file values
.env - With multiple files, the first file's value wins (historic dotenv behavior)
-f - reverses this: later files override earlier ones
--overload - flag values take precedence over file values
--env
${VAR}.env# Variable expansion
USERNAME="admin"
DATABASE_URL="postgres://${USERNAME}@localhost/mydb"
# Default values (use fallback if unset/empty)
DB_HOST=${DB_HOST:-localhost}
DB_PORT=${DB_PORT:-5432}
# Alternate values (use alternate if variable IS set)
DEBUG_MODE=${NODE_ENV:+false}
# Command substitution
WHOAMI="$(whoami)"CERT="-----BEGIN CERTIFICATE-----
MIIB...
-----END CERTIFICATE-----"Important: What dotenvx Does NOT Have
- ❌ — use
dotenvx keysinsteaddotenvx keypair - ❌ — no such command
dotenvx status - ❌ — to rotate, use
dotenvx rotateto update values, or decrypt → delete .env.keys → re-encryptdotenvx set - ❌ flag — does not exist
--env-name - ❌ files — dotenvx encrypts in place, not to a separate vault file
.env.vault - ❌ — the correct env var is
DOTENVX_PRIVATE_KEY(no X in the middle)DOTENV_PRIVATE_KEY - ❌ — there is no Python package; dotenvx is a CLI tool that wraps any language
pip install dotenvx - ❌ — no Python API; use
dotenvx.load_dotenv()at the CLI leveldotenvx run -- python app.py
dotenvx encrypt
dotenvx encrypt.envDOTENV_PUBLIC_KEY.envDOTENV_PRIVATE_KEY.env.keysdotenvx encrypt # encrypts .env
dotenvx encrypt -f .env.production # encrypts specific file
dotenvx encrypt --stdout # output to stdout instead of in-place- contains encrypted values +
.envDOTENV_PUBLIC_KEY - contains
.env.keys(keep this secret, never commit it)DOTENV_PRIVATE_KEY - The encrypted is safe to commit to version control
.env
dotenvx decrypt
dotenvx decrypt.envdotenvx decrypt # decrypts .env
dotenvx decrypt -f .env.production # decrypts specific file
dotenvx decrypt --stdout # output to stdout.env.keysDOTENV_PRIVATE_KEY*dotenvx set
dotenvx set.envdotenvx set KEY value # set in .env
dotenvx set KEY value -f .env.production # set in specific file
dotenvx set KEY "multi word value" # quoted values
dotenvx set KEY value -fk .env.keys -f apps/app1/.env # monorepodotenvx get
dotenvx getdotenvx get HELLO # from .env
dotenvx get HELLO -f .env.production # from specific file
dotenvx get HELLO --env HELLO=Override # from --env string
dotenvx get HELLO --overload # with overload semantics
dotenvx get HELLO --strict # exit 1 if key missing
dotenvx get HELLO --convention=nextjs # with convention
dotenvx get HELLO -fk .env.keys -f app/.env # monorepodotenvx get # all vars from .env as JSON
dotenvx get -f .env.production # all vars from specific file
dotenvx get --all # include DOTENV_PUBLIC_KEY
dotenvx get --format shell # output as KEY=value linesdotenvx keypair
dotenvx keypair.envdotenvx keypair # all keypairs as JSON
dotenvx keypair DOTENV_PRIVATE_KEY # just the private key
dotenvx keypair -f .env.production # for specific file
dotenvx keypair DOTENV_PRIVATE_KEY_PRODUCTION -f .env.productionEncryption Workflow
Initial Setup
# 1. Create your .env
echo "DATABASE_URL=postgres://localhost/mydb" > .env
echo "API_KEY=sk-secret123" >> .env
# 2. Encrypt it
dotenvx encrypt
# ✔ encrypted (.env)
# Creates .env.keys with your private key
# 3. Commit .env (encrypted, safe), do NOT commit .env.keys
echo ".env.keys" >> .gitignore
git add .env .gitignore
git commit -m "add encrypted env"Multi-Environment Encryption
# Encrypt each environment
dotenvx encrypt -f .env.production
dotenvx encrypt -f .env.staging
dotenvx encrypt -f .env.ci
# Each creates a corresponding private key in .env.keys:
# DOTENV_PRIVATE_KEY_PRODUCTION="..."
# DOTENV_PRIVATE_KEY_STAGING="..."
# DOTENV_PRIVATE_KEY_CI="..."Runtime Decryption
DOTENV_PRIVATE_KEY_*dotenvx run# The private key suffix matches the file suffix
DOTENV_PRIVATE_KEY="key" dotenvx run -- node app.js # decrypts .env
DOTENV_PRIVATE_KEY_PRODUCTION="key" dotenvx run -- node app.js # decrypts .env.production
DOTENV_PRIVATE_KEY_CI="key" dotenvx run -- node app.js # decrypts .env.ci
# Combine multiple
DOTENV_PRIVATE_KEY="k1" DOTENV_PRIVATE_KEY_PRODUCTION="k2" dotenvx run -- node app.js
# Comma-separated keys for monorepos (same environment, different apps)
DOTENV_PRIVATE_KEY_CI="key1,key2" dotenvx run -f app1/.env.ci -f app2/.env.ci -- node app.jsCI/CD Integration
# GitHub Actions example
name: deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: curl -fsS https://dotenvx.sh/install.sh | sh
- run: dotenvx run -- node build.js
env:
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}Conventions
--convention=nextjs
--convention=nextjs.env.$(NODE_ENV).local.env.local.env.$(NODE_ENV).env
dotenvx run --convention=nextjs -- next dev--convention=flow
--convention=flowDOTENV_ENVNODE_ENVDOTENV_ENV=development dotenvx run --convention=flow -- node app.jsMonorepo Support
-fk.env.keys# Set values for different apps
dotenvx set HELLO app1 -fk .env.keys -f apps/app1/.env
dotenvx set HELLO app2 -fk .env.keys -f apps/app2/.env
# Run with shared keys
dotenvx run -fk .env.keys -f apps/app1/.env -- node apps/app1/index.js
# Get values
dotenvx get HELLO -fk .env.keys -f apps/app1/.envDocker
FROM node:latest
RUN curl -fsS https://dotenvx.sh/install.sh | sh
COPY . .
CMD ["dotenvx", "run", "--", "node", "index.js"]docker run -it --rm -v $(pwd):/app dotenv/dotenvx run -- node index.jsCommon Patterns
dotenvx set NEW_SECRET "value" -f .env.production
# Automatically re-encryptsdotenvx set API_KEY "new-key-value" -f .env.productiondotenvx get -f .env.production # needs private key available
dotenvx get API_KEY -f .env.production # single valuedotenvx encrypt -f .env.production
# Done. Commit the encrypted .env.production, store .env.keys privately.dotenvx run --quiet -- ./my-script.shdotenvx run -f .env.ci --strict -- npm testGitignore Recommendations
# Never commit private keys
.env.keys
# Encrypted .env files ARE safe to commit
# !.env
# !.env.production
# !.env.stagingTroubleshooting
- — the specified
MISSING_ENV_FILEfile doesn't exist. Create it or use.env.--ignore=MISSING_ENV_FILE - — the requested key isn't in the
MISSING_KEYfile..env - Decryption fails — ensure the correct is set. The suffix must match the file suffix (e.g.,
DOTENV_PRIVATE_KEY_*for_PRODUCTION)..env.production - Deno + encrypt — don't use . Deno has incomplete cipher support. Install dotenvx as a binary instead.
deno run npm:@dotenvx/dotenvx encrypt - Shell expanding prematurely — use a subshell:
$VARSdotenvx run -- sh -c 'echo $MY_VAR'
Extension Commands (dotenvx ext
)
dotenvx extdotenvx ext genexample # generate .env.example from .env
dotenvx ext genexample -f .env.production # from specific file
dotenvx ext gitignore # append .env.keys to .gitignore
dotenvx ext ls # list all .env files in project
dotenvx ext ls -f .env.production # check specific file
dotenvx ext settings # view current dotenvx settings