From c5d576266f5be6aa2402ebc8723d0e6f279c5bc2 Mon Sep 17 00:00:00 2001 From: Benjamin Newman Date: Wed, 21 Jan 2026 16:53:40 -0800 Subject: [PATCH 1/4] docs: add util.parseArgs replacements for CLI argument parsers --- docs/modules/parseargs.md | 27 ++++++++++++++++++++ manifests/preferred.json | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 docs/modules/parseargs.md diff --git a/docs/modules/parseargs.md b/docs/modules/parseargs.md new file mode 100644 index 0000000..5a726b6 --- /dev/null +++ b/docs/modules/parseargs.md @@ -0,0 +1,27 @@ +--- +description: Modern alternatives to CLI argument parsing packages using Node.js built-in util.parseArgs +--- + +# Replacements for argument parsers + +## `util.parseArgs` (native, Node.js) + +[`util.parseArgs`](https://nodejs.org/api/util.html#utilparseargsconfig) is built into Node.js (since 18.3.0 and 16.17.0) and can replace many common CLI parsing libraries such as `minimist`, `mri`, `arg`, `meow`, `yargs-parser`, `yargs`, `commander`, and `sade`. + +Example: + +```ts +import { parseArgs } from 'node:util' + +const { values, positionals } = parseArgs({ + args: process.argv.slice(2), + options: { + force: { type: 'boolean', short: 'f' }, + output: { type: 'string', short: 'o' }, + }, + allowPositionals: true, +}) +``` + +> [!NOTE] +> `parseArgs` only supports `string` and `boolean` types and does not provide subcommand routing, auto-generated help, or validation. If your CLI relies heavily on these features, evaluate whether the dependency savings justify the added code. diff --git a/manifests/preferred.json b/manifests/preferred.json index 90fd04a..2c2e754 100644 --- a/manifests/preferred.json +++ b/manifests/preferred.json @@ -18,6 +18,12 @@ "replacements": ["node:stream"], "url": {"type": "e18e", "id": "through"} }, + "arg": { + "type": "module", + "moduleName": "arg", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} + }, "axios": { "type": "module", "moduleName": "axios", @@ -84,6 +90,12 @@ "replacements": ["util.styleText", "picocolors", "ansis"], "url": {"type": "e18e", "id": "chalk"} }, + "commander": { + "type": "module", + "moduleName": "commander", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} + }, "core-util-is": { "type": "module", "moduleName": "core-util-is", @@ -2304,6 +2316,18 @@ "replacements": ["node:crypto"], "url": {"type": "e18e", "id": "md5"} }, + "meow": { + "type": "module", + "moduleName": "meow", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} + }, + "minimist": { + "type": "module", + "moduleName": "minimist", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} + }, "mkdirp": { "type": "module", "moduleName": "mkdirp", @@ -2316,6 +2340,12 @@ "replacements": ["day.js", "date-fns", "luxon", "Date"], "url": {"type": "e18e", "id": "moment"} }, + "mri": { + "type": "module", + "moduleName": "mri", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} + }, "node-fetch": { "type": "module", "moduleName": "node-fetch", @@ -2464,6 +2494,12 @@ "replacements": ["fs.rm", "fs.rmdir", "premove"], "url": {"type": "e18e", "id": "rimraf"} }, + "sade": { + "type": "module", + "moduleName": "sade", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} + }, "set-value": { "type": "module", "moduleName": "set-value", @@ -2559,6 +2595,18 @@ "moduleName": "xmldom", "replacements": ["@xmldom/xmldom"], "url": {"type": "e18e", "id": "xmldom"} + }, + "yargs": { + "type": "module", + "moduleName": "yargs", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} + }, + "yargs-parser": { + "type": "module", + "moduleName": "yargs-parser", + "replacements": ["util.parseArgs"], + "url": {"type": "e18e", "id": "parseargs"} } }, "replacements": { @@ -3259,6 +3307,12 @@ "nodeFeatureId": {"moduleName": "node:util", "exportName": "types"}, "url": {"type": "node", "id": "api/util.html#utiltypes"} }, + "util.parseArgs": { + "id": "util.parseArgs", + "type": "native", + "nodeFeatureId": {"moduleName": "node:util", "exportName": "parseArgs"}, + "url": {"type": "node", "id": "api/util.html#utilparseargsconfig"} + }, "webpack.output.clean": { "id": "webpack.output.clean", "type": "documented", From 55ffc33a15bc3b6036dc902de3cdfc9fb56087fb Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Sun, 12 Apr 2026 18:26:52 +0100 Subject: [PATCH 2/4] docs: drop cli builders --- docs/modules/parseargs.md | 28 ++++++++++++++++---- manifests/preferred.json | 54 +++++++++++---------------------------- 2 files changed, 38 insertions(+), 44 deletions(-) diff --git a/docs/modules/parseargs.md b/docs/modules/parseargs.md index 5a726b6..1e90070 100644 --- a/docs/modules/parseargs.md +++ b/docs/modules/parseargs.md @@ -4,9 +4,9 @@ description: Modern alternatives to CLI argument parsing packages using Node.js # Replacements for argument parsers -## `util.parseArgs` (native, Node.js) +## `util.parseArgs` (native, since Node.js 16.x) -[`util.parseArgs`](https://nodejs.org/api/util.html#utilparseargsconfig) is built into Node.js (since 18.3.0 and 16.17.0) and can replace many common CLI parsing libraries such as `minimist`, `mri`, `arg`, `meow`, `yargs-parser`, `yargs`, `commander`, and `sade`. +[`util.parseArgs`](https://nodejs.org/api/util.html#utilparseargsconfig) is built into Node.js (since 18.3.0 and 16.17.0) and can replace many common CLI options parsing libraries. Example: @@ -17,11 +17,29 @@ const { values, positionals } = parseArgs({ args: process.argv.slice(2), options: { force: { type: 'boolean', short: 'f' }, - output: { type: 'string', short: 'o' }, + output: { type: 'string', short: 'o' } }, - allowPositionals: true, + allowPositionals: true }) ``` > [!NOTE] -> `parseArgs` only supports `string` and `boolean` types and does not provide subcommand routing, auto-generated help, or validation. If your CLI relies heavily on these features, evaluate whether the dependency savings justify the added code. +> `parseArgs` only supports `string` and `boolean` types. If you'd like to support stronger types, one of the other options may be a better fit. + +## `mri` + +[`mri`](https://github.com/lukeed/mri) is a minimalistic argument parser that supports both short and long options, as well as positional arguments. + +Example: + +```ts +import mri from 'mri' + +const options = mri(process.argv.slice(2), { + alias: { + f: 'force', + o: 'output' + }, + boolean: ['force'] +}) +``` diff --git a/manifests/preferred.json b/manifests/preferred.json index 13dd629..a7c4f30 100644 --- a/manifests/preferred.json +++ b/manifests/preferred.json @@ -27,7 +27,7 @@ "arg": { "type": "module", "moduleName": "arg", - "replacements": ["util.parseArgs"], + "replacements": ["util.parseArgs", "mri"], "url": {"type": "e18e", "id": "parseargs"} }, "@supabase/node-fetch": { @@ -120,12 +120,6 @@ "replacements": ["util.styleText", "picocolors", "ansis"], "url": {"type": "e18e", "id": "chalk"} }, - "commander": { - "type": "module", - "moduleName": "commander", - "replacements": ["util.parseArgs"], - "url": {"type": "e18e", "id": "parseargs"} - }, "copy-text-to-clipboard": { "type": "module", "moduleName": "copy-text-to-clipboard", @@ -2424,16 +2418,10 @@ "replacements": ["node:crypto"], "url": {"type": "e18e", "id": "md5"} }, - "meow": { - "type": "module", - "moduleName": "meow", - "replacements": ["util.parseArgs"], - "url": {"type": "e18e", "id": "parseargs"} - }, "minimist": { "type": "module", "moduleName": "minimist", - "replacements": ["util.parseArgs"], + "replacements": ["util.parseArgs", "mri"], "url": {"type": "e18e", "id": "parseargs"} }, "mkdirp": { @@ -2454,12 +2442,6 @@ "replacements": ["day.js", "date-fns", "luxon", "Date"], "url": {"type": "e18e", "id": "moment"} }, - "mri": { - "type": "module", - "moduleName": "mri", - "replacements": ["util.parseArgs"], - "url": {"type": "e18e", "id": "parseargs"} - }, "node-fetch": { "type": "module", "moduleName": "node-fetch", @@ -2632,12 +2614,6 @@ "replacements": ["fs.rm", "fs.rmdir", "premove"], "url": {"type": "e18e", "id": "rimraf"} }, - "sade": { - "type": "module", - "moduleName": "sade", - "replacements": ["util.parseArgs"], - "url": {"type": "e18e", "id": "parseargs"} - }, "set-value": { "type": "module", "moduleName": "set-value", @@ -2786,16 +2762,10 @@ "replacements": ["@xmldom/xmldom"], "url": {"type": "e18e", "id": "xmldom"} }, - "yargs": { - "type": "module", - "moduleName": "yargs", - "replacements": ["util.parseArgs"], - "url": {"type": "e18e", "id": "parseargs"} - }, "yargs-parser": { "type": "module", "moduleName": "yargs-parser", - "replacements": ["util.parseArgs"], + "replacements": ["util.parseArgs", "mri"], "url": {"type": "e18e", "id": "parseargs"} } }, @@ -3326,6 +3296,12 @@ "url": {"type": "e18e", "id": "body-parser"}, "replacementModule": "milliparsec" }, + "mri": { + "id": "mri", + "type": "documented", + "url": {"type": "e18e", "id": "parseargs"}, + "replacementModule": "mri" + }, "nano-staged": { "id": "nano-staged", "type": "documented", @@ -3613,6 +3589,12 @@ "id": "api/util.html#utilisdeepstrictequalval1-val2-options" } }, + "util.parseArgs": { + "id": "util.parseArgs", + "type": "native", + "nodeFeatureId": {"moduleName": "node:util", "exportName": "parseArgs"}, + "url": {"type": "node", "id": "api/util.html#utilparseargsconfig"} + }, "util.stripVTControlCharacters": { "id": "util.stripVTControlCharacters", "type": "native", @@ -3640,12 +3622,6 @@ "nodeFeatureId": {"moduleName": "node:util", "exportName": "types"}, "url": {"type": "node", "id": "api/util.html#utiltypes"} }, - "util.parseArgs": { - "id": "util.parseArgs", - "type": "native", - "nodeFeatureId": {"moduleName": "node:util", "exportName": "parseArgs"}, - "url": {"type": "node", "id": "api/util.html#utilparseargsconfig"} - }, "vitest": { "id": "vitest", "type": "documented", From aa40584b6913cd1939965faa7f572d4336961b9e Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Sun, 12 Apr 2026 18:36:10 +0100 Subject: [PATCH 3/4] chore: update readme --- docs/modules/README.md | 1 + manifests/preferred.json | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/modules/README.md b/docs/modules/README.md index 8342266..b325d20 100644 --- a/docs/modules/README.md +++ b/docs/modules/README.md @@ -14,6 +14,7 @@ ESLint plugin. - [`@75lb/deep-merge`](./deep-merge.md) - [`@jsdevtools/ezspawn`](./ez-spawn.md) +- [`arg`](./parseargs.md) - [`axios`](./fetch.md) - [`bluebird`](./bluebird-q.md) - [`body-parser`](./body-parser.md) diff --git a/manifests/preferred.json b/manifests/preferred.json index a7c4f30..967f6ca 100644 --- a/manifests/preferred.json +++ b/manifests/preferred.json @@ -24,18 +24,18 @@ "replacements": ["node:stream"], "url": {"type": "e18e", "id": "through"} }, - "arg": { - "type": "module", - "moduleName": "arg", - "replacements": ["util.parseArgs", "mri"], - "url": {"type": "e18e", "id": "parseargs"} - }, "@supabase/node-fetch": { "type": "module", "moduleName": "@supabase/node-fetch", "replacements": ["fetch", "ofetch", "ky"], "url": {"type": "e18e", "id": "fetch"} }, + "arg": { + "type": "module", + "moduleName": "arg", + "replacements": ["util.parseArgs", "mri"], + "url": {"type": "e18e", "id": "parseargs"} + }, "axios": { "type": "module", "moduleName": "axios", From f04c4938956e8656bfa0130009ebab659ba9ca3e Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:22:18 +0100 Subject: [PATCH 4/4] chore: remove redundant url --- manifests/preferred.json | 1 - 1 file changed, 1 deletion(-) diff --git a/manifests/preferred.json b/manifests/preferred.json index 710564b..8d5c15e 100644 --- a/manifests/preferred.json +++ b/manifests/preferred.json @@ -3233,7 +3233,6 @@ "mri": { "id": "mri", "type": "documented", - "url": {"type": "e18e", "id": "parseargs"}, "replacementModule": "mri" }, "nano-staged": {