process.argv

Returns the command-line arguments the process was launched with, as an array of strings.

Signature
process.argv
  • Added in Node.js v0.1.27

Return value

string[]An array of strings: the executable path, the entry point path if one was provided, then any remaining command-line arguments.

process.argv is the raw argument vector. Index 0 is process.execPath — the absolute path of the Node binary — and index 1 is the absolute path of the entry point. Everything a user typed starts at index 2, which is why almost every CLI begins with process.argv.slice(2).

When to reach for it

Use it for small scripts and build steps where a full argument-parsing dependency is overkill, or as the input to util.parseArgs() for anything with flags, short options and positionals.

What trips people up

  • Runtime flags are not in argv. Options aimed at Node itself, such as --trace-warnings or --max-old-space-size, land in process.execArgv. Only arguments after the script path reach argv.
  • There is no argv[1] with node -e. With inline evaluation there is no entry point, so user arguments start at index 1 and slice(2) silently drops the first one.
  • Everything is a string. --port 8080 gives you '8080'; nothing is coerced and nothing is validated.
  • npm swallows flags. npm run build --watch passes --watch to npm; you need npm run build -- --watch.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Accept a target file path for a one-off migration or codemod script.
  • Read a --dry-run flag before a script performs destructive work.
  • Feed process.argv.slice(2) into util.parseArgs() to build a small CLI.
  • Log the exact command a failing CI job was invoked with.

Frequently asked questions

Why does process.argv start at index 2 for my arguments?

Because index 0 is the Node executable and index 1 is the absolute path of the script being run, so user arguments begin at index 2. The exception is `node -e '...'`, where no script path exists and the first user argument sits at index 1.

How do I pass arguments through npm run to my script?

Put a bare `--` between the npm script name and your arguments: `npm run build -- --watch`. Without the separator npm treats `--watch` as its own flag and it never reaches process.argv.

Why is my numeric argument a string?

process.argv is documented as `string[]`, so nothing is parsed or coerced for you. Convert with `Number(value)` and check the result with `Number.isFinite()`, since a bad argument yields `NaN` instead of throwing.

More examples

Parsing flags with util.parseArgs()

The output shows parseArgs (available since v18.3.0) splitting the same array three ways: `--out ./dump` becomes a typed value, the short `-v` expands to `verbose: true`, and the two bare filenames collect into `positionals`. An unknown flag makes parseArgs throw `ERR_PARSE_ARGS_UNKNOWN_OPTION` rather than being silently ignored, which is the main reason to prefer it over hand-rolled filtering.

Example · javascript
const { parseArgs } = require('node:util');

// node backup.js --out ./dump -v notes.txt todo.txt
const { values, positionals } = parseArgs({
  args: process.argv.slice(2),
  options: {
    out: { type: 'string', short: 'o', default: './backup' },
    verbose: { type: 'boolean', short: 'v', default: false },
  },
  allowPositionals: true,
});

console.log('output directory:', values.out);
console.log('verbose:', values.verbose);
console.log('files:', positionals);
// output directory: ./dump
// verbose: true
// files: [ 'notes.txt', 'todo.txt' ]

argv versus execArgv

The output shows where each part of the command line ends up. `--trace-warnings` appears only in `execArgv` because it was consumed by the runtime before the script started, while `--port 8080` reaches `argv`. `process.argv0` keeps the original argv[0] as the shell supplied it, which differs from the resolved `execPath` when the binary was invoked through a symlink or a custom name.

Example · javascript
// Invoked as: node --trace-warnings server.js --port 8080
console.log('execPath   :', process.argv[0]);
console.log('argv0      :', process.argv0);
console.log('entry point:', process.argv[1]);
console.log('user args  :', process.argv.slice(2));
console.log('node flags :', process.execArgv);
// execPath   : /usr/local/bin/node
// argv0      : node
// entry point: /srv/app/server.js
// user args  : [ '--port', '8080' ]
// node flags : [ '--trace-warnings' ]

A dry-run guard for a destructive script

The output shows the script reporting what it would do rather than doing it. Exiting with code 1 on missing arguments is what makes the script usable from a Makefile or CI step: a shell `&&` chain stops on the non-zero code, whereas printing usage and returning normally would let the pipeline continue as if the work had succeeded.

Example · javascript
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');
const targets = args.filter((a) => !a.startsWith('-'));

if (targets.length === 0) {
  console.error('usage: node prune.js [--dry-run] <path...>');
  process.exit(1);
}

for (const target of targets) {
  if (dryRun) {
    console.log(`would delete: ${target}`);
  } else {
    console.log(`deleting: ${target}`);
  }
}
// node prune.js --dry-run cache/ tmp/
// would delete: cache/
// would delete: tmp/

Discussion

  • Be the first to comment on this lesson.