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

@jitl/cli

v0.1.1

Published

Straightforward and typesafe command-line argument parsing with subcommands.

Readme

@jitl/cli

Straightforward and type-safe command-line argument parsing with subcommands.

Example

import { createCLICommand, validate, logger, runThenExitIfMain, runCommand } from '@jitl/cli'

export const command = createCLICommand({
  description: `Say hello`,
  flags: {
    name: {
      description: `What name should we greet?`,
      validate: validate.string(),
    },
    exuberant: {
      description: `Are we excited?`,
      validate: validate.boolean(),
      default: () => false,
    },
  },
  async run({ name, exuberant }) {
    logger.log(`Hello, ${name}. Nice to see you today${exuberant ? '!' : '.'}`)
  },
})

runThenExitIfMain(module, (name, argv) => runCommand(name, command, argv))

Motivation

  1. Type-safe without stuttering. While existing libraries offer typings via @types/... packages, few infer the arguments of the run() function of a command from the parameters.

    The parameters of the run(flags, args, rest) function are completely inferred from the runtime type specification, so your CLI command declarations are succinct and readable.

  2. Library, not a framework. Existing Typescript frameworks like oclif force a specific setup, and contain many layers of abstraction between invocation and your run() function.

    This package offers flexibility through composition, rather than a complex "plug-ins" or "hooks" interface.

  3. Usable conventions. Many command-line frameworks follow typical Unix conventions, which are suitable for experts, but provide a poor user experience for casual CLI users.

    • Prefer long (GNU-style) named flags like --bool | --value given-value. Removes mental burden of argument order, and makes reading your shell history more clear.

      Positional arguments are still available for glob-related use-cases.

    • Prompt users for missing required arguments. Don't kick the user and force them to read the help.

  4. Bike-shedding. There are many command-line frameworks out there. It's easy to be opinionated about the "mistakes" (choices) a CLI framework makes.

    Because this package is short, has a flat dependency graph, and favors composition over hooks/plugins/inheritance, it's easy to replace, wrap, extend, smoosh, and make it your own.

Dependencies

This package only imports its dependencies when they are needed for a specific purpose.

  • chalk: imported when displaying help output. Used to bold text, which has a nice appearance.

  • table: imported when displaying help output. Used to format the table of flags, etc.

  • fs-extra: imported when loading a directory of subcommands. Used to scan a directory for subcommand files. For better performance and type-safety, but also more boilerplate, consider manually constructing a CommandLoaders object.

  • inquirer: imported when a user fails to provide a required argument. Used to interactively prompt the user for the needed value.

In short, this package never imports a dependency on the happy path to run a fully-specified command.

Documentation

For now, you'll need to read the code.

Known Deficiencies

  • Design modifications for the Command interface to allow nesting subcommands easily without custom code. Currently, because we throw if an unknown flag is given, a standard CLI command cannot dispatch to subcommands unless they both share the same flags.

    An elegant design would allow for arbitrary nesting of commands and subcommand loaders.

  • The current validate: Validator<T> interface is not introspectable at runtime, which limits the usefulness and accuracy of help messages for an argument. All we can show to guide the user is the default value.

    A usable system should be able to infer specific syntax based on the type of the flag.

  • Documentation.

    It should be auto-generated from TSDoc comments in the source.

  • Examples for subcommands.

    This should go in the ./examples directory.

  • Tests.

    Ah, tests.