{"id":13433234,"url":"https://github.com/dotenvx/dotenvx","last_synced_at":"2026-04-24T02:01:13.047Z","repository":{"id":207965723,"uuid":"720267554","full_name":"dotenvx/dotenvx","owner":"dotenvx","description":"a secure dotenv–from the creator of `dotenv`","archived":false,"fork":false,"pushed_at":"2026-04-17T21:05:38.000Z","size":20654,"stargazers_count":5351,"open_issues_count":64,"forks_count":140,"subscribers_count":11,"default_branch":"main","last_synced_at":"2026-04-17T22:39:55.359Z","etag":null,"topics":["cli","configuration-file","curl","dotenv","dotenvx","end-to-end-encryption","env","environment-variables","homebrew","secret-management","secret-manager","secrets","secrets-management","security-tools","winget"],"latest_commit_sha":null,"homepage":"https://dotenvx.com/docs","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dotenvx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-11-18T00:55:16.000Z","updated_at":"2026-04-17T21:37:01.000Z","dependencies_parsed_at":"2023-11-21T01:25:14.949Z","dependency_job_id":"ca7de13e-2166-4240-a47f-ef8c3e9c2f1b","html_url":"https://github.com/dotenvx/dotenvx","commit_stats":null,"previous_names":["dotenv-org/git-dotenv","dotenv-org/dotenv","dotenvx/dotenvx"],"tags_count":301,"template":false,"template_full_name":null,"purl":"pkg:github/dotenvx/dotenvx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotenvx%2Fdotenvx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotenvx%2Fdotenvx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotenvx%2Fdotenvx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotenvx%2Fdotenvx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dotenvx","download_url":"https://codeload.github.com/dotenvx/dotenvx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotenvx%2Fdotenvx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32205942,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T01:12:49.758Z","status":"online","status_checked_at":"2026-04-24T02:00:07.115Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","configuration-file","curl","dotenv","dotenvx","end-to-end-encryption","env","environment-variables","homebrew","secret-management","secret-manager","secrets","secrets-management","security-tools","winget"],"created_at":"2024-07-31T02:01:22.884Z","updated_at":"2026-04-24T02:01:13.027Z","avatar_url":"https://github.com/dotenvx.png","language":"JavaScript","readme":"[![dotenvx](https://dotenvx.com/banner.png)](https://dotenvx.com)\n\n*a secure dotenv*–from the creator of [`dotenv`](https://github.com/motdotla/dotenv).\n\n* run anywhere (cross-platform)\n* multi-environment\n* encrypted envs\n\n[Read the whitepaper](https://dotenvx.com/dotenvx.pdf?v=README)\n\n\u0026nbsp;\n\n\n### Quickstart [![npm version](https://img.shields.io/npm/v/@dotenvx/dotenvx.svg)](https://www.npmjs.com/package/@dotenvx/dotenvx) [![downloads](https://img.shields.io/npm/dw/@dotenvx/dotenvx)](https://www.npmjs.com/package/@dotenvx/dotenvx) [![test suite](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/motdotenv/bb76445765a9731e7d824a6efdf53524/raw/dotenvxTestCount.json)](https://github.com/dotenvx/dotenvx/tree/main/tests) \n\nInstall and use it in code just like `dotenv`.\n\n```sh\nnpm install @dotenvx/dotenvx --save\n```\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config()\n// or import '@dotenvx/dotenvx/config' // for esm\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n\u0026nbsp;\n\nor install globally - *unlocks dotenv for any language, framework, or platform!*\n\n\u003cdetails\u003e\u003csummary\u003ewith npm 🌍\u003c/summary\u003e\u003cbr\u003e\n\n```sh\nnpm i -g @dotenvx/dotenvx\ndotenvx encrypt\n```\n\n[![npm installs](https://img.shields.io/npm/dt/@dotenvx/dotenvx)](https://npmjs.com/@dotenvx/dotenvx)\n\n\u0026nbsp;\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003ewith curl 🌐\u003c/summary\u003e\u003cbr\u003e\n\n```sh\ncurl -sfS https://dotenvx.sh | sh\ndotenvx encrypt\n```\n\n[![curl installs](https://img.shields.io/endpoint?url=https://dotenvx.sh/stats/curl\u0026label=curl%20installs)](https://github.com/dotenvx/dotenvx.sh/blob/main/install.sh)\n\n\u0026nbsp;\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003ewith brew 🍺\u003c/summary\u003e\u003cbr\u003e\n\n```sh\nbrew install dotenvx/brew/dotenvx\ndotenvx encrypt\n```\n\n[![brew installs](https://img.shields.io/github/downloads/dotenvx/dotenvx/total?label=brew%20installs)](https://github.com/dotenvx/homebrew-brew/blob/main/Formula/dotenvx.rb)\n\n\u0026nbsp;\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003ewith docker 🐳\u003c/summary\u003e\u003cbr\u003e\n\n```sh\ndocker run -it --rm -v $(pwd):/app dotenv/dotenvx encrypt\n```\n\n[![docker pulls](https://img.shields.io/docker/pulls/dotenv/dotenvx)](https://hub.docker.com/r/dotenv/dotenvx)\n\n\u0026nbsp;\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003ewith github releases 🐙\u003c/summary\u003e\u003cbr\u003e\n\n```sh\ncurl -L -o dotenvx.tar.gz \"https://github.com/dotenvx/dotenvx/releases/latest/download/dotenvx-$(uname -s)-$(uname -m).tar.gz\"\ntar -xzf dotenvx.tar.gz\n./dotenvx encrypt\n```\n\n[![github releases](https://img.shields.io/github/downloads/dotenvx/dotenvx/total)](https://github.com/dotenvx/dotenvx/releases)\n\n\u0026nbsp;\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\u003csummary\u003eor windows 🪟\u003c/summary\u003e\u003cbr\u003e\n\n```sh\nwinget install dotenvx\ndotenvx encrypt\n```\n\n\u003c/details\u003e\n\n\u0026nbsp;\n\n## Run Anywhere\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ node index.js\nHello undefined # without dotenvx\n\n$ dotenvx run -- node index.js\nHello Dotenvx # with dotenvx\n\u003e :-D\n```\n\nsee [extended quickstart guide](https://dotenvx.com/docs/quickstart)\n\nMore examples\n\n\u003cdetails\u003e\u003csummary\u003eTypeScript 📘\u003c/summary\u003e\u003cbr\u003e\n\n```json\n// package.json\n{\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"chalk\": \"^5.3.0\"\n  }\n}\n```\n\n```js\n// index.ts\nimport chalk from 'chalk'\nconsole.log(chalk.blue(`Hello ${process.env.HELLO}`))\n```\n\n```sh\n$ npm install\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx run -- npx tsx index.ts\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eCloudflare Workers ⛅️\u003c/summary\u003e\u003cbr\u003e\n\n```sh\ncp .env .env.txt\n```\n\n```js\nimport envSrc from '../.env.txt' // txt so cloudflare includes it in deployment\nimport dotenvx from '@dotenvx/dotenvx'\n\n// use `wrangler secret put DOTENV_PRIVATE_KEY` to set decryption key once\nconst config = dotenvx.config({ envs: [{ type: 'env', value: envSrc, privateKeyName: 'DOTENV_PRIVATE_KEY' }] })\nconst envx = config.parsed\n\nexport default {\n  async fetch(request, env, ctx) {\n    return new Response(`Hello ${envx.HELLO}`)\n  }\n}\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eDeno 🦕\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"console.log('Hello ' + Deno.env.get('HELLO'))\" \u003e index.ts\n\n$ deno run --allow-env index.ts\nHello undefined\n\n$ dotenvx run -- deno run --allow-env index.ts\nHello Dotenvx\n```\n\n\u003e [!WARNING]\n\u003e 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.\n\u003e\n\u003e ```\n\u003e $ deno run -A npm:@dotenvx/dotenvx encrypt\n\u003e Unknown cipher\n\u003e ```\n\u003e \n\u003e Instead, use `dotenvx` as designed, by installing the cli as a binary - via curl, brew, etc.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eBun 🥟\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Test\" \u003e .env.test\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ bun index.js\nHello undefined\n\n$ dotenvx run -f .env.test -- bun index.js\nHello Test\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003ePython 🐍\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo 'import os;print(\"Hello \" + os.getenv(\"HELLO\", \"\"))' \u003e index.py\n\n$ dotenvx run -- python3 index.py\nHello Dotenvx\n```\n\nsee [extended python guide](https://dotenvx.com/docs/quickstart)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003ePHP 🐘\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo '\u003c?php echo \"Hello {$_SERVER[\"HELLO\"]}\\n\";' \u003e index.php\n\n$ dotenvx run -- php index.php\nHello Dotenvx\n```\n\nsee [extended php guide](https://dotenvx.com/docs/quickstart)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eRuby 💎\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo 'puts \"Hello #{ENV[\"HELLO\"]}\"' \u003e index.rb\n\n$ dotenvx run -- ruby index.rb\nHello Dotenvx\n```\n\nsee [extended ruby guide](https://dotenvx.com/docs/quickstart)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eGo 🐹\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo 'package main; import (\"fmt\"; \"os\"); func main() { fmt.Printf(\"Hello %s\\n\", os.Getenv(\"HELLO\")) }' \u003e main.go\n\n$ dotenvx run -- go run main.go\nHello Dotenvx\n```\n\nsee [extended go guide](https://dotenvx.com/docs/quickstart)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eRust 🦀\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo 'fn main() {let hello = std::env::var(\"HELLO\").unwrap_or(\"\".to_string());println!(\"Hello {hello}\");}' \u003e src/main.rs\n\n$ dotenvx run -- cargo run\nHello Dotenvx\n```\n\nsee [extended rust guide](https://dotenvx.com/docs/quickstart)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eJava ☕️\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo 'public class Index { public static void main(String[] args) { System.out.println(\"Hello \" + System.getenv(\"HELLO\")); } }' \u003e index.java\n\n$ dotenvx run -- java index.java\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eClojure 🌿\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo '(println \"Hello\" (System/getenv \"HELLO\"))' \u003e index.clj\n\n$ dotenvx run -- clojure -M index.clj\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eKotlin 📐\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo 'fun main() { val hello = System.getenv(\"HELLO\") ?: \"\"; println(\"Hello $hello\") }' \u003e index.kt\n$ kotlinc index.kt -include-runtime -d index.jar\n\n$ dotenvx run -- java -jar index.jar\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e.NET 🔵\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ dotnet new console -n HelloWorld -o HelloWorld\n$ cd HelloWorld\n$ echo \"HELLO=Dotenvx\" | Out-File -FilePath .env -Encoding utf8\n$ echo 'Console.WriteLine($\"Hello {Environment.GetEnvironmentVariable(\"HELLO\")}\");' \u003e Program.cs\n\n$ dotenvx run -- dotnet run\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eBash 🖥️\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx run --quiet -- sh -c 'echo Hello $HELLO'\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eFish 🐠\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx run --quiet -- sh -c 'echo Hello $HELLO'\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eCron ⏰\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n# run every day at 8am\n0 8 * * * dotenvx run -- /path/to/myscript.sh\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eFrameworks ▲\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ dotenvx run -- next dev\n$ dotenvx run -- npm start\n$ dotenvx run -- bin/rails s\n$ dotenvx run -- php artisan serve\n```\n\nsee [framework guides](https://dotenvx.com/docs#frameworks)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eDocker 🐳\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ docker run -it --rm -v $(pwd):/app dotenv/dotenvx run -- node index.js\n```\n\nOr in any image:\n\n```Containerfile\nFROM node:latest\nRUN echo \"HELLO=Dotenvx\" \u003e .env \u0026\u0026 echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\nRUN curl -fsS https://dotenvx.sh/install.sh | sh\nCMD [\"/usr/local/bin/dotenvx\", \"run\", \"--\", \"echo\", \"Hello $HELLO\"]\n```\n\nsee [docker guide](https://dotenvx.com/docs/platforms/docker)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eCI/CDs 🐙\u003c/summary\u003e\u003cbr\u003e\n\n```yaml\nname: build\non: [push]\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v3\n    - uses: actions/setup-node@v3\n      with:\n        node-version: 16\n    - run: curl -fsS https://dotenvx.sh/install.sh | sh\n    - run: dotenvx run -- node build.js\n      env:\n        DOTENV_KEY: ${{ secrets.DOTENV_KEY }}\n```\n\nsee [github actions guide](https://dotenvx.com/docs/cis/github-actions)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003ePlatforms\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n# heroku\nheroku buildpacks:add https://github.com/dotenvx/heroku-buildpack-dotenvx\n\n# docker\nRUN curl -fsS https://dotenvx.sh | sh\n\n# vercel\nnpm install @dotenvx/dotenvx --save\n```\n\nsee [platform guides](https://dotenvx.com/docs#platforms)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eProcess Managers\u003c/summary\u003e\u003cbr\u003e\n\n```js\n// pm2\n\"scripts\": {\n  \"start\": \"dotenvx run -- pm2-runtime start ecosystem.config.js --env production\"\n},\n```\n\nsee [process manager guides](https://dotenvx.com/docs#process-managers)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003enpx\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n# alternatively use npx\n$ npx @dotenvx/dotenvx run -- node index.js\n$ npx @dotenvx/dotenvx run -- next dev\n$ npx @dotenvx/dotenvx run -- npm start\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003enpm\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ npm install @dotenvx/dotenvx --save\n```\n\n```json\n{\n  \"scripts\": {\n    \"start\": \"./node_modules/.bin/dotenvx run -- node index.js\"\n  },\n  \"dependencies\": {\n    \"@dotenvx/dotenvx\": \"^0.5.0\"\n  }\n}\n```\n\n```sh\n$ npm run start\n\n\u003e start\n\u003e ./node_modules/.bin/dotenvx run -- node index.js\n\n[dotenvx@1.X.X] injecting env (1) from .env.production\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003easdf\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n# use dotenvx with asdf\n$ asdf plugin add dotenvx\n$ asdf install dotenvx latest\n```\n\nthank you [@jgburet](https://github.com/jgburet/asdf-dotenvx) of Paris 🇫🇷\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eGit\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n# use as a git submodule\n$ git dotenvx run -- node index.js\n$ git dotenvx run -- next dev\n$ git dotenvx run -- npm start\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eVariable Expansion\u003c/summary\u003e\u003cbr\u003e\n\nReference and expand variables already on your machine for use in your .env file.\n\n```ini\n# .env\nUSERNAME=\"username\"\nDATABASE_URL=\"postgres://${USERNAME}@localhost/my_database\"\n```\n```js\n// index.js\nconsole.log('DATABASE_URL', process.env.DATABASE_URL)\n```\n```sh\n$ dotenvx run --debug -- node index.js\n[dotenvx@0.14.1] injecting env (2) from .env\nDATABASE_URL postgres://username@localhost/my_database\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003eCommand Substitution\u003c/summary\u003e\u003cbr\u003e\n\nAdd the output of a command to one of your variables in your .env file.\n\n```ini\n# .env\nDATABASE_URL=\"postgres://$(whoami)@localhost/my_database\"\n```\n```js\n// index.js\nconsole.log('DATABASE_URL', process.env.DATABASE_URL)\n```\n```sh\n$ dotenvx run --debug -- node index.js\n[dotenvx@0.14.1] injecting env (1) from .env\nDATABASE_URL postgres://yourusername@localhost/my_database\n```\n\n\u003c/details\u003e\n\n\n\u0026nbsp;\n\n## Multiple Environments\n\n\u003e Create a `.env.production` file and use `-f` to load it. It's straightforward, yet flexible.\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.production -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.production\nHello production\n\u003e ^^\n```\n\nMore examples\n\n\u003cdetails\u003e\u003csummary\u003emultiple `.env` files\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=local\" \u003e .env.local\n\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx run -f .env.local -f .env -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.local,.env\nHello local\n```\n\nNote 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.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003e`--overload` flag\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=local\" \u003e .env.local\n\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx run -f .env.local -f .env --overload -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.local,.env\nHello Dotenvx\n```\n\nNote that with `--overload` subsequent files DO override pre-existing variables defined in previous files.\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`--verbose` flag\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n\n$ dotenvx run -f .env.production --verbose -- node index.js\n[dotenvx][verbose] injecting env from /path/to/.env.production\n[dotenvx][verbose] HELLO set\n[dotenvx@1.X.X] injecting env (1) from .env.production\nHello production\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`--debug` flag\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n\n$ dotenvx run -f .env.production --debug -- node index.js\n[dotenvx][debug] configuring options\n[dotenvx][debug] {\"envFile\":[\".env.production\"]}\n[dotenvx][verbose] injecting env from /path/to/.env.production\n[dotenvx][debug] reading env from /path/to/.env.production\n[dotenvx][debug] parsing env from /path/to/.env.production\n[dotenvx][debug] {\"HELLO\":\"production\"}\n[dotenvx][debug] writing env from /path/to/.env.production\n[dotenvx][verbose] HELLO set\n[dotenvx][debug] HELLO set to production\n[dotenvx@1.X.X] injecting env (1) from .env.production\nHello production\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`--quiet` flag\u003c/summary\u003e\u003cbr\u003e\n\nUse `--quiet` to suppress all output (except errors).\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n\n$ dotenvx run -f .env.production --quiet -- node index.js\nHello production\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`--log-level` flag\u003c/summary\u003e\u003cbr\u003e\n\nSet `--log-level` to whatever you wish. For example, to suppress warnings (risky), set log level to `error`:\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n\n$ dotenvx run -f .env.production --log-level=error -- node index.js\nHello production\n```\n\nAvailable log levels are `error, warn, info, verbose, debug, silly`\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`--convention` flag\u003c/summary\u003e\u003cbr\u003e\n\nLoad envs using [Next.js' convention](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#environment-variable-load-order) or [dotenv-flow convention](https://www.npmjs.com/package/dotenv-flow). Set `--convention` to `nextjs` or `flow`:\n\n```sh\n$ echo \"HELLO=development local\" \u003e .env.development.local\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=development\" \u003e .env.development\n$ echo \"HELLO=env\" \u003e .env\n\n$ dotenvx run --convention=nextjs -- node index.js\nHello development local\n\n$ dotenvx run --convention=flow -- node index.js\nHello development local\n```\n\n(more conventions available upon request)\n\n\u003c/details\u003e\n\n\u0026nbsp;\n\n## Encryption\n\n\u003e Add encryption to your `.env` files with a single command. Use `dotenvx encrypt`.\n\n```sh\n$ dotenvx encrypt\n◈ encrypted (.env)\n```\n\n[![encrypted .env](https://github.com/user-attachments/assets/46dfe1a7-a027-4d80-9207-789eccc325dc)](https://dotenvx.com)\n\n\u003e A `DOTENV_PUBLIC_KEY` (encryption key) and a `DOTENV_PRIVATE_KEY` (decryption key) are generated using the same public-key cryptography as [Bitcoin](https://en.bitcoin.it/wiki/Secp256k1).\n\nMore examples\n\n\u003cdetails\u003e\u003csummary\u003e`.env`\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (2) from .env\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`.env.production`\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Production\" \u003e .env.production\n$ dotenvx encrypt -f .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ DOTENV_PRIVATE_KEY_PRODUCTION=\"\u003c.env.production private key\u003e\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (2) from .env.production\nHello Production\n```\n\nNote the `DOTENV_PRIVATE_KEY_PRODUCTION` ends with `_PRODUCTION`. This instructs `dotenvx run` to load the `.env.production` file.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`.env.ci`\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Ci\" \u003e .env.ci\n$ dotenvx encrypt -f .env.ci\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ DOTENV_PRIVATE_KEY_CI=\"\u003c.env.ci private key\u003e\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (2) from .env.ci\nHello Ci\n```\n\nNote the `DOTENV_PRIVATE_KEY_CI` ends with `_CI`. This instructs `dotenvx run` to load the `.env.ci` file. See the pattern?\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003ecombine multiple encrypted .env files\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ dotenvx set HELLO Dotenvx -f .env\n$ dotenvx set HELLO Production -f .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ DOTENV_PRIVATE_KEY=\"\u003c.env private key\u003e\" DOTENV_PRIVATE_KEY_PRODUCTION=\"\u003c.env.production private key\u003e\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (3) from .env, .env.production\nHello Dotenvx\n```\n\nNote 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?\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003ecombine multiple encrypted .env files for monorepo\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ mkdir app1\n$ mkdir app2\n$ dotenvx set HELLO app1 -f app1/.env.ci\n$ dotenvx set HELLO app2 -f app2/.env.ci\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ DOTENV_PRIVATE_KEY_CI=\"\u003capp1/privat ci key\u003e,\u003capp2/private ci key\u003e\" dotenvx run -f app1/.env.ci -f app2/.env.ci -- node index.js\n[dotenvx@1.X.X] injecting env (2) from app1/.env.ci,app2/.env.ci\nHello app1\n\n$ DOTENV_PRIVATE_KEY_CI=\"\u003capp1/privat ci key\u003e,\u003capp2/private ci key\u003e\" dotenvx run -f app1/.env.ci -f app2/.env.ci --overload -- node index.js\n[dotenvx@1.X.X] injecting env (2) from app1/.env.ci,app2/.env.ci\nHello app2\n```\n\nNote the `DOTENV_PRIVATE_KEY_CI` (and any `DOTENV_PRIVATE_KEY*`) can take multiple private keys by simply comma separating them.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`--stdout`\u003c/summary\u003e\u003cbr\u003e\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt --stdout\n$ dotenvx encrypt --stdout \u003e .env.encrypted\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eother curves\u003c/summary\u003e\u003cbr\u003e\n\n\u003e `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.\n\u003e \n\u003e If your organization's compliance department requires [NIST approved curves](https://csrc.nist.gov/projects/elliptic-curve-cryptography) or other curves like `curve25519`, please reach out at [security@dotenvx.com](mailto:security@dotenvx.com).\n\n\u003c/details\u003e\n\n\u0026nbsp;\n\n## Advanced\n\n\u003e Become a `dotenvx` power user.\n\u003e\n\n### CLI 📟\n\nAdvanced CLI commands.\n\n\u003cdetails\u003e\u003csummary\u003e`run` - Variable Expansion\u003c/summary\u003e\u003cbr\u003e\n\nReference and expand variables already on your machine for use in your .env file.\n\n```ini\n# .env\nUSERNAME=\"username\"\nDATABASE_URL=\"postgres://${USERNAME}@localhost/my_database\"\n```\n```js\n// index.js\nconsole.log('DATABASE_URL', process.env.DATABASE_URL)\n```\n```sh\n$ dotenvx run --debug -- node index.js\n[dotenvx@1.X.X] injecting env (2) from .env\nDATABASE_URL postgres://username@localhost/my_database\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Default Values\u003c/summary\u003e\u003cbr\u003e\n\nUse default values when environment variables are unset or empty.\n\n```ini\n# .env\n# Default value syntax: use value if set, otherwise use default\nDATABASE_HOST=${DB_HOST:-localhost}\nDATABASE_PORT=${DB_PORT:-5432}\n\n# Alternative syntax (no colon): use value if set, otherwise use default\nAPI_URL=${API_BASE_URL-https://api.example.com}\n```\n```js\n// index.js\nconsole.log('DATABASE_HOST', process.env.DATABASE_HOST)\nconsole.log('DATABASE_PORT', process.env.DATABASE_PORT)\nconsole.log('API_URL', process.env.API_URL)\n```\n```sh\n$ dotenvx run --debug -- node index.js\n[dotenvx@1.X.X] injecting env (3) from .env\nDATABASE_HOST localhost\nDATABASE_PORT 5432\nAPI_URL https://api.example.com\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Alternate Values\u003c/summary\u003e\u003cbr\u003e\n\nUse alternate values when environment variables are set and non-empty.\n\n```ini\n# .env\nNODE_ENV=production\n\n# Alternate value syntax: use alternate if set and non-empty, otherwise empty\nDEBUG_MODE=${NODE_ENV:+false}\nLOG_LEVEL=${NODE_ENV:+error}\n\n# Alternative syntax (no colon): use alternate if set, otherwise empty  \nCACHE_ENABLED=${NODE_ENV+true}\n```\n```js\n// index.js\nconsole.log('NODE_ENV', process.env.NODE_ENV)\nconsole.log('DEBUG_MODE', process.env.DEBUG_MODE)\nconsole.log('LOG_LEVEL', process.env.LOG_LEVEL)\nconsole.log('CACHE_ENABLED', process.env.CACHE_ENABLED)\n```\n```sh\n$ dotenvx run --debug -- node index.js\n[dotenvx@1.X.X] injecting env (4) from .env\nNODE_ENV production\nDEBUG_MODE false\nLOG_LEVEL error\nCACHE_ENABLED true\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Interpolation Syntax Summary (Variable Expansion, Default/Alternate Values)\u003c/summary\u003e\u003cbr\u003e\n\nComplete reference for variable interpolation patterns supported by dotenvx:\n\n```ini\n# .env\nDEFINED_VAR=hello\nEMPTY_VAR=\n# UNDEFINED_VAR is not set\n\n# Default value syntax - use variable if set/non-empty, otherwise use default\nTEST1=${DEFINED_VAR:-fallback}     # Result: \"hello\"\nTEST2=${EMPTY_VAR:-fallback}       # Result: \"fallback\"  \nTEST3=${UNDEFINED_VAR:-fallback}   # Result: \"fallback\"\n\n# Default value syntax (no colon) - use variable if set, otherwise use default\nTEST4=${DEFINED_VAR-fallback}      # Result: \"hello\"\nTEST5=${EMPTY_VAR-fallback}        # Result: \"\" (empty, but set)\nTEST6=${UNDEFINED_VAR-fallback}    # Result: \"fallback\"\n\n# Alternate value syntax - use alternate if variable is set/non-empty, otherwise empty\nTEST7=${DEFINED_VAR:+alternate}    # Result: \"alternate\"\nTEST8=${EMPTY_VAR:+alternate}      # Result: \"\" (empty)\nTEST9=${UNDEFINED_VAR:+alternate}  # Result: \"\" (empty)\n\n# Alternate value syntax (no colon) - use alternate if variable is set, otherwise empty  \nTEST10=${DEFINED_VAR+alternate}    # Result: \"alternate\"\nTEST11=${EMPTY_VAR+alternate}      # Result: \"alternate\" (empty but set)\nTEST12=${UNDEFINED_VAR+alternate}  # Result: \"\" (empty)\n```\n\n**Key differences:**\n- `:-` vs `-`: The colon makes empty values trigger the fallback\n- `:+` vs `+`: The colon makes empty values not trigger the alternate  \n- Default syntax (`-`): Use variable value or fallback\n- Alternate syntax (`+`): Use alternate value or empty string\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Command Substitution\u003c/summary\u003e\u003cbr\u003e\n\nAdd the output of a command to one of your variables in your .env file.\n\n```ini\n# .env\nDATABASE_URL=\"postgres://$(whoami)@localhost/my_database\"\n```\n```js\n// index.js\nconsole.log('DATABASE_URL', process.env.DATABASE_URL)\n```\n```sh\n$ dotenvx run --debug -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env\nDATABASE_URL postgres://yourusername@localhost/my_database\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Shell Expansion\u003c/summary\u003e\u003cbr\u003e\n\nPrevent your shell from expanding inline `$VARIABLES` before dotenvx has a chance to inject it. Use a subshell.\n\n```sh\n$ dotenvx run --env=\"HELLO=Dotenvx\" -- sh -c 'echo Hello $HELLO'\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Multiline\u003c/summary\u003e\u003cbr\u003e\n\nDotenvx supports multiline values. This is particularly useful in conjunction with Docker - which [does not support multiline values](https://stackoverflow.com/questions/50299617/set-multiline-environment-variable-with-dockerfile/79578348#79578348).\n\n```ini\n# .env\nMULTILINE_PEM=\"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNl1tL3QjKp3DZWM0T3u\nLgGJQwu9WqyzHKZ6WIA5T+7zPjO1L8l3S8k8YzBrfH4mqWOD1GBI8Yjq2L1ac3Y/\nbTdfHN8CmQr2iDJC0C6zY8YV93oZB3x0zC/LPbRYpF8f6OqX1lZj5vo2zJZy4fI/\nkKcI5jHYc8VJq+KCuRZrvn+3V+KuL9tF9v8ZgjF2PZbU+LsCy5Yqg1M8f5Jp5f6V\nu4QuUoobAgMBAAE=\n-----END PUBLIC KEY-----\"\n```\n\n```js\n// index.js\nconsole.log('MULTILINE_PEM', process.env.MULTILINE_PEM)\n```\n\n```sh\n$ dotenvx run -- node index.js\nMULTILINE_PEM -----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNl1tL3QjKp3DZWM0T3u\nLgGJQwu9WqyzHKZ6WIA5T+7zPjO1L8l3S8k8YzBrfH4mqWOD1GBI8Yjq2L1ac3Y/\nbTdfHN8CmQr2iDJC0C6zY8YV93oZB3x0zC/LPbRYpF8f6OqX1lZj5vo2zJZy4fI/\nkKcI5jHYc8VJq+KCuRZrvn+3V+KuL9tF9v8ZgjF2PZbU+LsCy5Yqg1M8f5Jp5f6V\nu4QuUoobAgMBAAE=\n-----END PUBLIC KEY-----\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Contextual Help\u003c/summary\u003e\u003cbr\u003e\n\nUnlike other dotenv libraries, dotenvx attempts to unblock you with contextual help.\n\nFor example, when missing a custom .env file:\n\n```sh\n$ dotenvx run -f .env.missing -- echo $HELLO\n[MISSING_ENV_FILE] missing file (/Users/scottmotte/Code/dotenvx/playground/apr-16/.env.missing). fix: [echo \"HELLO=Dotenvx\" \u003e .env.missing]\n```\n\nor when missing a KEY:\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx get GOODBYE\n[MISSING_KEY] missing key (GOODBYE)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - multiple `-f` flags\u003c/summary\u003e\u003cbr\u003e\n\nCompose multiple `.env` files for environment variables loading, as you need.\n\n```sh\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.local -f .env -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.local, .env\nHello local\n```\n\nNote 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.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --env HELLO=String`\u003c/summary\u003e\u003cbr\u003e\n\nSet environment variables as a simple `KEY=value` string pair.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run --env HELLO=String -f .env -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env, and --env flag\nHello String\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --overload`\u003c/summary\u003e\u003cbr\u003e\n\nOverride existing env variables. These can be variables already on your machine or variables loaded as files consecutively. The last variable seen will 'win'.\n\n```sh\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.local -f .env --overload -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.local, .env\nHello Dotenvx\n```\n\nNote that with `--overload` subsequent files DO override pre-existing variables defined in previous files.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run` - Environment Variable Precedence (Container/Cloud Deployments)\u003c/summary\u003e\u003cbr\u003e\n\nWhen deploying applications in containers or cloud environments, you often need to override specific environment variables at runtime without modifying committed `.env` files. By default, dotenvx follows the historic dotenv principle: **environment variables already present take precedence over `.env` files**.\n\n```sh\n# .env.prod contains: MODEL_REGISTRY=registry.company.com/models/v1\n$ echo \"MODEL_REGISTRY=registry.company.com/models/v1\" \u003e .env.prod\n$ echo \"console.log('MODEL_REGISTRY:', process.env.MODEL_REGISTRY)\" \u003e app.js\n\n# Without environment variable set - uses .env.prod value\n$ dotenvx run -f .env.prod -- node app.js\nMODEL_REGISTRY: registry.company.com/models/v1\n\n# With environment variable set (e.g., via Azure Container Service) - environment variable takes precedence\n$ MODEL_REGISTRY=registry.azure.com/models/v2 dotenvx run -f .env.prod -- node app.js\nMODEL_REGISTRY: registry.azure.com/models/v2\n\n# To force .env.prod to override environment variables, use --overload\n$ MODEL_REGISTRY=registry.azure.com/models/v2 dotenvx run -f .env.prod --overload -- node app.js\nMODEL_REGISTRY: registry.company.com/models/v1\n```\n\n**For container deployments:** Set environment variables through your cloud provider's UI/configuration (Azure Container Service, AWS ECS, etc.) to override specific values from committed `.env` files without rebuilding your application.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`DOTENV_PRIVATE_KEY=key run`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt your encrypted `.env` by setting `DOTENV_PRIVATE_KEY` before `dotenvx run`.\n\n```sh\n$ touch .env\n$ dotenvx set HELLO encrypted\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n# check your .env.keys files for your privateKey\n$ DOTENV_PRIVATE_KEY=\"122...0b8\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (2) from .env\nHello encrypted\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`DOTENV_PRIVATE_KEY_PRODUCTION=key run`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt 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.\n\n```sh\n$ touch .env.production\n$ dotenvx set HELLO \"production encrypted\" -f .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n# check .env.keys for your privateKey\n$ DOTENV_PRIVATE_KEY_PRODUCTION=\"122...0b8\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (2) from .env.production\nHello production encrypted\n```\n\nNote the `DOTENV_PRIVATE_KEY_PRODUCTION` ends with `_PRODUCTION`. This instructs dotenvx run to load the `.env.production` file.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`DOTENV_PRIVATE_KEY_CI=key dotenvx run`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt 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.\n\n```sh\n$ touch .env.ci\n$ dotenvx set HELLO \"ci encrypted\" -f .env.ci\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n# check .env.keys for your privateKey\n$ DOTENV_PRIVATE_KEY_CI=\"122...0b8\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (2) from .env.ci\nHello ci encrypted\n```\n\nNote the `DOTENV_PRIVATE_KEY_CI` ends with `_CI`. This instructs dotenvx run to load the `.env.ci` file. See the pattern?\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`DOTENV_PRIVATE_KEY=key DOTENV_PRIVATE_KEY_PRODUCTION=key run` - Combine Multiple\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt your encrypted `.env` and `.env.production` files by setting `DOTENV_PRIVATE_KEY` and `DOTENV_PRIVATE_KEY_PRODUCTION` before `dotenvx run`. \n\n```sh\n$ touch .env\n$ touch .env.production\n$ dotenvx set HELLO encrypted\n$ dotenvx set HELLO \"production encrypted\" -f .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n# check .env.keys for your privateKeys\n$ DOTENV_PRIVATE_KEY=\"122...0b8\" DOTENV_PRIVATE_KEY_PRODUCTION=\"122...0b8\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (3) from .env, .env.production\nHello encrypted\n\n$ DOTENV_PRIVATE_KEY_PRODUCTION=\"122...0b8\" DOTENV_PRIVATE_KEY=\"122...0b8\" dotenvx run -- node index.js\n[dotenvx@1.X.X] injecting env (3) from .env.production, .env\nHello production encrypted\n```\n\nCompose 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.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --verbose`\u003c/summary\u003e\u003cbr\u003e\n\nSet log level to `verbose`. ([log levels](https://docs.npmjs.com/cli/v8/using-npm/logging#setting-log-levels))\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.production --verbose -- node index.js\nloading env from .env.production (/path/to/.env.production)\nHELLO set\n[dotenvx@1.X.X] injecting env (1) from .env.production\nHello production\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --debug`\u003c/summary\u003e\u003cbr\u003e\n\nSet log level to `debug`. ([log levels](https://docs.npmjs.com/cli/v8/using-npm/logging#setting-log-levels))\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.production --debug -- node index.js\nprocess command [node index.js]\noptions: {\"env\":[],\"envFile\":[\".env.production\"]}\nloading env from .env.production (/path/to/.env.production)\n{\"HELLO\":\"production\"}\nHELLO set\nHELLO set to production\n[dotenvx@1.X.X] injecting env (1) from .env.production\nexecuting process command [node index.js]\nexpanding process command to [/opt/homebrew/bin/node index.js]\nHello production\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --quiet`\u003c/summary\u003e\u003cbr\u003e\n\nUse `--quiet` to suppress all output (except errors). ([log levels](https://docs.npmjs.com/cli/v8/using-npm/logging#setting-log-levels))\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.production --quiet -- node index.js\nHello production\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --log-level`\u003c/summary\u003e\u003cbr\u003e\n\nSet `--log-level` to whatever you wish. For example, to suppress warnings (risky), set log level to `error`:\n\n```sh\n$ echo \"HELLO=production\" \u003e .env.production\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.production --log-level=error -- node index.js\nHello production\n```\n\nAvailable log levels are `error, warn, info, verbose, debug, silly` ([source](https://docs.npmjs.com/cli/v8/using-npm/logging#setting-log-levels))\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --strict`\u003c/summary\u003e\u003cbr\u003e\n\nExit with code `1` if any errors are encountered - like a missing .env file or decryption failure.\n\n```sh\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.missing --strict -- node index.js\n[MISSING_ENV_FILE] missing file (/path/to/.env.missing). fix: [echo \"HELLO=Dotenvx\" \u003e .env.missing]\n```\n\nThis can be useful in `ci` scripts where you want to fail the ci if your `.env` file could not be decrypted at runtime.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --ignore`\u003c/summary\u003e\u003cbr\u003e\n\nIgnore errors like `MISSING_ENV_FILE`.\n\n```sh\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run -f .env.missing --ignore=MISSING_ENV_FILE -- node index.js\n...\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --convention=nextjs`\u003c/summary\u003e\u003cbr\u003e\n\nLoad envs using [Next.js' convention](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#environment-variable-load-order). Set `--convention` to `nextjs`:\n\n```sh\n$ echo \"HELLO=development local\" \u003e .env.development.local\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=development\" \u003e .env.development\n$ echo \"HELLO=env\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx run --convention=nextjs -- node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.local, .env.development, .env\nHello development local\n```\n\n(more conventions available upon request)\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --convention=flow`\u003c/summary\u003e\u003cbr\u003e\n\nLoad envs using [dotenv-flow's convention](https://www.npmjs.com/package/dotenv-flow). Set `--convention` to `flow`:\n\n```sh\n$ echo \"HELLO=development local\" \u003e .env.development.local\n$ echo \"HELLO=development\" \u003e .env.development\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=env\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ NODE_ENV=development dotenvx run --convention=flow -- node index.js \n[dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.development, .env.local, .env\nHello development local\n```\n\nFurther, we recommend using `DOTENV_ENV` over `NODE_ENV`– as `dotenvx` works everywhere, not just node.\n\n```sh\n$ DOTENV_ENV=development dotenvx run --convention=flow -- node index.js \n[dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.development, .env.local, .env\nHello development local\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run -fk`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path to `.env.keys`. This is useful with monorepos.\n\n```sh\n$ mkdir -p apps/app1\n$ touch apps/app1/.env\n$ dotenvx set HELLO Dotenvx -fk .env.keys -f apps/app1/.env\n\n$ dotenvx run -fk .env.keys -f apps/app1/.env -- yourcommand\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`run --no-ops`\u003c/summary\u003e\u003cbr\u003e\n\nTurn off [Dotenvx Ops](https://dotenvx.com/ops) features.\n\n```sh\n$ dotenvx run --no-ops -- yourcommand\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get KEY`\u003c/summary\u003e\u003cbr\u003e\n\nReturn a single environment variable's value.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx get HELLO\nWorld\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get KEY -f`\u003c/summary\u003e\u003cbr\u003e\n\nReturn a single environment variable's value from a specific `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"HELLO=production\" \u003e .env.production\n\n$ dotenvx get HELLO -f .env.production\nproduction\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get KEY -fk`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path to `.env.keys`. This is useful with monorepos.\n\n```sh\n$ mkdir -p apps/app1\n$ touch apps/app1/.env\n$ dotenvx set HELLO Dotenvx -fk .env.keys -f apps/app1/.env\n\n$ dotenvx get HELLO -fk .env.keys -f apps/app1/.env\nworld\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get KEY --env`\u003c/summary\u003e\u003cbr\u003e\n\nReturn a single environment variable's value from a `--env` string.\n\n```sh\n$ dotenvx get HELLO --env HELLO=String -f .env.production\nString\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003e`get KEY --overload`\u003c/summary\u003e\u003cbr\u003e\n\nReturn a single environment variable's value where each found value is overloaded.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"HELLO=production\" \u003e .env.production\n\n$ dotenvx get HELLO -f .env.production --env HELLO=String -f .env --overload\nWorld\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get KEY --strict`\u003c/summary\u003e\u003cbr\u003e\n\nExit with code `1` if any errors are encountered - like a missing key, missing .env file, or decryption failure.\n\n```sh\n$ dotenvx get DOES_NOT_EXIST --strict\n[MISSING_KEY] missing key (DOES_NOT_EXIST)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get KEY --convention=nextjs`\u003c/summary\u003e\u003cbr\u003e\n\nReturn a single environment variable's value using [Next.js' convention](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#environment-variable-load-order). Set `--convention` to `nextjs`:\n\n```sh\n$ echo \"HELLO=development local\" \u003e .env.development.local\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=development\" \u003e .env.development\n$ echo \"HELLO=env\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ dotenvx get HELLO --convention=nextjs\ndevelopment local\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get KEY --convention=flow`\u003c/summary\u003e\u003cbr\u003e\n\nReturn a single environment variable's value using [dotenv-flow's convention](https://www.npmjs.com/package/dotenv-flow). Set `--convention` to `flow`:\n\n```sh\n$ echo \"HELLO=development local\" \u003e .env.development.local\n$ echo \"HELLO=development\" \u003e .env.development\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=env\" \u003e .env\n$ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n$ NODE_ENV=development dotenvx get HELLO --convention=flow\ndevelopment local\n```\n\nFurther, we recommend using `DOTENV_ENV` over `NODE_ENV`– as `dotenvx` works everywhere, not just node.\n\n```sh\n$ DOTENV_ENV=development dotenvx get HELLO --convention=flow\ndevelopment local\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get` (json)\u003c/summary\u003e\u003cbr\u003e\n\nReturn a json response of all key/value pairs in a `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx get\n{\"HELLO\":\"Dotenvx\"}\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get --format shell`\u003c/summary\u003e\u003cbr\u003e\n\nReturn a shell formatted response of all key/value pairs in a `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"KEY=value\" \u003e\u003e .env\n\n$ dotenvx get --format shell\nHELLO=Dotenvx KEY=value\n```\n\nThis can be useful when combined with `env` on the command line.\n\n```\n$ echo \"console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)\" \u003e index.js\n$ env $(dotenvx get --format=shell) node index.js\nHello value World\n```\n\nor with `export`.\n\n```\n$ echo \"console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)\" \u003e index.js\n$ export $(dotenvx get --format=shell)\n$ node index.js\nHello value World\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get --format eval`\u003c/summary\u003e\u003cbr\u003e\n\nReturn an `eval`-ready shell formatted response of all key/value pairs in a `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"KEY=value\" \u003e\u003e .env\n\n$ dotenvx get --format eval\nHELLO=\"Dotenvx\"\nKEY=\"value\"\n```\n\nNote that this exports newlines and quoted strings.\n\nThis can be useful for more complex .env values (spaces, escaped characters, quotes, etc) combined with `eval` on the command line.\n\n```sh\n$ echo \"console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)\" \u003e index.js\n$ eval $(dotenvx get --format=eval) node index.js\nHello value World\n```\n\nBe 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.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003e`get --all`\u003c/summary\u003e\u003cbr\u003e\n\nReturn preset machine envs as well.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx get --all\n{\"PWD\":\"/some/file/path\",\"USER\":\"username\",\"LIBRARY_PATH\":\"/usr/local/lib\", ..., \"HELLO\":\"Dotenvx\"}\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get --all --pretty-print`\u003c/summary\u003e\u003cbr\u003e\n\nMake the output more readable - pretty print it.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx get --all --pretty-print\n{\n  \"PWD\": \"/some/filepath\",\n  \"USER\": \"username\",\n  \"LIBRARY_PATH\": \"/usr/local/lib\",\n  ...,\n  \"HELLO\": \"Dotenvx\"\n}\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set KEY value`\u003c/summary\u003e\u003cbr\u003e\n\nSet an encrypted key/value (on by default).\n\n```sh\n$ touch .env\n\n$ dotenvx set HELLO Dotenvx\nset HELLO with encryption (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set KEY value -f`\u003c/summary\u003e\u003cbr\u003e\n\nSet an (encrypted) key/value for another `.env` file.\n\n```sh\n$ touch .env.production\n\n$ dotenvx set HELLO production -f .env.production\nset HELLO with encryption (.env.production)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set KEY value -fk`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path to `.env.keys`. This is useful with monorepos.\n\n```sh\n$ mkdir -p apps/app1\n$ touch apps/app1/.env\n\n$ dotenvx set HELLO Dotenvx -fk .env.keys -f apps/app1/.env\nset HELLO with encryption (.env)\n```\n\nPut it to use.\n\n```sh\n$ dotenvx get -fk .env.keys -f apps/app1/.env\n```\n\nUse it with a relative path.\n\n```sh\n$ cd apps/app1\n$ dotenvx get -fk ../../.env.keys -f .env\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set KEY \"value with spaces\"`\u003c/summary\u003e\u003cbr\u003e\n\nSet a value containing spaces.\n\n```sh\n$ touch .env.ci\n\n$ dotenvx set HELLO \"my ci\" -f .env.ci\nset HELLO with encryption (.env.ci)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set KEY -- \"- + * ÷\"`\u003c/summary\u003e\u003cbr\u003e\n\nIf your value starts with a dash (`-`), then place two dashes instructing the cli that there are no more flag arguments.\n\n```sh\n$ touch .env.ci\n\n$ dotenvx set HELLO -f .env.ci -- \"- + * ÷\"\nset HELLO with encryption (.env.ci)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set KEY value --plain`\u003c/summary\u003e\u003cbr\u003e\n\nSet a plaintext key/value.\n\n```sh\n$ touch .env\n\n$ dotenvx set HELLO Dotenvx --plain\nset HELLO (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`encrypt`\u003c/summary\u003e\u003cbr\u003e\n\nEncrypt the contents of a `.env` file to an encrypted `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx encrypt\n◈ encrypted (.env) + local key (.env.keys)\n⮕  next run [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys\n⮕  next run [DOTENV_PRIVATE_KEY='122...0b8' dotenvx run -- yourcommand] to test decryption locally\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`encrypt -f`\u003c/summary\u003e\u003cbr\u003e\n\nEncrypt the contents of a specified `.env` file to an encrypted `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"HELLO=Production\" \u003e .env.production\n\n$ dotenvx encrypt -f .env.production\n◈ encrypted (.env.production) + local key (.env.keys)\n⮕  next run [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys\n⮕  next run [DOTENV_PRIVATE_KEY='bff...bc4' dotenvx run -- yourcommand] to test decryption locally\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`encrypt --no-ops`\u003c/summary\u003e\u003cbr\u003e\n\nTurn off [Dotenvx Ops](https://dotenvx.com/ops) features for encrypt.\n\n```sh\n$ dotenvx encrypt --no-ops\n◈ encrypted (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`encrypt -fk`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path to `.env.keys`. This is useful with monorepos.\n\n```sh\n$ mkdir -p apps/app1\n$ echo \"HELLO=Dotenvx\" \u003e apps/app1/.env\n\n$ dotenvx encrypt -fk .env.keys -f apps/app1/.env\n◈ encrypted (apps/app1/.env)\n```\n\nPut it to use.\n\n```sh\n$ dotenvx run -fk .env.keys -f apps/app1/.env\n```\n\nUse with a relative path.\n\n```sh\n$ cd apps/app1\n$ dotenvx run -fk ../../.env.keys -f .env\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`encrypt -k`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify the key(s) to encrypt by passing `--key`.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHELLO2=Universe\" \u003e .env\n\n$ dotenvx encrypt -k HELLO2\n◈ encrypted (.env)\n```\n\nEven specify a glob pattern.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n\n$ dotenvx encrypt -k \"HE*\"\n◈ encrypted (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`encrypt -ek`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify the key(s) to NOT encrypt by passing `--exclude-key`.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHELLO2=Universe\" \u003e .env\n\n$ dotenvx encrypt -ek HELLO\n◈ encrypted (.env)\n```\n\nEven specify a glob pattern.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n\n$ dotenvx encrypt -ek \"HO*\"\n◈ encrypted (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`encrypt --stdout`\u003c/summary\u003e\u003cbr\u003e\n\nEncrypt the contents of a `.env` file and send to stdout.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt --stdout\n#/-------------------[DOTENV_PUBLIC_KEY]--------------------/\n#/            public-key encryption for .env files          /\n#/       [how it works](https://dotenvx.com/encryption)     /\n#/----------------------------------------------------------/\nDOTENV_PUBLIC_KEY=\"034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45\"\n# .env\nHELLO=\"encrypted:BDqDBibm4wsYqMpCjTQ6BsDHmMadg9K3dAt+Z9HPMfLEIRVz50hmLXPXRuDBXaJi/LwWYEVUNiq0HISrslzQPaoyS8Lotg3gFWJTsNCdOWnqpjF2xNUX2RQiP05kAbEXM6MWVjDr\"\n```\n\nor send to a file:\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt --stdout \u003e somefile.txt\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`decrypt`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt the contents of an encrypted `.env` file to an unencrypted `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx decrypt\n◇ decrypted (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`decrypt -f`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt the contents of a specified encrypted `.env` file to an unencrypted `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"HELLO=Production\" \u003e .env.production\n\n$ dotenvx encrypt -f .env.production\n◈ encrypted (.env.production)\n$ dotenvx decrypt -f .env.production\n◇ decrypted (.env.production)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`decrypt -fk`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path to `.env.keys`. This is useful with monorepos.\n\n```sh\n$ mkdir -p apps/app1\n$ echo \"HELLO=Dotenvx\" \u003e apps/app1/.env\n\n$ dotenvx encrypt -fk .env.keys -f apps/app1/.env\n◈ encrypted (apps/app1/.env)\n$ dotenvx decrypt -fk .env.keys -f apps/app1/.env\n◇ decrypted (apps/app1/.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`decrypt -k`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt the contents of a specified key inside an encrypted `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx decrypt -k HELLO\n◇ decrypted (.env)\n```\n\nEven specify a glob pattern.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx decrypt -k \"HE*\"\n◇ decrypted (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`decrypt -ek`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt the contents inside an encrypted `.env` file except for an excluded key.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx decrypt -ek HOLA\n◇ decrypted (.env)\n```\n\nEven specify a glob pattern.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx decrypt -ek \"HO*\"\n◇ decrypted (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`decrypt --stdout`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt the contents of an encrypted `.env` file and send to stdout.\n\n```sh\n$ dotenvx decrypt --stdout\n#/-------------------[DOTENV_PUBLIC_KEY]--------------------/\n#/            public-key encryption for .env files          /\n#/       [how it works](https://dotenvx.com/encryption)     /\n#/----------------------------------------------------------/\nDOTENV_PUBLIC_KEY=\"034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45\"\n# .env\nHELLO=\"Dotenvx\"\n```\n\nor send to a file:\n\n```sh\n$ dotenvx decrypt --stdout \u003e somefile.txt\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`keypair`\u003c/summary\u003e\u003cbr\u003e\n\nPrint public/private keys for `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt\n\n$ dotenvx keypair\n{\"DOTENV_PUBLIC_KEY\":\"\u003cpublicKey\u003e\",\"DOTENV_PRIVATE_KEY\":\"\u003cprivateKey\u003e\"}\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`keypair -f`\u003c/summary\u003e\u003cbr\u003e\n\nPrint public/private keys for `.env.production` file.\n\n```sh\n$ echo \"HELLO=Production\" \u003e .env.production\n$ dotenvx encrypt -f .env.production\n\n$ dotenvx keypair -f .env.production\n{\"DOTENV_PUBLIC_KEY_PRODUCTION\":\"\u003cpublicKey\u003e\",\"DOTENV_PRIVATE_KEY_PRODUCTION\":\"\u003cprivateKey\u003e\"}\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`keypair -fk`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path to `.env.keys`. This is useful for printing public/private keys for monorepos.\n\n```sh\n$ mkdir -p apps/app1\n$ echo \"HELLO=Dotenvx\" \u003e apps/app1/.env\n$ dotenvx encrypt -fk .env.keys -f apps/app1/.env\n\n$ dotenvx keypair -fk .env.keys -f apps/app1/.env\n{\"DOTENV_PUBLIC_KEY\":\"\u003cpublicKey\u003e\",\"DOTENV_PRIVATE_KEY\":\"\u003cprivateKey\u003e\"}\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`keypair DOTENV_PRIVATE_KEY`\u003c/summary\u003e\u003cbr\u003e\n\nPrint specific keypair for `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt\n\n$ dotenvx keypair DOTENV_PRIVATE_KEY\n\u003cprivateKey\u003e\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`keypair --format shell`\u003c/summary\u003e\u003cbr\u003e\n\nPrint a shell formatted response of public/private keys.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenx encrypt\n\n$ dotenvx keypair --format shell\nDOTENV_PUBLIC_KEY=\u003cpublicKey\u003e DOTENV_PRIVATE_KEY=\u003cprivateKey\u003e\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ls`\u003c/summary\u003e\u003cbr\u003e\n\nPrint all `.env` files in a tree structure.\n\n```sh\n$ touch .env\n$ touch .env.production\n$ mkdir -p apps/backend\n$ touch apps/backend/.env\n\n$ dotenvx ls\n├─ .env.production\n├─ .env\n└─ apps\n   └─ backend\n      └─ .env\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ls directory`\u003c/summary\u003e\u003cbr\u003e\n\nPrint all `.env` files inside a specified path to a directory.\n\n```sh\n$ touch .env\n$ touch .env.production\n$ mkdir -p apps/backend\n$ touch apps/backend/.env\n\n$ dotenvx ls apps/backend\n└─ .env\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ls -f`\u003c/summary\u003e\u003cbr\u003e\n\nGlob `.env` filenames matching a wildcard.\n\n```sh\n$ touch .env\n$ touch .env.production\n$ mkdir -p apps/backend\n$ touch apps/backend/.env\n$ touch apps/backend/.env.prod\n\n$ dotenvx ls -f **/.env.prod*\n├─ .env.production\n└─ apps\n   └─ backend\n      └─ .env.prod\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ls -ef`\u003c/summary\u003e\u003cbr\u003e\n\nGlob `.env` filenames excluding a wildcard.\n\n```sh\n$ touch .env\n$ touch .env.production\n$ mkdir -p apps/backend\n$ touch apps/backend/.env\n$ touch apps/backend/.env.prod\n\n$ dotenvx ls -ef '**/.env.prod*'\n├─ .env\n└─ apps\n   └─ backend\n      └─ .env\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`rotate`\u003c/summary\u003e\u003cbr\u003e\n\nRotate public/private keys for `.env` file and re-encrypt all encrypted values.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx rotate\n⟳ rotated (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`rotate -f`\u003c/summary\u003e\u003cbr\u003e\n\nRotate public/private keys for a specified encrypted `.env` file and re-encrypt all encrypted values.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"HELLO=Production\" \u003e .env.production\n\n$ dotenvx encrypt -f .env.production\n◈ encrypted (.env.production)\n$ dotenvx rotate -f .env.production\n⟳ rotated (.env.production)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`rotate -fk`\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path to `.env.keys`. This is useful with monorepos.\n\n```sh\n$ mkdir -p apps/app1\n$ echo \"HELLO=Dotenvx\" \u003e apps/app1/.env\n\n$ dotenvx encrypt -fk .env.keys -f apps/app1/.env\n◈ encrypted (apps/app1/.env)\n$ dotenvx rotate -fk .env.keys -f apps/app1/.env\n⟳ rotated (apps/app1/.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`rotate -k`\u003c/summary\u003e\u003cbr\u003e\n\nRotate the contents of a specified key inside an encrypted `.env` file.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx rotate -k HELLO\n⟳ rotated (.env)\n```\n\nEven specify a glob pattern.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx rotate -k \"HE*\"\n⟳ rotated (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`rotate -ek`\u003c/summary\u003e\u003cbr\u003e\n\nRotate the encrypted contents inside an encrypted `.env` file except for an excluded key.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx rotate -ek HOLA\n⟳ rotated (.env)\n```\n\nEven specify a glob pattern.\n\n```sh\n$ echo \"HELLO=Dotenvx\\nHOLA=Mundo\" \u003e .env\n$ dotenvx encrypt\n◈ encrypted (.env)\n$ dotenvx rotate -ek \"HO*\"\n⟳ rotated (.env)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`rotate --stdout`\u003c/summary\u003e\u003cbr\u003e\n\nRotate the contents of an encrypted `.env` file and send to stdout.\n\n```sh\n$ dotenvx rotate --stdout\n#/-------------------[DOTENV_PUBLIC_KEY]--------------------/\n#/            public-key encryption for .env files          /\n#/       [how it works](https://dotenvx.com/encryption)     /\n#/----------------------------------------------------------/\nDOTENV_PUBLIC_KEY=\"034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45\"\n# .env\nHELLO=\"encrypted:12345\"\n```\n\nor send to a file:\n\n```sh\n$ dotenvx rotate --stdout \u003e somefile.txt\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`help`\u003c/summary\u003e\u003cbr\u003e\n\nOutput help for `dotenvx`.\n\n```sh\n$ dotenvx help\nUsage: dotenvx run -- yourcommand\n\na secure dotenv–from the creator of `dotenv`\n\nOptions:\n  -l, --log-level \u003clevel\u003e      set log level (default: \"info\")\n  -q, --quiet                  sets log level to error\n  -v, --verbose                sets log level to verbose\n  -d, --debug                  sets log level to debug\n  -V, --version                output the version number\n  -h, --help                   display help for command\n\nCommands:\n  run                inject env at runtime [dotenvx run -- yourcommand]\n  get [KEY]          return a single environment variable\n  set \u003cKEY\u003e \u003cvalue\u003e  set a single environment variable\n  encrypt            convert .env file(s) to encrypted .env file(s)\n  decrypt            convert encrypted .env file(s) to plain .env file(s)\n  keypair [KEY]      print public/private keys for .env file(s)\n  ls [directory]     print all .env files in a tree structure\n \nAdvanced: \n  pro                          🏆 pro\n  ext                          🔌 extensions\n```\n\nYou can get more detailed help per command with `dotenvx help COMMAND`.\n\n```sh\n$ dotenvx help run\nUsage: @dotenvx/dotenvx run [options]\n\ninject env at runtime [dotenvx run -- yourcommand]\n\nOptions:\n  -e, --env \u003cstrings...\u003e            environment variable(s) set as string (example: \"HELLO=Dotenvx\") (default: [])\n  -f, --env-file \u003cpaths...\u003e         path(s) to your env file(s) (default: [])\n  -fv, --env-vault-file \u003cpaths...\u003e  path(s) to your .env.vault file(s) (default: [])\n  -o, --overload                    override existing env variables\n  --convention \u003cname\u003e               load a .env convention (available conventions: ['nextjs'])\n  -h, --help                        display help for command\n\nExamples:\n\n  $ dotenvx run -- npm run dev\n  $ dotenvx run -- flask --app index run\n  $ dotenvx run -- php artisan serve\n  $ dotenvx run -- bin/rails s\n\nTry it:\n\n  $ echo \"HELLO=Dotenvx\" \u003e .env\n  $ echo \"console.log('Hello ' + process.env.HELLO)\" \u003e index.js\n\n  $ dotenvx run -- node index.js\n  [dotenvx@1.X.X] injecting env (1) from .env\n  Hello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`--version`\u003c/summary\u003e\u003cbr\u003e\n\nCheck current version of `dotenvx`.\n\n```sh\n$ dotenvx --version\nX.X.X\n```\n\n\u003c/details\u003e\n\n### Extensions 🔌\n\nCLI extensions.\n\n\u003cdetails\u003e\u003csummary\u003e`ext genexample`\u003c/summary\u003e\u003cbr\u003e\n\nIn one command, generate a `.env.example` file from your current `.env` file contents.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n\n$ dotenvx ext genexample\n▣ generated (.env.example)\n```\n\n```ini\n# .env.example\nHELLO=\"\"\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext genexample -f`\u003c/summary\u003e\u003cbr\u003e\n\nPass multiple `.env` files to generate your `.env.example` file from the combination of their contents.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ echo \"DB_HOST=example.com\" \u003e .env.production\n\n$ dotenvx ext genexample -f .env -f .env.production\n▣ generated (.env.example)\n```\n\n```ini\n# .env.example\nHELLO=\"\"\nDB_HOST=\"\"\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext genexample directory`\u003c/summary\u003e\u003cbr\u003e\n\nGenerate a `.env.example` file inside the specified directory. Useful for monorepos.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ mkdir -p apps/backend\n$ echo \"HELLO=Backend\" \u003e apps/backend/.env\n\n$ dotenvx ext genexample apps/backend\n▣ generated (.env.example)\n```\n\n```ini\n# apps/backend/.env.example\nHELLO=\"\"\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext gitignore`\u003c/summary\u003e\u003cbr\u003e\n\nGitignore your `.env` files.\n\n```sh\n$ dotenvx ext gitignore\n▣ ignored .env* (.gitignore)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext gitignore --pattern`\u003c/summary\u003e\u003cbr\u003e\n\nGitignore specific pattern(s) of `.env` files.\n\n```sh\n$ dotenvx ext gitignore --pattern .env.keys\n▣ ignored .env.keys (.gitignore)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext precommit`\u003c/summary\u003e\u003cbr\u003e\n\nPrevent `.env` files from being committed to code.\n\n```sh\n$ dotenvx ext precommit\n▣ .env files (1) protected (encrypted or gitignored)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext precommit --install`\u003c/summary\u003e\u003cbr\u003e\n\nInstall a shell script to `.git/hooks/pre-commit` to prevent accidentally committing any `.env` files to source control.\n\n```sh\n$ dotenvx ext precommit --install\n▣ dotenvx ext precommit installed [.git/hooks/pre-commit]\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext precommit directory`\u003c/summary\u003e\u003cbr\u003e\n\nPrevent `.env` files from being committed to code inside a specified path to a directory.\n\n```sh\n$ echo \"HELLO=Dotenvx\" \u003e .env\n$ mkdir -p apps/backend\n$ echo \"HELLO=Backend\" \u003e apps/backend/.env\n\n$ dotenvx ext precommit apps/backend\n▣ apps/backend/.env not protected (encrypted or gitignored)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext prebuild`\u003c/summary\u003e\u003cbr\u003e\n\nPrevent `.env` files from being built into your docker containers.\n\nAdd it to your `Dockerfile`.\n\n```Containerfile\n# Install via script\nRUN curl -fsS https://dotenvx.sh | sh\n\n# Or copy binary from official image\nCOPY --from=dotenv/dotenvx:latest /usr/local/bin/dotenvx /bin/local/bin\n\n# ... orther container commands\n\nRUN dotenvx ext prebuild\nCMD [\"/usr/local/bin/dotenvx\", \"run\", \"--\", \"node\", \"index.js\"]\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext prebuild directory`\u003c/summary\u003e\u003cbr\u003e\n\nPrevent `.env` files from being built into your docker containers inside a specified path to a directory.\n\nAdd it to your `Dockerfile`.\n\n```Containerfile\n# Install via script\nRUN curl -fsS https://dotenvx.sh | sh\n\n# Or copy binary from official image\nCOPY --from=dotenv/dotenvx:latest /usr/local/bin/dotenvx /bin/local/bin\n\n# ... orther container commands\n\nRUN dotenvx ext prebuild apps/backend\nCMD [\"/usr/local/bin/dotenvx\", \"run\", \"--\", \"node\", \"apps/backend/index.js\"]\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`ext scan`\u003c/summary\u003e\u003cbr\u003e\n\nScan for leaked secrets.\n\n```sh\n$ dotenvx ext scan\n100 commits scanned.\nno leaks found\n```\n\nUses [gitleaks](https://gitleaks.io) under the hood.\n\n\u003c/details\u003e\n\n### Library 📦\n\nUse dotenvx directly in code.\n\n\u003cdetails\u003e\u003csummary\u003e`config()`\u003c/summary\u003e\u003cbr\u003e\n\nUse directly in node.js code.\n\n```ini\n# .env\nHELLO=\"Dotenvx\"\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config()\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n```sh\n$ node index.js\n[dotenvx@1.X.X] injecting env (1) from .env\nHello Dotenvx\n```\n\nIt defaults to looking for a `.env` file.\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(path: ['.env.local', '.env'])` - multiple files\u003c/summary\u003e\u003cbr\u003e\n\nSpecify path(s) to multiple .env files.\n\n```ini\n# .env.local\nHELLO=\"Me\"\n```\n\n```ini\n# .env\nHELLO=\"Dotenvx\"\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({path: ['.env.local', '.env']})\n\n// esm\n// import dotenvx from \"@dotenvx/dotenvx\";\n// dotenvx.config({path: ['.env.local', '.env']});\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n```sh\n$ node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.local, .env\nHello Me\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(overload: true)` - overload\u003c/summary\u003e\u003cbr\u003e\n\nUse `overload` to overwrite the prior set value.\n\n```ini\n# .env.local\nHELLO=\"Me\"\n```\n\n```ini\n# .env\nHELLO=\"Dotenvx\"\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({path: ['.env.local', '.env'], overload: true})\n\n// esm\n// import dotenvx from \"@dotenvx/dotenvx\";\n// dotenvx.config({path: ['.env.local', '.env'], overload: true});\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n```sh\n$ node index.js\n[dotenvx@1.X.X] injecting env (1) from .env.local, .env\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(quiet: true)` - quiet\u003c/summary\u003e\u003cbr\u003e\n\nSuppress all output (except errors).\n\n```ini\n# .env\nHELLO=\"Dotenvx\"\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], quiet: true})\n\n// esm\n// import dotenvx from \"@dotenvx/dotenvx\";\n// dotenvx.config({path: ['.env.missing', '.env'], quiet: true});\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n```sh\n$ node index.js\nError: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(strict: true)` - strict\u003c/summary\u003e\u003cbr\u003e\n\nExit with code `1` if any errors are encountered - like a missing .env file or decryption failure.\n\n```ini\n# .env\nHELLO=\"Dotenvx\"\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], strict: true})\n\n// esm\n// import dotenvx from \"@dotenvx/dotenvx\";\n// dotenvx.config({path: ['.env.missing', '.env'], strict: true});\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n```sh\n$ node index.js\nError: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(ignore:)` - ignore\u003c/summary\u003e\u003cbr\u003e\n\nUse `ignore` to suppress specific errors like `MISSING_ENV_FILE`.\n\n```ini\n# .env\nHELLO=\"Dotenvx\"\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({path: ['.env.missing', '.env'], ignore: ['MISSING_ENV_FILE']})\n\n// esm\n// import dotenvx from \"@dotenvx/dotenvx\";\n// dotenvx.config({path: ['.env.missing', '.env'], ignore: ['MISSING_ENV_FILE']});\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n```sh\n$ node index.js\n[dotenvx@1.X.X] injecting env (1) from .env\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(envKeysFile:)` - envKeysFile\u003c/summary\u003e\u003cbr\u003e\n\nUse `envKeysFile` to customize the path to your `.env.keys` file. This is useful with monorepos.\n\n```ini\n# .env\nHELLO=\"Dotenvx\"\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({path: ['.env'], envKeysFile: '../../.env.keys'})\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(convention:)` - convention\u003c/summary\u003e\u003cbr\u003e\n\nSet a convention when using `dotenvx.config()`. This allows you to use the same file loading order as the CLI without needing to specify each file individually.\n\n```sh\n# Setup environment files\n$ echo \"HELLO=development local\" \u003e .env.development.local\n$ echo \"HELLO=local\" \u003e .env.local\n$ echo \"HELLO=development\" \u003e .env.development\n$ echo \"HELLO=env\" \u003e .env\n```\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({ convention: 'nextjs' })\n\nconsole.log(`Hello ${process.env.HELLO}`)\n```\n\n```sh\n$ NODE_ENV=development node index.js\n[dotenvx@1.28.0] injecting env (1) from .env.development.local, .env.local, .env.development, .env\nHello development local\n```\n\nThis is equivalent to using `--convention=nextjs` with the CLI:\n\n```sh\n$ dotenvx run --convention=nextjs -- node index.js\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`config(noOps:)` - noOps\u003c/summary\u003e\u003cbr\u003e\n\nTurn off [Dotenvx Ops](https://dotenvx.com/ops) features.\n\n```js\n// index.js\nrequire('@dotenvx/dotenvx').config({noOps: true})\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`parse(src)`\u003c/summary\u003e\u003cbr\u003e\n\nParse a `.env` string directly in node.js code.\n\n```js\n// index.js\nconst dotenvx = require('@dotenvx/dotenvx')\nconst src = 'HELLO=Dotenvx'\nconst parsed = dotenvx.parse(src)\nconsole.log(`Hello ${parsed.HELLO}`)\n```\n\n```sh\n$ node index.js\nHello Dotenvx\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`parse(src, {processEnv:})`\u003c/summary\u003e\u003cbr\u003e\n\nSometimes, you want to run `parse` without it accessing `process.env`. (You can pass a fake processEnv this way as well - sometimes useful.)\n\n```js\n// index.js\nconst dotenvx = require('@dotenvx/dotenvx')\nconst src = 'USER=Me'\nconst parsed = dotenvx.parse(src, { processEnv: {} })\nconsole.log(`Hello ${parsed.USER}`)\n```\n\n```sh\n$ node index.js\nHello Me\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`parse(src, {privateKey:})`\u003c/summary\u003e\u003cbr\u003e\n\nDecrypt an encrypted `.env` string with `privateKey`.\n\n```js\n// index.js\nconst dotenvx = require('@dotenvx/dotenvx')\nconst src = 'HELLO=\"encrypted:BE9Y7LKANx77X1pv1HnEoil93fPa5c9rpL/1ps48uaRT9zM8VR6mHx9yM+HktKdsPGIZELuZ7rr2mn1gScsmWitppAgE/1lVprNYBCqiYeaTcKXjDUXU5LfsEsflnAsDhT/kWG1l\"'\nconst parsed = dotenvx.parse(src, { privateKey: 'a4547dcd9d3429615a3649bb79e87edb62ee6a74b007075e9141ae44f5fb412c' })\nconsole.log(`Hello ${parsed.HELLO}`)\n```\n\n```sh\n$ node index.js\nHello Dotenvx\n```\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set(KEY, value)`\u003c/summary\u003e\u003cbr\u003e\n\nProgrammatically set an environment variable. \n\n```js\n// index.js\nconst dotenvx = require('@dotenvx/dotenvx')\ndotenvx.set('HELLO', 'Dotenvx', { path: '.env' })\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`set(KEY, value, {plain:})`\u003c/summary\u003e\u003cbr\u003e\n\nProgrammatically set a plaintext environment variable.\n\n```js\n// index.js\nconst dotenvx = require('@dotenvx/dotenvx')\ndotenvx.set('HELLO', 'Dotenvx', { plain: true })\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e`get(KEY)` - \u003ci\u003eDecryption at Access\u003c/i\u003e\u003c/summary\u003e\u003cbr\u003e\n\nProgrammatically get an environment variable at access/runtime.\n\n```js\n// index.js\nconst dotenvx = require('@dotenvx/dotenvx')\nconst decryptedValue = dotenvx.get('HELLO')\nconsole.log(decryptedValue)\n```\n\nThis is known as *Decryption at Access* and is written about in [the whitepaper](https://dotenvx.com/dotenvx.pdf).\n\n\u003c/details\u003e\n\n\u0026nbsp;\n\n## Ops ⛨\n\n[![dotenvx-ops](https://dotenvx.com/dotenvx-ops-banner.png?v=6)](https://dotenvx.com/ops)\n\n```\n⛨ ARMORED KEYS: Harden your private keys.\n⮕ install [curl -sfS https://dotenvx.sh/ops | sh]\n⮕ then run [dotenvx-ops login]\n```\n\n[Learn more](https://dotenvx.com/ops)\n\n\u0026nbsp;\n\n## Whitepaper\n\n\u003e **Dotenvx: Reducing Secrets Risk with Cryptographic Separation**\n\u003e\n\u003e 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.\n\u003e\n\u003e ...\n\u003e\n\u003e [Read the whitepaper](https://dotenvx.com/dotenvx.pdf)\n\n\u0026nbsp;\n\n## Guides\n\n\u003e Go deeper with `dotenvx` – detailed framework and platform guides.\n\u003e\n\n* [Languages](https://dotenvx.com/docs#languages)\n  * [Node.js](https://dotenvx.com/docs/languages/nodejs)\n  * [Python](https://dotenvx.com/docs/languages/python)\n  * [Ruby](https://dotenvx.com/docs/languages/ruby)\n  * [Go](https://dotenvx.com/docs/languages/go)\n  * [PHP](https://dotenvx.com/docs/languages/php)\n  * [Rust](https://dotenvx.com/docs/languages/rust)\n* [Frameworks](https://dotenvx.com/docs#frameworks)\n  * [Astro](https://dotenvx.com/docs/frameworks/astro)\n  * [Express](https://dotenvx.com/docs/frameworks/express)\n  * [Next](https://dotenvx.com/docs/frameworks/next)\n  * [Remix](https://dotenvx.com/docs/frameworks/remix)\n  * [Flask](https://dotenvx.com/docs/frameworks/flask)\n  * [Sinatra](https://dotenvx.com/docs/frameworks/sinatra)\n  * [Rocket](https://dotenvx.com/docs/frameworks/rocket)\n* [Platforms](https://dotenvx.com/docs#platforms)\n  * [Digital Ocean](https://dotenvx.com/docs/platforms/digital-ocean)\n  * [Docker](https://dotenvx.com/docs/platforms/docker)\n  * [Fly](https://dotenvx.com/docs/platforms/fly)\n  * [Heroku](https://dotenvx.com/docs/platforms/heroku)\n  * [Netlify](https://dotenvx.com/docs/platforms/netlify)\n  * [Vercel](https://dotenvx.com/docs/platforms/vercel)\n  * [Railway](https://dotenvx.com/docs/platforms/railway)\n  * [Render](https://dotenvx.com/docs/platforms/render)\n* [CI/CDs](https://dotenvx.com/docs#cis)\n  * [GitHub Actions](https://dotenvx.com/docs/cis/github-actions)\n* [Background Jobs](https://dotenvx.com/docs#background-jobs)\n  * [Trigger.dev](https://dotenvx.com/docs/background-jobs/triggerdotdev)\n* [Package Managers](https://dotenvx.com/docs#package-managers)\n  * [NPM](https://dotenvx.com/docs/package-managers/npm)\n  * [PNPM](https://dotenvx.com/docs/package-managers/pnpm)\n* [Process Managers](https://dotenvx.com/docs#process-managers)\n  * [PM2](https://dotenvx.com/docs/process-managers/pm2)\n* [Monorepos](https://dotenvx.com/docs#monorepos)\n  * [Nx](https://dotenvx.com/docs/monorepos/nx)\n  * [Turborepo](https://dotenvx.com/docs/monorepos/turborepo)\n* [Concepts](https://dotenvx.com/docs#concepts)\n  * [.env](https://dotenvx.com/docs/env-file)\n  * [.env.keys](https://dotenvx.com/docs/env-keys-file)\n\n\u0026nbsp;\n\n## FAQ\n\n#### How does encryption work?\n\nDotenvx uses Elliptic Curve Integrated Encryption Scheme (ECIES) to encrypt each secret with a unique ephemeral key, while ensuring it can be decrypted using a long-term private key.\n\nWhen you initialize encryption, a DOTENV_PUBLIC_KEY (encryption key) and DOTENV_PRIVATE_KEY (decryption key) are generated. The DOTENV_PUBLIC_KEY is used to encrypt secrets, and the DOTENV_PRIVATE_KEY is securely stored in your cloud secrets manager or .env.keys file.\n\nYour encrypted .env file is then safely committed to code. Even if the file is exposed, secrets remain protected since decryption requires the separate DOTENV_PRIVATE_KEY, which is never stored alongside it. Read [the whitepaper](https://dotenvx.com/dotenvx.pdf?v=README) for more details.\n\n#### Is it safe to commit an encrypted .env file to code?\n\nYes. Dotenvx encrypts secrets using AES-256 with ephemeral keys, ensuring that even if the encrypted .env file is exposed, its contents remain secure. The encryption keys themselves are protected using Secp256k1 elliptic curve cryptography, which is widely used for secure key exchange in technologies like Bitcoin.\n\nThis means that every secret in the .env file is encrypted with a unique AES-256 key, and that key is further encrypted using a public key (Secp256k1). Even if an attacker obtains the encrypted .env file, they would still need the corresponding private key—stored separately in a secrets manager—to decrypt anything.\n\nBreaking this encryption would require brute-forcing both AES-256 and elliptic curve cryptography, which is computationally infeasible with current technology. Read [the whitepaper](https://dotenvx.com/dotenvx.pdf?v=README) for more details.\n\n#### Why am I getting the error `node: .env: not found`?\n\nYou 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`.\n\nThis fix is easy. Replace `--env-file` with `-f`.\n\n```bash\n# from this:\n./node_modules/.bin/dotenvx run --env-file .env -- yourcommand\n# to this:\n./node_modules/.bin/dotenvx run -f .env -- yourcommand\n```\n\n[more context](https://github.com/dotenvx/dotenvx/issues/131)\n\n\u0026nbsp;\n\n## Contributing\n\nYou can fork this repo and create [pull requests](https://github.com/dotenvx/dotenvx/pulls) or if you have questions or feedback:\n\n* [github.com/dotenvx/dotenvx](https://github.com/dotenvx/dotenvx/issues) - bugs and discussions\n* [@dotenvx 𝕏](https://x.com/dotenvx) (DMs are open)\n","funding_links":[],"categories":["JavaScript","others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotenvx%2Fdotenvx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdotenvx%2Fdotenvx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotenvx%2Fdotenvx/lists"}