
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
clibuilder
Advanced tools
A highly customizable command line application builder.
Key highlights:
name and version are now required and not read from package.json.node_modules anymore.yarn PnP and pnpm.keywords are now used for plugin lookup.ESM along with CJS.my-cli cmd1 cmd2 cmd3z)# npm
npm install clibuilder
# yarn
yarn add clibuilder
# pnpm
pnpm install clibuilder
#rush
rush add -p clibuilder
You can use clibuilder to create your command line application in many ways.
The most basic way looks like this:
// Define your app
const app = cli({ name: 'app', version: '1.0.0' })
.default({ run() { /* ...snip... */ }})
// Use your app
app.parse(process.argv)
.catch(e => /* handle error */process.exit(e?.code || 1))
You can add additional named commands and sub-commands:
cli({ ... })
.command({ name: 'hello', run() { this.ui.info('hello world') }})
.command({
name: 'repo',
commands:[
command({ name: 'create', run() { /* ..snip.. */ }})
]
})
Command can have alias:
cli({ ... })
.command({
name: 'search-packages',
alias: ['sp'],
/* ..snip.. */
})
// call as: `my-cli sp`
You can specify arguments:
cli({ ... }).default({
arguments: [
// type defaults to string
{ name: 'name', description: 'your name' }
],
run(args) { this.ui.info(`hello, ${args.name}`) }
})
cli({ ... }).command({
name: 'sum',
arguments: [
// using `zod` to specify number[]
{ name: 'values', description: 'values to add', type: z.array(z.number()) }
],
run(args) {
// inferred as number[]
return args.values.reduce((p, v) => p + v, 0)
}
})
Of course, you can also specify options:
cli({ ... }).default({
options: {
// type defaults to boolean
'no-progress': { description: 'disable progress bar' },
run(args) {
if (args['no-progress']) this.ui.info('disable progress bar')
}
}
})
and you can add option alias too:
cli({ ... }).command({
options: {
project: {
alias: ['p']
}
}
})
You can use z to mark argument and/or options as optional
cli({... }).default({
arguments: [{ name: 'a', description: '', type: z.optional(z.string()) }],
options: {
y: { type: z.optional(z.number()) }
}
})
If you invoke a command expecting a config,
the config will be loaded.
Each command defines their own config.
cli({ ... })
.default({
config: z.object({ presets: z.string() }),
run() {
this.ui.info(`presets: ${this.config.presets}`)
}
})
Config file can be written in JSON, YAML, cjs, or mjs.
Common filename are supported:
.{name}.<cjs|mjs|js|json|yaml|yml>.{name}rc.<cjs|mjs|js|json|yaml|yml>{name}.<cjs|mjs|js|json|yaml|yml>{name}rc.<cjs|mjs|js|json|yaml|yml>You can override the config name too:
cli({ config: 'alt-config.json' })
One of the key features of clibuilder is supporting plugins.
Plugins are defined inside the config:
{
"plugins": ["my-cli-plugin"]
}
clibuilder allows you to build plugins to add commands to your application.
i.e. You can build your application in a distributed fashion.
To create a plugin:
activate(ctx: PluginActivationContext) functionpackage.json to make it searchableimport { command, PluginActivationContext } from 'clibuilder'
// in plugin package
const sing = command({ ... })
const dance = command({ ... })
export function activate({ addCommand }: PluginCli.ActivationContext) {
addCommand({
name: 'miku',
commands: [sing, dance]
})
}
// in plugin's package.json
{
"keywords": ['your-app-plugin', 'vocaloid']
}
The CLI can search for plugins using the keywords values.
testCommand() can be used to test your command:
import { command, testCommand } from 'clibuilder'
test('some test', async () => {
const { result, messages } = await testCommand(command({
name: 'cmd-a',
run() {
this.ui.info('miku')
return 'x'
}
}), 'cmd-a')
expect(result).toBe('x')
expect(messages).toBe('miku')
})
To make your CLI easily executable, you can add shebang to your script:
#!/usr/bin/env node
// your code
FAQs
A CLI building library
The npm package clibuilder receives a total of 433 weekly downloads. As such, clibuilder popularity was classified as not popular.
We found that clibuilder demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.