Clap.js CLI Argument Parser

raw JSON →
3.1.1 verified Thu Apr 23 auth: no javascript

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.

error Error: Command definition expected to be a string or a command instance, got [object Object]
cause Attempting to define a command with multiple parameters after v3.0.0-beta.1/v3.1.0 changes.
fix
Ensure the command() method receives only one string parameter, representing the command's usage (e.g., command('my-command [arg]')).
error ReferenceError: require is not defined
cause Using CommonJS `require()` syntax within an ESM module context (e.g., in a `.mjs` file or a file where `type: module` is set in `package.json`).
fix
Migrate your import statements to ESM import { command } from 'clap'; or import cli from 'clap';.
error TypeError: cli.command is not a function
cause Incorrect ESM import, often trying `import { cli } from 'clap';` when `cli` is not a named export but rather a common alias for the default export, or attempting to destructure `command` from a module that exports it as a property of its default export.
fix
For ESM, use 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.
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`.
fix Ensure your project is configured for ESM (e.g., `"type": "module"` in package.json) or use appropriate CommonJS imports. Update Node.js to a supported version.
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.
fix Refactor `command()` calls to only pass the usage string as the first parameter (e.g., `command('my-command [arg1]')`). Ensure no additional parameters are provided.
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()`).
fix Upgrade Node.js to version 8 or higher. If migrating from v1, review method names like `create()` which are no longer part of the public API in current versions.
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.
fix Consult the `.option()` API documentation carefully for the correct usage patterns and argument definitions, particularly for `normalize` and `default` values.
npm install clap
yarn add clap
pnpm add clap

Demonstrates basic CLI setup with options, arguments, version, description, sub-commands, and an action function to process parsed values.

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']);