mrkeyoor.com_
Sat 08 Aug 21:00 UTC
npmCLI & Toolingupdated 08 Aug 2026

getopts

getopts is a small, dependency-free parser that turns an argv array into an object of flags plus a special underscore array for positional operands. It understands grouped short flags, long options, aliases, defaults, negated booleans, repeated values, an end-of-options marker, and early stopping for hand-built subcommands. It ships both ESM and CommonJS entry points and TypeScript declarations, but it deliberately stops at parsing: help text, command dispatch, validation, prompts, and error messages remain your application's job.

Verdict

getopts is a good low-level choice when all you need is fast argv parsing and you are willing to own validation and help. Do not install it expecting a CLI framework, precise inferred types, or conservative string handling.

API stability5/5Version 2.3.0 exposes one function and six compact configuration concepts: alias, boolean, string, default, unknown, and stopEarly. The repository implementation is about 180 lines and the public behavior is fully visible in one file. With no plugin lifecycle or command abstraction to evolve, the compatibility surface is small. The tradeoff is that long-standing coercion and scalar-to-array behavior are part of that stable contract too.
Docs4/5The README documents short and long flags, attached values, aliases, forced strings and booleans, defaults, unknown filtering, repeated options, negation, operands, the double-dash marker, and stopEarly with runnable input-and-output examples. Included declarations repeat most of that guidance. It does not provide a dedicated site, migration history, or an explicit table of coercion edge cases, so the implementation remains the final reference for ambiguous tokens.
Maintenance3/5The package is not deprecated and the repository is not archived. GitHub shows a push in July 2025 and only five open issues and pull requests combined, which is manageable for such a small project. However, npm 2.3.0 was published in February 2021 and remains current. That can indicate maturity, but it also means fixes and compatibility changes are delivered slowly, so teams should test their exact edge cases before depending on a future response.
Ecosystem4/5The package received 4,538,269 npm downloads in the measured week and has no runtime dependencies, making it a common transitive building block with little installation risk. It supports ESM, CommonJS, and TypeScript declarations from one package. Its ecosystem is intentionally narrow, though: there are no official help, completion, prompt, validation, or command-routing add-ons comparable to the integrations built around Commander and yargs.

Use it if

  • You need to parse flags in a small Node CLI without adopting a command framework or adding runtime dependencies
  • You are replacing minimist and want a similarly direct object result with aliases, booleans, strings, defaults, and positional operands
  • You need both import and require consumers from the same package and are comfortable validating the parsed result yourself
  • You want stopEarly parsing so a small dispatcher can hand the remaining argv tokens to a subcommand
Skip it if

Setup reality

npm install getopts is the whole dependency setup. There are no peer dependencies, native modules, credentials, generated files, or configuration files. The package exposes an ES module default from index.js and a CommonJS export from index.cjs, so both import getopts from 'getopts' and require('getopts') are supported. The surprises are behavioral. Pass process.argv.slice(2), not the complete process.argv array. Unless an option is listed in boolean, a following non-option token becomes its value; this means --verbose file.txt consumes file.txt instead of leaving it positional. Unless an option is listed in string, values that JavaScript's numeric conversion accepts become numbers, and the exact text false becomes boolean false. Declared string and boolean options are always present even when omitted, as an empty string or false. Repeating a key changes its result from a scalar to an array, so downstream code must allow both shapes. A separate negative number begins with a dash and may be read as another option; use an equals form such as --count=-1 when that value is intended. The unknown callback filters only names not mentioned by alias, boolean, string, or default settings, and returning false silently discards them rather than throwing. Type declarations are included, but the dynamic result keys are typed as any. There is no automatic help or invalid-flag error, so production CLIs need their own usage text, validation, and exit-code policy.

Patterns

Parse flags and positional operandsparse-process-arguments

import getopts from 'getopts';

const options = getopts(process.argv.slice(2));
console.log(options.verbose);
console.log(options._);

Always slice off the Node executable and script path. Non-option tokens are collected in options._.

Keep short and long aliases in syncdefine-aliases

const options = getopts(['-o', 'dist/app.js'], {
  alias: {output: ['o', 'f']},
});

console.log(options.output); // dist/app.js
console.log(options.o);      // dist/app.js

Every alias is written into the result. Repeated values share the same array object across the canonical name and its aliases.

Prevent a boolean from consuming the next operandforce-boolean-flag

const options = getopts(['--verbose', 'report.txt'], {
  boolean: ['verbose'],
});

console.log(options.verbose); // true
console.log(options._);       // ['report.txt']

Without the boolean declaration, report.txt becomes the value of verbose rather than a positional operand.

Keep numeric-looking input as textpreserve-string-value

const options = getopts(['--zip=00123'], {
  string: ['zip'],
});

console.log(options.zip); // '00123'

Undeclared values are coerced when numeric conversion succeeds, which would turn 00123 into 123.

Apply defaults and aliasesset-default-values

const options = getopts([], {
  alias: {port: 'p'},
  default: {port: 3000, color: true},
});

console.log(options.port, options.p); // 3000 3000

Defaults are copied to known aliases. A value provided on argv replaces the default for the canonical key and aliases.

Read a repeated option as an arraycollect-repeated-options

const options = getopts([
  '--tag=docs',
  '--tag=release',
]);

console.log(options.tag); // ['docs', 'release']

The first occurrence is a scalar; only the second occurrence turns it into an array. Normalize with [].concat(options.tag ?? []) if both cases are valid.

Support a no-prefixed booleannegate-boolean-option

const options = getopts(['--no-color'], {
  boolean: ['color'],
  default: {color: true},
});

console.log(options.color); // false

Any long option beginning --no- is interpreted as the positive key set to false, even without a boolean declaration.

Stop option parsing with a double dashpass-through-operands

const options = getopts([
  '--quiet',
  '--',
  '--child-flag',
  'file.txt',
]);

console.log(options._); // ['--child-flag', 'file.txt']

Everything after the standalone -- is positional, which is the safest way to pass flags to a child process.

Allow only declared option namesfilter-unknown-options

const allowed = new Set(['verbose', 'v', 'output', 'o']);
const options = getopts(process.argv.slice(2), {
  alias: {verbose: 'v', output: 'o'},
  unknown: name => allowed.has(name),
});

Returning false drops an unknown option silently. Throw inside the callback or compare argv separately if invalid flags must produce an error.

Stop at the first operand for subcommand dispatchdispatch-subcommand

const root = getopts(process.argv.slice(2), {
  boolean: ['verbose'],
  stopEarly: true,
});

const [command, ...subargv] = root._;
if (command === 'build') {
  const build = getopts(subargv, {string: ['out']});
  // runBuild(build)
}

With stopEarly, every token from the first operand onward goes into _. Parse subargv separately with the selected command's option rules.

Bind a negative number with equals syntaxparse-negative-number

const options = getopts(['--offset=-5']);
console.log(options.offset); // -5

A separate -5 token starts with a dash and can be parsed as an option. The equals form makes the negative number unambiguous.

Use the CommonJS exportload-commonjs

const getopts = require('getopts');

const options = getopts(process.argv.slice(2), {
  boolean: ['help'],
});

The package export map selects index.cjs for require and index.js for import, so no interop .default access is needed.

Alternatives

PackageRegistryPick it when
minimistnpmChoose it when compatibility with minimist's long-established parsing behavior matters more than getopts' smaller focused implementation
mrinpmChoose it for another compact dependency-free parser with a similar flags-and-operands result
commandernpmChoose it when the CLI also needs subcommands, generated help, validation, action handlers, and a larger support ecosystem