Arg is an unopinionated, no-frills CLI argument parser for Node.js. It takes a specification object defining argument types and aliases, then parses command line arguments returning a simple object with parsed values. The library provides zero-dependency, high-performance parsing with built-in error handling and flexible parsing modes.
npm install argconst arg = require('arg');For ES modules:
import arg from 'arg';const arg = require('arg');
// Define argument specification
const args = arg({
// Type handlers
'--help': Boolean,
'--version': Boolean,
'--verbose': arg.COUNT, // Counts occurrences
'--port': Number, // Converts to number
'--name': String, // Converts to string
'--tag': [String], // Array of strings
// Aliases
'-h': '--help',
'-v': '--verbose',
'-p': '--port',
'-n': '--name'
});
console.log(args);
// Example result:
// {
// _: ['extra', 'arguments'],
// '--help': true,
// '--verbose': 3,
// '--port': 8080,
// '--name': 'myapp',
// '--tag': ['prod', 'web']
// }Parses command line arguments according to a specification object.
/**
* Parse command line arguments according to specification
* @param {Spec} spec - Argument specification object
* @param {Options} options - Optional parsing configuration
* @returns {Result} Parsed arguments object with _ array for positionals
*/
function arg(spec, options);
/**
* Specification object defining argument types and aliases
* @typedef {Object} Spec
* @property {string|Handler|Handler[]} [key] - Argument handler or alias
*/
interface Spec {
[key: string]: string | Handler | [Handler];
}
/**
* Parsing options configuration
* @typedef {Object} Options
* @property {string[]} [argv] - Arguments to parse (default: process.argv.slice(2))
* @property {boolean} [permissive] - Allow unknown arguments instead of throwing error (default: false)
* @property {boolean} [stopAtPositional] - Stop parsing at first positional argument (default: false)
*/
interface Options {
argv?: string[];
permissive?: boolean;
stopAtPositional?: boolean;
}
/**
* Result object with parsed arguments
* @typedef {Object} Result
* @property {string[]} _ - Array of positional/unparsed arguments
* @property {*} [argumentName] - Parsed values for each specified argument
*/
interface Result {
_: string[];
[key: string]: any;
}Usage Example:
const args = arg(
{
'--output': String,
'--count': Number,
'--verbose': Boolean,
'-o': '--output',
'-c': '--count',
'-v': '--verbose'
},
{
argv: ['--output', 'result.txt', '--count', '5', '--verbose', 'file1.js', 'file2.js'],
permissive: false
}
);
// Result: { _: ['file1.js', 'file2.js'], '--output': 'result.txt', '--count': 5, '--verbose': true }Marks a handler function as a flag that doesn't consume the next argument.
/**
* Mark a handler function as a flag (boolean-like behavior)
* @param {Function} fn - Handler function to mark as flag
* @returns {Function} Handler function with flag symbol
*/
arg.flag(fn);Usage Example:
function customCounter(value, argName, previousValue) {
return (previousValue || 0) + 1;
}
const args = arg({
'--debug': arg.flag(customCounter),
'-d': '--debug'
});
// --debug -d --debug results in: { '--debug': 3 }Built-in utility for counting flag occurrences.
/**
* Built-in flag handler that counts occurrences
* Equivalent to arg.flag((v, name, prev) => (prev || 0) + 1)
*/
arg.COUNT;Internal symbol used to mark functions as flags.
/**
* Internal symbol used to identify flag handlers
* Used by arg.flag() to mark handlers that don't consume arguments
*/
arg.flagSymbol;Usage Example:
// Check if a handler is marked as a flag
function isFlag(handler) {
return handler[arg.flagSymbol] === true;
}
const myHandler = arg.flag((v, name, prev) => (prev || 0) + 1);
console.log(isFlag(myHandler)); // true
console.log(isFlag(String)); // falseCustom error class for argument parsing errors with specific error codes.
/**
* Custom error class for argument parsing errors
* @param {string} message - Error message
* @param {string} code - Specific error code for programmatic handling
*/
class ArgError extends Error {
constructor(message, code);
/** Error name (always 'ArgError') */
name: string;
/** Specific error code for programmatic handling */
code: string;
}
// Available as arg.ArgErrorError Codes:
ARG_CONFIG_NO_SPEC: No specification object providedARG_CONFIG_EMPTY_KEY: Empty string used as argument keyARG_CONFIG_NONOPT_KEY: Argument key doesn't start with '-'ARG_CONFIG_NONAME_KEY: Singular '-' keys not allowedARG_CONFIG_VAD_TYPE: Invalid type (not function or valid array)ARG_CONFIG_SHORTOPT_TOOLONG: Short arguments must be single characterARG_UNKNOWN_OPTION: Unknown option in non-permissive modeARG_MISSING_REQUIRED_SHORTARG: Option requires argument but followed by short argARG_MISSING_REQUIRED_LONGARG: Option requires argument but none providedUsage Example:
try {
const args = arg({ '--port': Number });
} catch (err) {
if (err instanceof arg.ArgError && err.code === 'ARG_UNKNOWN_OPTION') {
console.log('Unknown option:', err.message);
} else {
throw err;
}
}// String handler (identity function)
'--name': String // Converts argument to string
// Number handler
'--port': Number // Converts argument to number
// Boolean handler (flag behavior)
'--verbose': Boolean // Always returns true, consumes no argument
// BigInt handler (if available)
'--big': BigInt // Converts argument to BigInt// Array types for multiple values
'--tag': [String] // Array of strings
'--port': [Number] // Array of numbers
'--flag': [Boolean] // Array of booleansUsage Example:
const args = arg({
'--tag': [String],
'--port': [Number]
});
// --tag prod --tag dev --port 8080 --port 3000
// Result: { '--tag': ['prod', 'dev'], '--port': [8080, 3000] }/**
* Custom type handler function
* @param {string} value - The argument value (always a string)
* @param {string} name - The argument name (e.g., '--port')
* @param {any} previousValue - Previous value for this argument (for accumulation)
* @returns {any} Processed value
*/
function Handler(value, name, previousValue) {
// Custom processing logic here
return processedValue;
}Usage Example:
// Custom JSON parser
const parseJSON = (value, name, prev) => {
try {
return JSON.parse(value);
} catch (e) {
throw new Error(`Invalid JSON for ${name}: ${value}`);
}
};
const args = arg({
'--config': parseJSON,
'--data': [parseJSON] // Array of JSON objects
});String values in the specification create aliases that map one argument to another.
// Alias definition
{
'-v': '--verbose', // -v maps to --verbose
'--output': String,
'-o': '--output' // -o maps to --output
}Usage Example:
const args = arg({
'--verbose': arg.COUNT,
'--output': String,
'-v': '--verbose',
'-o': '--output',
'--log': '--output' // Multiple aliases can point to same target
});When permissive: true, unknown arguments are added to the _ array instead of throwing an error.
const args = arg(
{ '--known': String },
{ permissive: true, argv: ['--known', 'value', '--unknown', 'ignored'] }
);
// Result: { _: ['--unknown', 'ignored'], '--known': 'value' }When stopAtPositional: true, parsing stops at the first positional argument.
const args = arg(
{ '--flag': Boolean },
{ stopAtPositional: true, argv: ['--flag', 'file.txt', '--ignored'] }
);
// Result: { _: ['file.txt', '--ignored'], '--flag': true }Override the default process.argv.slice(2) with custom arguments.
const args = arg(
{ '--port': Number },
{ argv: ['--port', '8080', 'server.js'] }
);
// Result: { _: ['server.js'], '--port': 8080 }Arg supports multiple argument formats:
# Long arguments with values
--port 8080
--port=8080
# Short arguments
-p 8080
-v
# Combined short flags
-vvv # Same as -v -v -v
-abc # Same as -a -b -c (if all are flags)
# Double dash separator
cmd --verbose file1.txt -- --not-parsed
# Negative numbers (special handling)
--number -42
--number=-42