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

args-kingdom

v1.0.0

Published

Clean CLI framework with commands, help, and validation - a better yargs

Readme

args-kingdom

Clean CLI framework with full yargs features, but lighter

npm version npm downloads bundle size

A modern, TypeScript-first CLI framework. All the power of yargs, but cleaner and lighter.

Why args-kingdom?

| Feature | args-kingdom | yargs | commander | |---------|-------|-------|-----------| | Bundle size | ~16 KB | 231 KB | 208 KB | | TypeScript-first | Yes | Partial | Partial | | Type inference | Full | Limited | Limited | | Zero deps | Yes | No | No |

Full Feature Parity with yargs

| Feature | args-kingdom | yargs | |---------|-------|-------| | Subcommands | Yes | Yes | | Positional args <required> [optional] | Yes | Yes | | Auto help (--help) | Yes | Yes | | Version (-V) | Yes | Yes | | Aliases (-p for --port) | Yes | Yes | | Boolean negation (--no-verbose) | Yes | Yes | | Array options (--file a --file b) | Yes | Yes | | Count options (-vvv = 3) | Yes | Yes | | Validation (required, choices) | Yes | Yes | | Conflicts & Implies | Yes | Yes | | Coerce functions | Yes | Yes | | Middleware | Yes | Yes | | Environment variables | Yes | Yes | | Config file loading | Yes | Yes | | Default command | Yes | Yes | | Demand command | Yes | Yes | | Strict mode | Yes | Yes | | Fail handler | Yes | Yes | | Examples in help | Yes | Yes | | Option groups | Yes | Yes | | Epilog | Yes | Yes |

Install

npm install args-kingdom

Quick Start

import { cli } from 'args-kingdom';

cli('myapp', '1.0.0')
  .env('MYAPP')  // Load MYAPP_PORT from env
  .command('serve', 'Start the server')
    .positional('<port>', { desc: 'Port number' })
    .option('host', { alias: 'h', type: 'string', default: 'localhost' })
    .option('verbose', { alias: 'v', type: 'count', desc: 'Verbosity level' })
    .example('myapp serve 3000', 'Start on port 3000')
    .example('myapp serve 8080 -vvv', 'Start with max verbosity')
    .action((args) => {
      console.log(`Server on ${args.host}:${args.port} (verbosity: ${args.verbose})`);
    })
  .run();
$ myapp serve 3000 -vvv
Server on localhost:3000 (verbosity: 3)

$ MYAPP_HOST=0.0.0.0 myapp serve 8080
Server on 0.0.0.0:8080 (verbosity: 0)

API Reference

Creating a CLI

import { cli } from 'args-kingdom';

const app = cli('myapp', '1.0.0');

Options

.option('name', {
  alias: 'n',              // Short flag (-n) or array ['-n', '--nm']
  type: 'string',          // 'string' | 'number' | 'boolean' | 'array' | 'count'
  default: 'world',        // Default value
  desc: 'Your name',       // Description for help
  required: true,          // Make it required
  choices: ['a', 'b'],     // Limit valid values
  conflicts: 'other',      // Can't use with --other
  implies: 'required',     // Requires --required to be set
  coerce: (v) => v.trim(), // Transform the value
  env: 'MY_NAME',          // Load from environment variable
  group: 'User Options:'   // Group in help output
})

Option Types

// String (default)
.option('name', { type: 'string' })
// --name hello → 'hello'

// Number
.option('port', { type: 'number', default: 3000 })
// --port 8080 → 8080

// Boolean
.option('verbose', { type: 'boolean' })
// --verbose → true, --no-verbose → false

// Array (multiple values)
.option('files', { type: 'array' })
// --files a.txt --files b.txt → ['a.txt', 'b.txt']

// Count (count occurrences)
.option('verbose', { alias: 'v', type: 'count' })
// -v → 1, -vvv → 3

Positional Arguments

.command('copy', 'Copy files')
  .positional('<source>', { desc: 'Source file' })        // Required
  .positional('[dest]', { desc: 'Destination', default: '.' }) // Optional
  .action((args) => {
    console.log(`Copying ${args.source} to ${args.dest}`);
  })

// $ myapp copy file.txt /tmp
// args.source = 'file.txt'
// args.dest = '/tmp'

Subcommands

cli('git')
  .command('remote', 'Manage remotes')
    .command('add', 'Add a remote')
      .positional('<name>')
      .positional('<url>')
      .action((args) => { /* ... */ })
  .run();

// $ git remote add origin https://github.com/...

Default Command

cli('myapp')
  .command('serve', 'Start server')
    .default()  // Runs when no command specified
    .option('port', { type: 'number', default: 3000 })
    .action((args) => console.log(`Port: ${args.port}`))
  .run();

