@dotenvx/dotenvx 2.17.4 → 2.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,7 +2,17 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- [Unreleased](https://github.com/dotenvx/dotenvx/compare/v2.17.4...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx/compare/v2.18.1...main)
6
+
7
+ ## [2.18.1](https://github.com/dotenvx/dotenvx/compare/v2.18.0...v2.18.1) (2026-07-26)
8
+
9
+ * Patch injected message when preset `encrypted:` value ([#927](https://github.com/dotenvx/dotenvx/issues/927))
10
+
11
+ ## [2.18.0](https://github.com/dotenvx/dotenvx/compare/v2.17.4...v2.18.0) (2026-07-25)
12
+
13
+ ### Added
14
+
15
+ * Make authenticated API calls to the Dotenvx Armor API with `dotenvx curl`. Allows you to control your Dotenvx Armor account directly from your agent inside Codex, Claude, etc. ([#923](https://github.com/dotenvx/dotenvx/pull/923))
6
16
 
7
17
  ## [2.17.4](https://github.com/dotenvx/dotenvx/compare/v2.17.3...v2.17.4) (2026-07-24)
8
18
 
package/README.md CHANGED
@@ -3497,25 +3497,68 @@ Set `mask: 0` to fully mask values.
3497
3497
 
3498
3498
   
3499
3499
 
3500
- ### Settings ⚙️
3500
+ ### More
3501
3501
 
3502
- There are global settings available that can be configured as environment variables.
3502
+ <details><summary>Settings ⚙️</summary><br>
3503
3503
 
3504
- <details><summary>Environment variables</summary><br>
3504
+ There are global settings available that can be configured as environment variables.
3505
3505
 
3506
3506
  ```ini
3507
- # dotenvx native settings
3507
+ # config
3508
3508
  DOTENV_CONFIG_CONVENTION= # set to a default convention like 'nextjs' or 'flow'
3509
3509
  DOTENV_CONFIG_IGNORE= # MISSING_ENV_FILE,OTHER
3510
3510
  DOTENV_CONFIG_QUIET= # set to "true" to default to --quiet
3511
+
3512
+ # armor
3513
+ DOTENVX_ARMOR_TOKEN= # for api calls
3511
3514
  DOTENVX_NO_ARMOR= # set to "true" to turn off Armor support
3515
+
3516
+ # 1password
3512
3517
  DOTENVX_NO_1PASSWORD= # set to "true" to turn off 1Password support
3513
- DOTENVX_NO_BITWARDEN= # set to "true" to turn off Bitwarden support
3514
3518
 
3515
- # other machine settings respected by dotenvx
3519
+ # bitwarden
3520
+ DOTENVX_NO_BITWARDEN= # set to "true" to turn off Bitwarden support
3516
3521
  BW_SESSION= # set to bitwarden session token to bypass password prompt
3517
3522
  ```
3518
3523
 
3524
+ </details>
3525
+ <details><summary>Error Codes 🚨</summary><br>
3526
+
3527
+ Dotenvx errors begin with a stable code in square brackets like `[MISSING_ENV_FILE]`.
3528
+
3529
+ ```ini
3530
+ # error codes
3531
+ 1PASSWORD_FAILED= # a value could not be resolved with the 1Password CLI
3532
+ ACCESS_APPROVAL_TIMEOUT= # an Armor access-approval request timed out
3533
+ BITWARDEN_FAILED= # a value could not be resolved with the Bitwarden CLI
3534
+ COMMAND_EXITED_WITH_CODE= # the command run by dotenvx exited with a non-zero status
3535
+ COMMAND_SUBSTITUTION_FAILED= # a $(command) expression in an environment value could not be evaluated
3536
+ DECRYPTION_FAILED= # an encrypted value could not be decrypted
3537
+ FILE_NOT_WRITABLE= # dotenvx could not write to the target file
3538
+ INVALID_COLOR= # the requested terminal color is invalid
3539
+ INVALID_CONVENTION= # the requested environment-file convention is invalid
3540
+ INVALID_PASSPHRASE= # a locked private key could not be unlocked with the supplied passphrase
3541
+ INVALID_PRIVATE_KEY= # a private key is malformed or otherwise invalid
3542
+ INVALID_PUBLIC_KEY= # a public key is malformed or otherwise invalid
3543
+ MALFORMED_ENCRYPTED_DATA= # the encrypted value is malformed
3544
+ MISPAIRED_PRIVATE_KEY= # a private key does not match the existing public key
3545
+ MISSING_DIRECTORY= # the requested directory does not exist
3546
+ MISSING_ENV_EXAMPLE= # the required .env.example file does not exist
3547
+ MISSING_ENV_FILE= # a requested environment file does not exist
3548
+ MISSING_ENV_FILES= # no .env* files were found
3549
+ MISSING_ENV_KEYS_FILE= # the requested .env.keys file does not exist
3550
+ MISSING_KEY= # a requested environment key does not exist
3551
+ MISSING_LOG_LEVEL= # the requested log level is not supported
3552
+ MISSING_PRIVATE_KEY= # the private key required to decrypt a value is missing
3553
+ MISSING_PUBLIC_KEY= # the public key required to encrypt a value is missing
3554
+ MISSING_REQUIRED= # validation detail for which required variables are missing; surfaced by VALIDATION_FAILED
3555
+ MISSING_VALUE= # no value was supplied for a key
3556
+ NOT_FOUND= # a private key was not found in the native secret store
3557
+ PRECOMMIT_HOOK_MODIFY_FAILED= # dotenvx could not update the pre-commit hook
3558
+ VALIDATION_FAILED= # one or more required variables declared by .env.example are missing
3559
+ WRONG_PRIVATE_KEY= # the supplied private key cannot decrypt the value
3560
+ ```
3561
+
3519
3562
  </details>
3520
3563
 
3521
3564
  &nbsp;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.17.4",
2
+ "version": "2.18.1",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a secure dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "funding": "https://dotenvx.com",
54
54
  "dependencies": {
55
- "@dotenvx/primitives": "^2.1.0",
55
+ "@dotenvx/primitives": "^2.1.1",
56
56
  "@dotenvx/tooling": "^1.0.3",
57
57
  "yocto-spinner": "^1.2.1"
58
58
  },
@@ -62,9 +62,13 @@
62
62
  "esbuild": "^0.28.1",
63
63
  "proxyquire": "^2.1.3",
64
64
  "sinon": "^14.0.1",
65
- "standard": "^17.1.0",
65
+ "standard": "^17.1.2",
66
66
  "standard-version": "^9.5.0",
67
- "tap": "^21.0.1"
67
+ "tap": "^21.7.4"
68
+ },
69
+ "overrides": {
70
+ "brace-expansion": "^5.0.8",
71
+ "minimatch": "^10.2.5"
68
72
  },
69
73
  "publishConfig": {
70
74
  "access": "public",
@@ -1,6 +1,6 @@
1
1
  const { Command } = require('@dotenvx/tooling')
2
2
 
3
- const examples = require('./../examples')
3
+ const help = require('./../help')
4
4
  const executeExtension = require('../../lib/helpers/executeExtension')
5
5
  const removeDynamicHelpSection = require('../../lib/helpers/removeDynamicHelpSection')
6
6
 
@@ -41,7 +41,7 @@ ext.command('genexample')
41
41
  // dotenvx ext gitignore
42
42
  ext.command('gitignore')
43
43
  .description('append to .gitignore')
44
- .addHelpText('after', examples.gitignore)
44
+ .addHelpText('after', help.gitignore)
45
45
  .option('--pattern <patterns...>', 'pattern(s) to gitignore', ['.env*'])
46
46
  .action(function (...args) {
47
47
  return require('./../actions/ext/gitignore').apply(this, args)
@@ -50,7 +50,7 @@ ext.command('gitignore')
50
50
  // dotenvx ext prebuild
51
51
  ext.command('prebuild')
52
52
  .description('prevent including .env files in docker')
53
- .addHelpText('after', examples.prebuild)
53
+ .addHelpText('after', help.prebuild)
54
54
  .argument('[directory]', 'directory to prevent including .env files from', '.')
55
55
  .action(function (...args) {
56
56
  return require('./../actions/ext/prebuild').apply(this, args)
@@ -59,7 +59,7 @@ ext.command('prebuild')
59
59
  // dotenvx ext precommit
60
60
  ext.command('precommit')
61
61
  .description('prevent committing .env files to code')
62
- .addHelpText('after', examples.precommit)
62
+ .addHelpText('after', help.precommit)
63
63
  .argument('[directory]', 'directory to prevent committing .env files from', '.')
64
64
  .option('-i, --install', 'install to .git/hooks/pre-commit')
65
65
  .action(function (...args) {
@@ -5,7 +5,7 @@ const { Command } = require('@dotenvx/tooling')
5
5
  const program = new Command()
6
6
 
7
7
  const { setLogLevel } = require('../shared/logger')
8
- const examples = require('./examples')
8
+ const help = require('./help')
9
9
  const packageJson = require('./../lib/helpers/packageJson')
10
10
  const executeDynamic = require('./../lib/helpers/executeDynamic')
11
11
  const removeDynamicHelpSection = require('./../lib/helpers/removeDynamicHelpSection')
@@ -60,7 +60,7 @@ program
60
60
  // dotenvx run -- node index.js
61
61
  program.command('run')
62
62
  .description('inject env at runtime [dotenvx run -- yourcommand]')
63
- .addHelpText('after', examples.run)
63
+ .addHelpText('after', help.run)
64
64
  .option('-e, --env <strings...>', 'environment variable(s) set as string (example: "HELLO=World")', collectEnvs('env'), [])
65
65
  .option('-f, --env-file <path>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
66
66
  .option('-fk, --env-keys-file <path>', 'path(s) to your .env.keys file(s) (default: same path as your env file)', collectEnvKeys)
@@ -113,7 +113,7 @@ program.command('get')
113
113
  program.command('set')
114
114
  .usage('<KEY> [value] [options]')
115
115
  .description('encrypt a single environment variable')
116
- .addHelpText('after', examples.set)
116
+ .addHelpText('after', help.set)
117
117
  .allowUnknownOption()
118
118
  .argument('KEY', 'KEY')
119
119
  .argument('[value]', 'value')
@@ -211,7 +211,7 @@ program.command('validate')
211
211
  // dotenvx gitignore
212
212
  program.command('gitignore')
213
213
  .description('append to .gitignore')
214
- .addHelpText('after', examples.gitignore)
214
+ .addHelpText('after', help.gitignore)
215
215
  .option('--pattern <patterns...>', 'pattern(s) to gitignore', ['.env*'])
216
216
  .action(function (...args) {
217
217
  return require('./actions/ext/gitignore').apply(this, args)
@@ -229,7 +229,7 @@ program.command('genexample')
229
229
  // dotenvx precommit
230
230
  program.command('precommit')
231
231
  .description('prevent committing .env files to code')
232
- .addHelpText('after', examples.precommit)
232
+ .addHelpText('after', help.precommit)
233
233
  .argument('[directory]', 'directory to prevent committing .env files from', '.')
234
234
  .option('-i, --install', 'install to .git/hooks/pre-commit')
235
235
  .action(function (...args) {
@@ -239,7 +239,7 @@ program.command('precommit')
239
239
  // dotenvx prebuild
240
240
  program.command('prebuild')
241
241
  .description('prevent including .env files in docker')
242
- .addHelpText('after', examples.prebuild)
242
+ .addHelpText('after', help.prebuild)
243
243
  .argument('[directory]', 'directory to prevent including .env files from', '.')
244
244
  .action(function (...args) {
245
245
  return require('./actions/ext/prebuild').apply(this, args)
@@ -260,17 +260,6 @@ program.command('update')
260
260
  return require('./actions/update').apply(this, args)
261
261
  })
262
262
 
263
- // dotenvx curl
264
- program.command('curl', { hidden: true })
265
- .description('make an authenticated dotenvx API request')
266
- .argument('<url>', 'dotenvx API URL')
267
- .option('-X, --request <method>', 'HTTP request method')
268
- .option('--data <json>', 'JSON request body')
269
- .option('--token <token>', 'set Armor ⛨ token')
270
- .action(function (...args) {
271
- return require('./actions/curl').apply(this, args)
272
- })
273
-
274
263
  // dotenvx login (compatibility alias for dotenvx armor login)
275
264
  program.command('login', { hidden: true })
276
265
  .description('log in to move keys off-device, share with your team, and audit access')
@@ -289,6 +278,18 @@ program.command('logout', { hidden: true })
289
278
  return require('./actions/logout').apply(this, args)
290
279
  })
291
280
 
281
+ // dotenvx curl
282
+ program.command('curl', { hidden: true })
283
+ .description('Dotenvx Armor API')
284
+ .addHelpText('after', help.curl)
285
+ .argument('<url>', '(run dotenvx run --help for list of urls)')
286
+ .option('-X, --request <method>', 'HTTP request method')
287
+ .option('--data <json>', 'JSON request body')
288
+ .option('--token <token>', 'set token')
289
+ .action(function (...args) {
290
+ return require('./actions/curl').apply(this, args)
291
+ })
292
+
292
293
  // dotenvx help
293
294
  program.command('help [command]')
294
295
  .description('display help for command')
@@ -311,6 +312,7 @@ program.addHelpText('after', 'Professional Security: ')
311
312
  program.addHelpText('after', ' lock ⊡ lock private keys with a local passphrase')
312
313
  program.addHelpText('after', ' native ⌥ move private keys into your OS secret store')
313
314
  program.addHelpText('after', ' armor ⛨ move private keys into Dotenvx Armor [www.dotenvx.com/armor]')
315
+ program.addHelpText('after', ' curl ⛨ call authenticated api to Dotenvx Armor [www.dotenvx.com/armor]')
314
316
 
315
317
  // dotenvx native
316
318
  require('./commands/native')(program.command('native', { hidden: true }))
@@ -90,10 +90,43 @@ Examples:
90
90
  `
91
91
  }
92
92
 
93
+ const curl = function () {
94
+ return `
95
+ Endpoints:
96
+
97
+ GET /api/account
98
+ GET /api/armor/keypairs
99
+ GET /api/armor/keypairs/:public_key
100
+ POST /api/armor/keypairs/:public_key/settings/guard
101
+ POST /api/armor/keypairs/:public_key/settings/enclave
102
+ GET /api/teams
103
+ GET /api/teams/:team
104
+ GET /api/teams/:team/members
105
+ GET /api/teams/:team/invitations
106
+ POST /api/teams/:team/invitations
107
+ DELETE /api/teams/:team/invitations/:id
108
+
109
+ Examples:
110
+
111
+ dotenvx curl https://armor.dotenvx.com/api/account
112
+ dotenvx curl https://armor.dotenvx.com/api/armor/keypairs
113
+ dotenvx curl https://armor.dotenvx.com/api/armor/keypairs/PUBLIC_KEY
114
+ dotenvx curl https://armor.dotenvx.com/api/armor/keypairs/PUBLIC_KEY/settings/guard --data '{"value":true}'
115
+ dotenvx curl https://armor.dotenvx.com/api/armor/keypairs/PUBLIC_KEY/settings/enclave --data '{"value":true}'
116
+ dotenvx curl https://armor.dotenvx.com/api/teams
117
+ dotenvx curl https://armor.dotenvx.com/api/teams/TEAM
118
+ dotenvx curl https://armor.dotenvx.com/api/teams/TEAM/members
119
+ dotenvx curl https://armor.dotenvx.com/api/teams/TEAM/members
120
+ dotenvx curl https://armor.dotenvx.com/api/teams/TEAM/invitations --data '{"email":"person@example.com","role":"member"}'
121
+ dotenvx curl https://armor.dotenvx.com/api/teams/TEAM/invitations/123 --request DELETE
122
+ `
123
+ }
124
+
93
125
  module.exports = {
94
126
  run,
95
127
  precommit,
96
128
  prebuild,
97
129
  gitignore,
98
- set
130
+ set,
131
+ curl
99
132
  }
@@ -1,12 +1,15 @@
1
1
  function buildApiError (statusCode, json) {
2
2
  const code = json.error.code || statusCode.toString()
3
3
  const message = `[${code}] ${json.error.message}`
4
- const help = `[${code}] ${json.error.help || JSON.stringify(json)}`
4
+ const help = json.error.help ? `fix: [${json.error.help}]` : `[${code}] ${JSON.stringify(json)}`
5
5
  const meta = json.error.meta
6
6
 
7
7
  const error = new Error(message)
8
8
  error.code = code
9
9
  error.help = help
10
+ if (json.error.help) {
11
+ error.messageWithHelp = `${message}. ${help}`
12
+ }
10
13
  error.meta = meta
11
14
  error.json = json
12
15