npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

super-commander

v0.4.1

Published

A fluent, deferred-registration wrapper around Commander.

Readme

super-commander

npm version license

A fluent, deferred-registration wrapper around Commander. Register subcommands and global options in any order.

Installation

npm install super-commander

Requires Node.js >= 22.12.0.

Quick start

import { SuperCommander } from 'super-commander';

const cli = new SuperCommander('myapp', (cmd) => cmd.description('My awesome CLI').version('1.0.0'));

// Register a global option
cli.addOption('--verbose', 'Enable verbose output');

// Add a subcommand with Commander Command
cli.addSubCommand('upload', (cmd) =>
    cmd
        .description('Upload a file')
        .argument('<file>')
        .action((file) => console.log('Uploading:', file))
);

// Add a subcommand with its own options using SuperCommander
cli.addSuperSubCommand('download', (superCmd) => {
    superCmd.withCommand((cmd) =>
        cmd
            .description('Download a file')
            .argument('<url>')
            .action((url) => console.log('Downloading:', url))
    );
    superCmd.addOption('--connection <number>', 'Number of download connections');
});

cli.parse();

Why super-commander?

Plain Commander requires you to register options and subcommands in a specific order on a single Command instance. This gets awkward when different modules own different parts of the CLI; you end up passing the command around or carefully sequencing initialization.

super-commander solves this with a builder that defers all registration until you call .parse(). Each module gets the same SuperCommander instance and adds its own options and subcommands whenever it's ready. Order doesn't matter, and duplicates are caught early with clear error messages.

// auth.ts -- registers itself, no coordination needed
export function registerAuth(cli: SuperCommander) {
    cli.addSubCommand('login', (cmd) =>
        cmd.description('Sign in').action(() => {
            /* ... */
        })
    );
    cli.addSubCommand('logout', (cmd) =>
        cmd.description('Sign out').action(() => {
            /* ... */
        })
    );
}

// main.ts
import { SuperCommander } from 'super-commander';
import { registerAuth } from './auth.js';

const cli = new SuperCommander('myapp');
registerAuth(cli);
cli.parse();

Nested command trees (addSuperSubCommand) let you build deep CLI structures with the same pattern: each subtree manages its own options, subcommands, and help configuration.

API

SuperCommander

new SuperCommander(programName, fn?)

Create a new CLI. programName is the root command name shown in help output. The optional fn receives the underlying Commander Command for setting .description(), .version(), etc.

const cli = new SuperCommander('myapp', (cmd) => cmd.description('My CLI').version('2.0.0'));

.addOption(flags, description?, fn?)

Register a global option on the root command. Throws if an option with the same name is already registered.

// Flags + description
cli.addOption('--verbose', 'Enable verbose output');

// Flags + description + config callback
cli.addOption('--port <number>', 'Port to listen on', (opt) => opt.default(3000).env('PORT'));

// Flags + config callback (skip description)
cli.addOption('--debug', (opt) => opt.default(false));

.addSubCommand(name, fn?)

Register a subcommand. Pass a callback to configure the command (.description(), .argument(), .action(), etc.), or omit it for a bare subcommand. Throws if name is already registered.

// With configuration
cli.addSubCommand('upload', (cmd) => cmd.description('Upload a file').argument('<file>').action(handler));

// Bare subcommand
cli.addSubCommand('status');

.registerSubCommands(...commands)

Register one or more pre-built SuperCommander instances as subcommands of the root command. Throws if any command name is already registered.

Please note that once a subcommand is registered, it can't be modified/mutated.

If you need a more dynamic approach, use addSuperSubCommand() instead.

// Build standalone command trees
const auth = new SuperCommander('auth');
auth.addSubCommand('login', (cmd) => cmd.description('Sign in').action(handler));
auth.addOption('--token <t>', 'Auth token');

const admin = new SuperCommander('admin');
admin.addSubCommand('dashboard', (cmd) => cmd.description('Show dashboard').action(handler));

// Register them all at once
cli.registerSubCommands(auth, admin);

When subcommands are registered this way, the parent's configureGlobalHelp config is propagated to each subtree automatically.

.addSuperSubCommand(subCmd)

Register a SuperSubCommand instance. Throws if a subcommand with the same name is already registered.

.addSuperSubCommand(name, fn)

Register a nested command tree. The callback receives a fresh SuperSubCommand instance, which has all the same registration methods. Use this when a subcommand needs its own subcommands, global options, or help configuration.

cli.addSuperSubCommand('admin', (admin) => {
    admin.withCommand((cmd) => cmd.description('Admin commands'));
    admin.addSubCommand('users', (cmd) =>
        cmd.description('Manage users').action(() => {
            /* ... */
        })
    );
    admin.addSubCommand('roles', (cmd) =>
        cmd.description('Manage roles').action(() => {
            /* ... */
        })
    );
});

.withCommand(fn)

Replace the root Command via a callback. Use for Commander features the wrapper doesn't expose directly (.hook(), .showSuggestionAfterError(), etc.).

cli.withCommand((cmd) => cmd.showSuggestionAfterError(true));

.configureGlobalHelp(config)

Apply HelpConfiguration to the root command and all subcommands at parse time.

cli.configureGlobalHelp({ showGlobalOptions: true });

.getHelpConfiguration()

Returns the current help configuration object set via configureGlobalHelp, or an empty object if none was set.

cli.configureGlobalHelp({ showGlobalOptions: true });
console.log(cli.getHelpConfiguration()); // { showGlobalOptions: true }

.parse(argv?, parseOptions?)

Assemble the full command tree and parse argv synchronously (defaults to process.argv). Returns the parsed root Command.

.parseAsync(argv?, parseOptions?)

Like .parse() but returns Promise<Command>. Use when a command action is async and you need to await it.

.command

Access the underlying root Command. Useful for inspecting the assembled tree after parsing.

.getName()

Returns the program name.

SuperSubCommand

SuperSubCommand extends SuperCommander, so it has all the same methods. Use it when registering a nested command tree via addSuperSubCommand(name, fn), or build one standalone and pass it to addSuperSubCommand(subCmd).

import { SuperSubCommand } from 'super-commander';

const admin = new SuperSubCommand('admin');
admin.addSubCommand('users', (cmd) => cmd.description('Manage users').action(handler));
admin.addOption('--realm <name>', 'Admin realm');

cli.addSuperSubCommand(admin);

Entry points

| Entry | What's included | | --------------------------- | ------------------------------------------------------------------------------------ | | super-commander | SuperCommander, SuperSubCommand, plus Command and Option from Commander | | super-commander/commander | Full Commander re-export (Command, Option, Argument, program, and all types) | | super-commander/ui | ask and clearLine -- terminal I/O utilities |

super-commander/ui

import { ask, clearLine } from 'super-commander/ui';

// Prompt the user
const name = await ask('What is your name? ');

// Password entry (keystrokes are hidden)
const password = await ask('Password: ', { silent: true });

// Prompt that cleans up after itself
const choice = await ask('Pick an option: ', { clear: true });

// Erase the last N lines from the terminal
clearLine(3);

License

ISC