minimist

A minimal library for argument parsing. Features very lightweight and simple implementation.

javascriptnodejscliargument-parsinglightweight

Framework

minimist

Overview

minimist is a minimal and lightweight library for parsing command-line arguments in Node.js. It provides basic functionality to convert process.argv into a structured object, designed with a simple API and minimal dependencies. It's widely used internally by many large-scale CLI tools and has been broadly adopted as the foundation for argument parsing.

Why minimist is chosen:

  • Minimal design: Lightweight and fast with no dependencies
  • Simple API: Low learning curve, easy to get started
  • Wide compatibility: Works with all versions of Node.js
  • Foundation library: Adopted in internal implementations of many CLI tools
  • Flexibility: Provides basic parsing functionality, customizable at higher layers

Details

History and Evolution

minimist was developed by James Halliday (substack) in 2013 and has grown as the foundational library for argument parsing in the Node.js ecosystem. Designed as a lightweight version of optimist, it achieves high performance and compatibility by focusing on minimal essential functionality.

Position in the Ecosystem

It plays a foundational role in the Node.js ecosystem:

  • Internal dependency: Used by higher-level libraries like yargs and commander.js
  • Simple scripts: Standard choice for lightweight CLI scripts
  • Educational purposes: Teaching material for understanding argument parsing mechanisms
  • Prototyping: Tool for rapid development and testing

Latest Trends (2024-2025)

  • Stable maturity: Maintains stable API over long periods
  • Security enhancements: Security improvements including prototype pollution countermeasures
  • ES Module support: Supports both CommonJS and ESM
  • TypeScript type definitions: Improved type safety with @types/minimist
  • Continuous maintenance: Security updates and compatibility maintenance

Key Features

Basic Functionality

  • Argument parsing: Converts process.argv into structured objects
  • Dash parsing: Processing of - and -- prefixes
  • Positional arguments: Collects non-option arguments in _ array
  • Aliases: Short and full form argument aliases
  • Type specification: Type conversion for strings, booleans, and numbers

Advanced Options

  • Default values: Setting default values for unspecified arguments
  • stopEarly: Stop parsing at first non-option argument
  • -- processing: Special handling of arguments after --
  • unknown function: Handling of undefined options
  • Transform functions: Custom value transformation processing

Performance Characteristics

  • Lightweight: Small footprint under 10KB
  • Fast: Minimal processing overhead
  • Memory efficient: Avoids unnecessary object creation
  • No dependencies: No reliance on external libraries

Pros and Cons

Pros

  • Lightweight: Minimal bundle size
  • Fast: High performance
  • Simple: Low learning cost
  • Stable: Stable API over long periods
  • Compatible: Works with wide range of Node.js versions
  • No dependencies: Low security risk

Cons

  • Limited functionality: Provides only basic features
  • No help generation: No automatic help message functionality
  • No validation: No input value validation functionality
  • No command support: No subcommand mechanism
  • No interactive features: No interactive features like prompts

Key Links

Usage Examples

Basic Usage

const minimist = require('minimist');

// Command example: node script.js -a beep --foo bar baz
const args = minimist(process.argv.slice(2));
console.log(args);

// Output:
// {
//   _: ['baz'],
//   a: 'beep',
//   foo: 'bar'
// }

Type Specification Example

const minimist = require('minimist');

// Command example: node script.js --port 3000 --debug --name myapp
const args = minimist(process.argv.slice(2), {
  string: ['name'],        // Treat name as string
  boolean: ['debug'],      // Treat debug as boolean
  alias: {                 // Alias configuration
    p: 'port',
    d: 'debug',
    n: 'name'
  }
});

console.log(args);
// Output:
// {
//   _: [],
//   port: 3000,
//   debug: true,
//   d: true,
//   name: 'myapp',
//   n: 'myapp',
//   p: 3000
// }

Setting Default Values

const minimist = require('minimist');

const args = minimist(process.argv.slice(2), {
  default: {
    port: 8080,
    host: 'localhost',
    debug: false
  },
  string: ['host'],
  boolean: ['debug'],
  alias: {
    p: 'port',
    h: 'host',
    d: 'debug'
  }
});

console.log(`Server starting on ${args.host}:${args.port}`);
console.log(`Debug mode: ${args.debug ? 'ON' : 'OFF'}`);

// Execution examples:
// node server.js
// => Server starting on localhost:8080, Debug mode: OFF
//
// node server.js --port 3000 --debug
// => Server starting on localhost:3000, Debug mode: ON

Using stopEarly Option

const minimist = require('minimist');

// stopEarly: Stop parsing at first non-option argument
const args = minimist(process.argv.slice(2), {
  stopEarly: true
});

console.log(args);

// Command example: node script.js --verbose command --arg value
// Output:
// {
//   _: ['command', '--arg', 'value'],
//   verbose: true
// }

Double Dash (--) Processing

const minimist = require('minimist');

const args = minimist(process.argv.slice(2), {
  '--': true  // Store arguments after -- in argv['--']
});

console.log(args);

