Skip to content

cli()

function cli(options: cli.Options): cli.Builder

Creates the builder that every clibuilder application starts from.

import { cli } from 'clibuilder'
const app = cli({ name: 'app', version: '1.0.0' })
namespace cli {
type Options = {
name: string
version: string
description?: string
config?: string | boolean
keywords?: string[]
onUsageError?: UsageErrorHandler
}
}
Option Type Description
name string Required. The CLI’s name — used in the help message, as the default config name, and as the default plugin keyword.
version string Required. Printed by --version. Since v8 this is not read from package.json — see Publishing.
description string A short summary shown at the top of the help message.
config string | boolean Opt into a config file. true derives the config name from name; a string overrides it.
keywords string[] Keywords used by the built-in plugins list / plugins search commands. Defaults to [name] when config is set.
onUsageError UsageErrorHandler Takes over how usage errors are reported, for every command that declares no handler of its own. See Reporting usage errors yourself.

Declaring config or keywords also adds the built-in plugins command to the CLI.

type Builder = {
readonly name: string
readonly version: string
readonly description: string
default(command): Omit<this, 'default'> & Executable
command(command): this & Executable
}

Defines the command that runs when no sub-command is named. Takes a command without a name — the CLI’s name is its name.

cli({ name: 'app', version: '1.0.0' }).default({
description: 'do the thing',
run() {
this.ui.info('running')
}
})

Can be called once: default is removed from the returned type afterwards.

Adds a named command. Returns the builder, so calls chain.

cli({ name: 'app', version: '1.0.0' })
.command({ name: 'a', description: 'command a', run() {} })
.command({ name: 'b', description: 'command b', run() {} })

See command() for the full shape.

type Executable = {
parse<R = any>(argv: string[]): Promise<R>
}

Parses the command line, resolves the command, validates its arguments, options, and config, and calls its run(). Resolves to whatever run() returned.

app.parse(process.argv)
.catch(e => process.exit(e?.code || 1))

argv is a full process.argv — the first two entries (the node binary and the script path) are skipped.

parse() does not reject for usage problems. An unknown flag, a missing required argument, a value that fails its schema, or a config that fails validation all cause the help message to be printed and the promise to resolve. Only an error thrown by your own run() rejects.

#!/usr/bin/env node
import { cli, command, z } from 'clibuilder'
cli({
name: 'app',
version: '1.0.0',
description: 'an example CLI',
config: true,
keywords: ['app-plugin']
})
.default({
config: z.object({ presets: z.string() }),
run() {
this.ui.info(`presets: ${this.config.presets}`)
}
})
.command(
command({
name: 'build',
description: 'build the project',
options: { watch: { description: 'rebuild on change', alias: ['w'] } },
run(args) {
this.ui.info(args.watch ? 'watching' : 'building once')
}
})
)
.parse(process.argv)
.catch(e => process.exit(e?.code || 1))