← All tools

Ismail-elkorchi/cli-core

Popularity 65 Updated Development & Build

Command definition and invocation core for TypeScript CLIs: parsing, help output, completions, plugins, and tests.

githubauto-collected

Installation

A directly usable install command is not verified yet. Check the project documentation or releases.

@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,
  examples: [{
    usage: "ship deploy billing --region eu",

}], 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

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.