How to parse command line args in Node.js
Parsing command line arguments correctly is the foundation of any useful Node.js CLI tool or script.
As the creator of CoreUI with over 10 years of Node.js experience since 2014, I’ve built dozens of CLI tools that accept flags, options, and positional arguments.
The standard approach uses the built-in process.argv for simple cases or minimist for automatic flag parsing without heavier frameworks.
This makes scripts flexible and configurable without code changes.
Read raw arguments from process.argv.
// node script.js hello world --debug
const args = process.argv.slice(2)
console.log(args) // ['hello', 'world', '--debug']
const positional = args.filter(a => !a.startsWith('-'))
const flags = args.filter(a => a.startsWith('-'))
console.log('Positional:', positional) // ['hello', 'world']
console.log('Flags:', flags) // ['--debug']
process.argv[0] is the Node.js binary path. process.argv[1] is the script path. Slicing from index 2 gives user-provided arguments. This is sufficient for simple scripts.
Using minimist for Easy Parsing
Parse flags and options automatically.
npm install minimist
const minimist = require('minimist')
// node script.js --name Alice --port 3000 --verbose file.txt
const argv = minimist(process.argv.slice(2))
console.log(argv.name) // 'Alice'
console.log(argv.port) // 3000 (number, not string)
console.log(argv.verbose) // true
console.log(argv._) // ['file.txt'] (positional)
minimist parses --key value into an object. Numbers are cast automatically. Boolean flags without values become true. Positional arguments collect in argv._.
Setting Defaults and Types
Ensure expected types and fallback values.
const minimist = require('minimist')
const argv = minimist(process.argv.slice(2), {
string: ['name', 'output'],
boolean: ['verbose', 'dry-run'],
number: ['port', 'timeout'],
default: {
port: 3000,
timeout: 5000,
verbose: false,
output: './dist'
},
alias: {
v: 'verbose',
o: 'output',
p: 'port'
}
})
console.log(`Starting on port ${argv.port}`)
console.log(`Output: ${argv.output}`)
console.log(`Verbose: ${argv.verbose}`)
string forces values to strings even if they look numeric. boolean flags default to false when absent. default provides fallback values. alias supports short flags like -v as an alias for --verbose.
Using Node.js Built-in parseArgs
Node.js 18+ has built-in argument parsing.
const { parseArgs } = require('node:util')
const { values, positionals } = parseArgs({
args: process.argv.slice(2),
options: {
name: { type: 'string', short: 'n' },
port: { type: 'string', short: 'p', default: '3000' },
verbose: { type: 'boolean', short: 'v', default: false }
},
allowPositionals: true
})
console.log('Name:', values.name)
console.log('Port:', Number(values.port))
console.log('Verbose:', values.verbose)
console.log('Files:', positionals)
node:util parseArgs is zero-dependency. It validates types at parse time. Short options use the short property. All string values must be converted manually if you need numbers.
Validating Required Arguments
Exit with helpful errors when required args are missing.
const minimist = require('minimist')
const chalk = require('chalk')
const argv = minimist(process.argv.slice(2), {
string: ['input', 'output'],
default: { format: 'json' }
})
function validate(argv) {
const errors = []
if (!argv.input) errors.push('--input is required')
if (!argv.output) errors.push('--output is required')
if (!['json', 'csv', 'xml'].includes(argv.format)) {
errors.push('--format must be json, csv, or xml')
}
if (errors.length > 0) {
errors.forEach(e => console.error(chalk.red(`Error: ${e}`)))
console.error('\nUsage: script --input <file> --output <dir> [--format json]')
process.exit(1)
}
}
validate(argv)
console.log(`Processing ${argv.input} → ${argv.output}`)
Collect all errors before exiting to show all problems at once. process.exit(1) signals failure to calling scripts. Print a usage example to help users correct their invocation.
Best Practice Note
This is the same argument parsing approach we use in CoreUI’s build scripts and code generation tools. Always provide sensible defaults so scripts work without any arguments for the common case. Print a help message with --help flag support. Use descriptive flag names over cryptic single letters, but add aliases for frequently used flags. For complex CLIs with subcommands, upgrade to commander which handles the full argument tree cleanly.



