Clap.js CLI Argument Parser
raw JSON →Clap.js is a robust library for Node.js designed to simplify the creation of command-line interfaces (CLIs). It provides a fluent API for defining commands, options, and arguments, supporting advanced features like argument coercion, completion suggestions, and sub-commands. The library aims to facilitate both simple CLI tools and complex applications with deep command hierarchies. Inspired by Commander.js, Clap.js focuses on ease of use and flexibility. The current stable version is 3.1.1, with recent releases addressing regressions and refining API signatures. Since version 3.0.0, it supports both ESM and CommonJS (dual module) and targets Node.js versions `^12.20.0`, `^14.13.0`, and `>=15.0.0`. It offers a structured approach to argv processing and context management for developers building intricate command-line tools.
Common errors
error Error: Command definition expected to be a string or a command instance, got [object Object] ↓
command() method receives only one string parameter, representing the command's usage (e.g., command('my-command [arg]')). error ReferenceError: require is not defined ↓
import { command } from 'clap'; or import cli from 'clap';. error TypeError: cli.command is not a function ↓
import { command } from 'clap'; if command is a named export, or import cli from 'clap'; then access via cli.command(...) if it's a method on the default export. Warnings
breaking Clap.js converted to pure ESM (ECMAScript Modules) since v3.0.0. While CommonJS is supported via dual module, direct CommonJS `require()` statements might behave differently or require updates to import paths. Node.js version requirements also changed to `^12.20.0`, `^14.13.0`, and `>=15.0.0`. ↓
breaking The `command()` function's signature changed in v3.1.0, removing all parameters except the first (`usage`). Earlier v3.0.0-beta.1 also changed `Command`'s constructor and `Command#command(method)` to take `usage` only (e.g., `command('name [param]')` instead of `command('name', '[param]')`). Passing additional parameters will now throw an error. ↓
breaking Support for Node.js versions older than 8 was dropped in v2.0.0. Additionally, the `create()` method was renamed in v2.0.0 (though the current API uses `command()`). ↓
gotcha When defining options with optional arguments, ensure proper usage syntax, e.g., `--bar [bar]`. Misconfigured option definitions can lead to unexpected parsing behavior or incorrect value assignment, especially when using `normalize` functions. ↓
Install
npm install clap yarn add clap pnpm add clap Imports
- command wrong
const { command } = require('clap'); // In ESM context, use importcorrectimport { command } from 'clap'; - clap wrong
import { clap } from 'clap';correctimport clap from 'clap'; // or const cli = require('clap'); - Command wrong
const Command = require('clap').Command;correctimport { Command } from 'clap';
Quickstart
import { command } from 'clap';
const myCommand = command('my-command [optional-arg]')
.description('An example CLI command with various options and sub-commands.')
.version('1.2.3')
.option('-b, --bool', 'A boolean option that can be toggled.')
.option('--foo <foo>', 'An option that requires an argument.')
.option('--bar [bar]', 'An option that can optionally take an argument.')
.option('--baz [value]', 'An option with an optional argument and a normalize function.',
value => Number(value) || 0,
123 // 123 is default if no value provided
)
.action(function({ options, args, literalArgs }) {
console.log('Command executed!');
console.log('Options:', options);
console.log('Arguments:', args);
console.log('Literal Args (after --):', literalArgs);
if (options.bool) {
console.log('Boolean option --bool was enabled.');
}
});
// Define a sub-command
myCommand
.command('nested <name>')
.description('A nested sub-command demonstrating hierarchy.')
.option('-q, --quz', 'A parameter specific to the nested command.', 'Default value for quz')
.action(({ args, options }) => {
console.log(`Executing nested command for ${args.name}`);
console.log('Nested options:', options);
})
.end(); // Go back to the parent command context
// Simulate running with arguments, e.g., process.argv.slice(2)
myCommand.run(['--foo', 'hello', '-b', 'arg1', '--', 'literal1', 'literal2']);
myCommand.run(['nested', 'user-name', '-q']);