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

@ismail-elkorchi/cli-core

v0.2.0

Published

Parser-independent command routing, help, completion, and dispatch primitives.

Readme

@ismail-elkorchi/cli-core

Build reusable, typed command systems for argv parsers, graphical interfaces, HTTP endpoints, tests, and other invocation sources.

cli-core compiles immutable command trees, routes scanner-classified command tokens, validates decoded invocations, binds positional values, produces help and completion data, and dispatches command-specific handlers. Its explicit scanner and binder boundary lets each integration choose its own flag grammar.

Clivoke combines cli-core with argv-flags and adds process and shell integration. Its README lists the available installation methods and end-to-end adapters.

Install

npm install @ismail-elkorchi/cli-core
deno add jsr:@ismail-elkorchi/cli-core

Quick start

Define the command tree once, then use it from structured adapters, help, completion, and dispatch:

import {
  createCliHelp,
  createCliInvocation,
  defineCli,
  dispatchCli,
} from "@ismail-elkorchi/cli-core";

const program = defineCli({
  name: "ship",
  invokable: false,
  options: [
    { name: "verbose", kind: "boolean", flags: ["-v", "--verbose"] },
  ],
  commands: [{
    name: "deploy",
    aliases: ["d"],
    description: "Deploy one service.",
    options: [{
      name: "region",
      kind: "value",
      flags: ["--region"],
      valueMode: "required",
      required: true,
      valueCandidates: ["eu", "us"],
    }],
    positionals: [{ name: "service" }],
  }],
});

const help = createCliHelp(program, ["deploy"]);
if (help === undefined) throw new Error("deploy help is unavailable");

const invocation = createCliInvocation(program, {
  sourceId: "deployment-api",
  commandPath: ["deploy"],
  optionValues: { region: "eu" },
  specifiedOptions: { verbose: false, region: true },
  positionalValues: { service: "billing" },
});

if (invocation.status === "invalid") {
  throw new Error(invocation.diagnostics.map(({ message }) => message).join("\n"));
}

await dispatchCli(invocation, {
  "ship deploy": ({ invocation: deploy }) => ({
    service: deploy.positionalValues.service,
    region: deploy.optionValues.region,
  }),
}, undefined);

Definitions are closed in TypeScript and at runtime. defineCli() returns an immutable CliProgram or throws one CliDefinitionError containing all definition issues found in the tree.

Command model

Options declared on the root are global. Options declared on a command are inherited by its descendants, preserving where each option originated for help and completion.

Every command has a stable canonical key such as ship deploy. Set invokable: false on a grouping command that requires a child command. Each command chooses child-command routing or positional binding, keeping command tokens unambiguous.

The root and child commands share the same positional and passthrough model. This supports shapes such as formatter <file>, archive <inputs...>, and runner -- node app.js directly. Set acceptsPassthroughArguments: true when post--- tokens belong to the selected command.

Option definitions contain parser-neutral facts used by routing and presentation: flag spellings, value mode, requiredness, repetition, multiplicity, defaults, false flags, finite value candidates, and descriptive labels. Integrations remain responsible for decoding option values.

Connect an option grammar

createCliInvocationParser() accepts a CliOptionBinder with two operations:

  • scan() classifies recognized option spans, ordinary arguments, unknown flags, and -- without decoding values.
  • bind() performs the final option parse after command tokens are removed.

Both operations receive the options visible to the current command, the argv elements being classified, and an argvIndexes map back to the complete input. Core validates that scanning is an ordered, exclusive partition and that final binding agrees about specified options, positionals, unknown flags, and post-terminator arguments.

Place command-local flags after the command that declares them. Ancestor flags may appear around descendant command tokens because descendants inherit those options. An unknown flag before a child command stops routing so its following token is never guessed to be a command or value.

Use createCliInvocation() when an adapter already has decoded option and positional values. The returned invocation records a structured source and can carry an application-defined sourceId.

Results and diagnostics

A ready invocation exposes:

  • commandKey as the command-specific discriminant;
  • the compiled command;
  • decoded option and positional values;
  • explicit option-presence information;
  • used aliases and deprecation warnings;
  • passthrough arguments and collected unknown flags;
  • an argv or structured source.

Literal definitions produce a union for every invokable command, so handlers receive the exact command key they implement. CliHandlers requires every invokable key. Invalid results contain structured diagnostics and unknown flags without partial values.

Core diagnostics are discriminated by source and code. Option integrations can create immutable option diagnostics with createCliOptionDiagnostic().

Help, completion, and dispatch

createCliHelp() returns renderer-neutral usage, command, alias, positional, and option data. completeCli() returns command, alias, flag, and finite option-value candidates. Both return undefined for an unknown canonical command path.

dispatchCli() sends a ready invocation to its canonical handler and returns the handler result. Handler errors propagate to the integration that owns application error policy.

Runtime support

  • ESM
  • Node.js 24 or later
  • Deno 2.6 or later
  • Bun 1.3 or later
  • Zero runtime dependencies

License

MIT