// $ myapp --port 8080
// Port: 8080

Middleware

.command('deploy', 'Deploy app')
  .middleware(async (args) => {
    // Add computed properties
    return { ...args, timestamp: Date.now() };
  })
  .middleware((args) => {
    // Auth check
    if (!process.env.API_KEY) throw new Error('API_KEY required');
  })
  .action((args) => {
    console.log(`Deploying at ${args.timestamp}`);
  })

Environment Variables

cli('myapp')
  .env('MYAPP')  // Prefix for all options
  .command('serve', 'Start server')
    .option('port', { type: 'number' })      // MYAPP_PORT
    .option('host', { type: 'string' })      // MYAPP_HOST
    .option('apiKey', { env: 'API_KEY' })    // Custom env name
    .action((args) => { /* ... */ })
  .run();

// $ MYAPP_PORT=8080 myapp serve

Config File

cli('myapp')
  .configFile('./myapp.config.json')
  .command('build', 'Build project')
    .option('outDir', { type: 'string' })
    .action((args) => { /* ... */ })
  .run();

Validation

// Conflicts - can't use together
.option('json', { type: 'boolean', conflicts: 'verbose' })
.option('verbose', { type: 'boolean' })
// Error: Options --json and --verbose cannot be used together

// Implies - requires another option
.option('cache', { type: 'boolean', implies: 'output' })
.option('output', { type: 'string' })
// Error: Option --cache requires --output

// Choices
.option('env', { type: 'string', choices: ['dev', 'prod'] })
// Error: Invalid value for --env: "staging". Choices: dev, prod

Coerce (Transform Values)

.option('date', {
  type: 'string',
  coerce: (v) => new Date(v)
})
// --date 2024-01-01 → Date object

.option('json', {
  type: 'string',
  coerce: JSON.parse
})
// --json '{"a":1}' → { a: 1 }

Strict Mode

cli('myapp')
  .strict()  // Error on unknown options
  .command('test', 'Run tests')
    .action(() => {})
  .run();

// $ myapp test --unknown
// Error: Unknown option: --unknown

Demand Command

cli('myapp')
  .demandCommand(1, 'Please specify a command')
  .command('serve', 'Start server')
  .command('build', 'Build project')
  .run();

// $ myapp
// Error: Please specify a command

Fail Handler

cli('myapp')
  .fail((msg, err) => {
    console.error(`Error: ${msg}`);
    process.exit(1);
  })
  .command('deploy', 'Deploy')
    .option('env', { required: true })
    .action(() => {})
  .run();

Help Customization

.command('serve', 'Start the server')
  .option('port', { type: 'number', desc: 'Port number' })
  .option('host', { type: 'string', desc: 'Host to bind' })
  .option('ssl', { type: 'boolean', desc: 'Enable SSL' })
  .group(['port', 'host'], 'Server Options:')
  .group(['ssl'], 'Security Options:')
  .example('myapp serve --port 3000', 'Start on port 3000')
  .example('myapp serve --ssl', 'Start with SSL')
  .epilog('For more info, visit https://example.com')

Output:

Usage: myapp serve [options]

Start the server

Server Options:
  --port <number>  Port number
  --host <string>  Host to bind

Security Options:
  --ssl            Enable SSL

Options:
  -h, --help       Show help

Examples:
  $ myapp serve --port 3000
    Start on port 3000
  $ myapp serve --ssl
    Start with SSL

For more info, visit https://example.com

Simple Parsing

For scripts that don't need commands:

import { parse } from 'args-kingdom';

const args = parse({
  port: { type: 'number', default: 3000 },
  verbose: { alias: 'v', type: 'count' },
  files: { type: 'array' }
});

// $ node script.js --port 8080 -vvv --files a.txt --files b.txt
args.port    // 8080
args.verbose // 3
args.files   // ['a.txt', 'b.txt']

Comparison with yargs

args-kingdom

import { cli } from 'args-kingdom';

cli('myapp', '1.0.0')
  .env('MYAPP')
  .command('serve', 'Start server')
    .positional('<port>')
    .option('host', { alias: 'h', default: 'localhost' })
    .option('verbose', { alias: 'v', type: 'count' })
    .action((args) => console.log(`${args.host}:${args.port}`))
  .run();

yargs

import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';

yargs(hideBin(process.argv))
  .env('MYAPP')
  .command('serve <port>', 'Start server', (yargs) => {
    return yargs
      .positional('port', { type: 'number' })
      .option('host', { alias: 'h', default: 'localhost' })
      .option('verbose', { alias: 'v', type: 'count' })
  }, (argv) => {
    console.log(`${argv.host}:${argv.port}`)
  })
  .parse();

Support

Buy Me A Coffee GitHub Sponsors

License

MIT