// Command example: node script.js --name test -- --other-flag value
// Output:
// {
//   _: [],
//   name: 'test',
//   '--': ['--other-flag', 'value']
// }

Custom Handling with unknown Function

const minimist = require('minimist');

const args = minimist(process.argv.slice(2), {
  unknown: function (arg) {
    if (arg.startsWith('-') || arg.startsWith('--')) {
      console.error(`Unknown option: ${arg}`);
      return false; // Ignore this argument
    }
    return true; // Process as positional argument
  }
});

console.log(args);

// Command example: node script.js --known value --unknown test positional
// Error output: Unknown option: --unknown
// Output:
// {
//   _: ['positional'],
//   known: 'value'
// }

Practical CLI Tool Example

#!/usr/bin/env node
const minimist = require('minimist');
const fs = require('fs');
const path = require('path');

// Help message
function showHelp() {
  console.log(`
Usage: mytools [options] <command> [args...]

Options:
  -h, --help     Show this help message
  -v, --verbose  Enable verbose output
  -o, --output   Output file path
  --version      Show version number

Commands:
  build          Build the project
  test           Run tests
  clean          Clean build artifacts

Examples:
  mytools build --output dist/
  mytools test --verbose
  mytools clean
`);
}

// Version information
function showVersion() {
  const packageJson = JSON.parse(
    fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8')
  );
  console.log(packageJson.version);
}

// Argument parsing
const args = minimist(process.argv.slice(2), {
  string: ['output', 'o'],
  boolean: ['help', 'verbose', 'version', 'h', 'v'],
  alias: {
    h: 'help',
    v: 'verbose',
    o: 'output'
  },
  default: {
    verbose: false
  }
});

// Show help
if (args.help) {
  showHelp();
  process.exit(0);
}

// Show version
if (args.version) {
  showVersion();
  process.exit(0);
}

// Get command
const command = args._[0];

if (!command) {
  console.error('Error: No command specified');
  showHelp();
  process.exit(1);
}

// Log function
function log(message) {
  if (args.verbose) {
    console.log(`[INFO] ${message}`);
  }
}

// Command processing
switch (command) {
  case 'build':
    log('Starting build process...');
    const outputDir = args.output || 'dist';
    console.log(`Building project to ${outputDir}/`);
    log('Build completed successfully');
    break;

  case 'test':
    log('Running test suite...');
    console.log('All tests passed!');
    break;

  case 'clean':
    log('Cleaning build artifacts...');
    console.log('Clean completed');
    break;

  default:
    console.error(`Error: Unknown command '${command}'`);
    showHelp();
    process.exit(1);
}

TypeScript Usage Example

import minimist from 'minimist';

interface CLIArgs {
  _: string[];
  port: number;
  host: string;
  debug: boolean;
  config?: string;
  help?: boolean;
}

const args = minimist(process.argv.slice(2), {
  string: ['host', 'config'],
  boolean: ['debug', 'help'],
  alias: {
    p: 'port',
    h: 'host',
    d: 'debug',
    c: 'config'
  },
  default: {
    port: 3000,
    host: 'localhost',
    debug: false
  }
}) as CLIArgs;

if (args.help) {
  console.log('Usage: server [options]');
  console.log('Options:');
  console.log('  -p, --port <number>     Server port (default: 3000)');
  console.log('  -h, --host <string>     Server host (default: localhost)');
  console.log('  -d, --debug             Enable debug mode');
  console.log('  -c, --config <path>     Configuration file path');
  console.log('  --help                  Show this help');
  process.exit(0);
}

console.log(`Starting server on ${args.host}:${args.port}`);
if (args.debug) {
  console.log('Debug mode enabled');
}
if (args.config) {
  console.log(`Using configuration file: ${args.config}`);
}

Combining with Configuration Files

const minimist = require('minimist');
const fs = require('fs');
const path = require('path');

function loadConfig(configPath) {
  try {
    const configFile = path.resolve(configPath);
    const config = JSON.parse(fs.readFileSync(configFile, 'utf8'));
    return config;
  } catch (error) {
    console.error(`Failed to load config file: ${error.message}`);
    return {};
  }
}

// Argument parsing
const args = minimist(process.argv.slice(2), {
  string: ['config'],
  boolean: ['watch', 'minify'],
  alias: {
    c: 'config',
    w: 'watch',
    m: 'minify'
  },
  default: {
    config: './build.config.json'
  }
});

// Load configuration file
const config = loadConfig(args.config);

// Override configuration with CLI options
const finalConfig = {
  ...config,
  watch: args.watch ?? config.watch ?? false,
  minify: args.minify ?? config.minify ?? true,
  input: args._[0] || config.input || 'src/index.js',
  output: args._[1] || config.output || 'dist/bundle.js'
};

console.log('Build configuration:', finalConfig);

// Build processing (example)
if (finalConfig.watch) {
  console.log('Starting in watch mode...');
}

if (finalConfig.minify) {
  console.log('Minification enabled');
}

console.log(`Input: ${finalConfig.input}`);
console.log(`Output: ${finalConfig.output}`);