cli-kit
A command line application toolkit for Node.js.
Features
- Command line parsing
- Support for command hierarchies
- Auto-generated help
- CLI template engine
- External CLI extensions
- Automatic Node.js version enforcement
Installation
npm i cli-kit --save
Usage
import CLI from 'cli-kit';
(async () => {
const { argv, _ } = await new CLI({
options: {
'-f, --force': 'use the force',
'--timeout [value]': {
desc: 'the timeout duration',
type: 'int'
}
}
}).exec();
console.log('options:', argv);
console.log('args:', _);
})();
Architecture
In cli-kit, commands and options are grouped into "contexts". The main CLI instance defines the "global context". Each command defines a new context. Each context can have its own commands, options, and arguments. What you end up with is a hierarchy of contexts.
When cli-kit parses the command line arguments, it will check each argument against the global context to see if the argument can be identified as a known command, option, or argument. If it finds a command, it adds the command's context to a stack and re-parses any unidentified arguments.
This allows you to create deep and dynamic hierarchies of commands, options, and arguments.
API
CLI
class A CLI
intance defines a global context for which you add commands, options, and arguments.
Extends Context
> HookEmitter
.
constuctor(opts)
-
opts
:Object
(optional)Various options to initialize the
CLI
instance.
Example
const cli = new CLI({
// An array of argument definitions. They are parsed in the order they are defined.
args: [
// An argument can be as simple as its name. Wrapping the name with `<` and `>` signifies
// that the argument is required.
'<arg1>',
// To define an optional arguemnt, you can use `[` and `]`.
'[arg2]',
// Or simply omit the brackets
'arg3',
// For more options, you can specify an argument descriptor
{
// The argument name. Follows the same rules as above.
name: 'arg4',
// The argument's description to show in the help output.
desc: undefined,
// When `true`, hides the argument from usage string in the help output.
hidden: false,
// When `true`, captures all subsequent argument values into an array
multiple: false,
// Overrides the brackets and forces the argument to be required or optional.
required: false,
// There are several built-in types. See the "types" section below for more info.
type: 'string'
},
// Adding `...` will capture all subsequent argument values into an array
'arg4...'
],
// Global flag to camel case property names derived from multi-word options/arguments.
// Defaults to true, can be overwritten by the option/argument.
camelCase: true,
// An object of command names to command descriptors.
commands: {
'some-command': {
// The action to perform when the command is parsed.
action({ argv, _ }) {
console.log('options:', argv);
console.log('args:', _);
},
// An array of alternate command names.
aliases: [ 'another-command' ],
// Command specific args. See `args` section above.
args: [],
// When `true`, camel case all option and argument names in the `argv` result.
camelCase: true,
// An object of subcommand names to subcommand descriptors.
commands: {},
// The command description.
desc: undefined,
// When `true`, hides the command from the help output.
hidden: false,
// An object of option formats to option descriptors. See the `options` section below.
options: {},
// The command name to display in the help output. Defaults to the command name.
title: undefined
}
},
// The default command `exec()` should run if no command was found during parsing.
// If `help` is `true` and no default command is specified, it will default to displaying the
// help screen. If you want help, but do not want to default to the help command, then set the
// `defaultCommand` to `null`.
defaultCommand: undefined,
// The CLI description to print on the help screen between the usage and commands/options/args.
desc: undefined,
// Adds the `-h, --help` to the global flags and enables the auto-generated help screen.
// Defaults to `true`.
help: true,
// The exit code to return when the help screen is displayed. This is useful if you want to
// force the program to exit if `--help` is specified and the user is chaining commands together
// or after displaying the help screen and prevent further execution in the CLI's promise chain.
helpExitCode: undefined,
// The name of the program used by the help screen to display the command's usage.
// Defaults to "program".
name: 'program',
// An object of option formats to option descriptors or an array of sorted group names and
// objects of option formats to option descriptors.
options: {
//
},
// The title for the top-level (or "Global") context. This title is displayed on the help screen
// when displaying the list of options.
title: 'Global',
// When set, it will automatically wire up the `-v, --version` option. Upon calling with your
// program with `--version`, it will display the version and exit with a success (zero) exit
// code.
version: null
});
exec(args)
Parses the command line args and executes a command, if found.
-
args
:Array<String>
(optional)An array of arguments. Each argument is expected to be a string.
Defaults to
process.argv.slice(2)
.
Returns a Promise
that resolves an Arguments
object. This object will contain the parsed options
in argv
and arguments in _
.
Example
cli.exec()
.then(({ argv, _ }) => {
console.log('options:', argv);
console.log('args:', _);
});
Context
class Base class for CLI
and Command
classes.
Extends HookEmitter
.
argument(arg)
Adds an argument to a CLI
or Command
.
-
arg
:Argument
,Object
, orString
.An argument descriptor. Either an
Argument
instance or anObject
to pass into aArgument
constructor.An argument requires a
name
.
Returns a reference to the CLI
or Command
.
Example
// define a non-required argument "foo"
cli.argument('foo');
// define a non-required argument "wiz"
cli.argument('[wiz]');
// define a required argument "pow"
cli.argument('<pow>');
cli.argument({
name: 'bar',
type: 'int'
});
cli.argument(new Argument('baz'));
command(cmd, opts)
Adds a command to a CLI
or Command
.
TODO
option(optOrFormat, group, params)
Adds an option or group of options to a CLI
or Command
.
TODO
cli-kit vs other libraries
General | cli-kit | arg | Caporal.js | Commander.js | dashdash | fields | getopts | inquirer | meow | minimist | mri | oclif | prompt | promptly | prompts | yargs |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Latest version | 0.5.4 | 4.1.0 | 1.1.0 | 2.19.0 | 1.14.1 | 0.1.24 | 2.2.3 | 6.2.1 | 5.0.0 | 1.2.0 | 1.1.4 | 1.12.8 | 1.0.0 | 3.0.3 | 2.0.1 | 12.0.5 |
Actively maintained (within last year) | ✅ | ✅ | ✅ | ✅ | Last release Dec 2016 | Last release Jul 2015 | ✅ | ✅ | ✅ | Last release Sep 2015 | ✅ | ✅ | Last release Mar 2016 | ✅ | ✅ | ✅ |
License | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT | MIT |
Language | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | JavaScript | TypeScript | JavaScript | JavaScript | JavaScript | JavaScript |
Async/promise support | ✅ | ❌ | ✅ 1 | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ 1 | ❌ | ✅ | ✅ | ❌ |
Data type coercion | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ |
User-defined input/output stream | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ |
Parsing | cli-kit | arg | Caporal.js | Commander.js | dashdash | fields | getopts | inquirer | meow | minimist | mri | oclif | prompt | promptly | prompts | yargs |
Command | ✅ | ❌ | ✅ | ✅ | ❌ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | ✅ | n/a | n/a | n/a | ✅ |
Command aliases | ✅ | ❌ | ✅ | ✅ | ❌ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | ✅ | n/a | n/a | n/a | ✅ |
Default command | ✅ | ❌ | ❌ | ❌ | ❌ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | ❌ | n/a | n/a | n/a | ✅ |
Subcommands | ✅ | ❌ | ❌ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | n/a | n/a | n/a | ||||
Options | ✅ | ✅ | ✅ | ✅ | ✅ | n/a | ✅ | n/a | ✅ | ✅ | ✅ | ✅ | n/a | n/a | n/a | ✅ |
Options aliases | ✅ | ✅ | ❌ | ❌ | ✅ | n/a | ✅ | n/a | ✅ | ✅ | ✅ | ❌ | n/a | n/a | n/a | ✅ |
Custom option validator | ✅ | ✅ | ✅ | ✅ | ❌ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | ✅ | n/a | n/a | n/a | ❌ 5 |
Flags (true/false) | ✅ | ✅ | ❌ | ✅ | ✅ | n/a | ✅ | n/a | ✅ | ✅ | ✅ | ✅ | n/a | n/a | n/a | ✅ |
Flag negation (--no-<name> ) | ✅ | ❌ | ❌ | ✅ | ❌ | n/a | ❌ | n/a | ✅ | ✅ | ✅ | ✅ | n/a | n/a | n/a | ✅ |
Argument support | ✅ | ✅ | ✅ | ✅ | ✅ | n/a | ✅ | n/a | ✅ | ✅ | ✅ | ✅ | n/a | n/a | n/a | ✅ |
Custom argument validator | ✅ | ❌ | ✅ | ✅ | ❌ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | ✅ | n/a | n/a | n/a | ✅ |
Stop parsing -- | ✅ | ✅ | ✅ | ✅ | ✅ | n/a | ✅ | n/a | ✅ | ✅ | ✅ | ✅ | n/a | n/a | n/a | ✅ |
Default option/argument values | ✅ | ❌ | ✅ | ✅ | ✅ | n/a | ✅ | n/a | ✅ | ✅ | ✅ | ✅ | n/a | n/a | n/a | ✅ |
Environment variable support | ✅ | ❌ | ❌ | ❌ | ✅ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | ✅ | n/a | n/a | n/a | ✅ 6 |
Auto-generated help screen | ✅ | ❌ | ✅ | ✅ | ✅ 7 | n/a | ❌ | n/a | ✅ | ❌ | ❌ | ✅ | n/a | n/a | n/a | ✅ |
Custom help exit code | ✅ | ❌ | ❌ | ❌ | ❌ | n/a | ❌ | n/a | ✅ | ❌ | ❌ | ❌ | n/a | n/a | n/a | ❌ |
Prompting | cli-kit | arg | Caporal.js | Commander.js | dashdash | fields | getopts | inquirer | meow | minimist | mri | oclif | prompt | promptly | prompts | yargs |
Single-line text prompting | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ | n/a | n/a | n/a | ✅ | ✅ | ✅ | ✅ | n/a |
Multi-line text prompting | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ❌ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ❌ | n/a |
Password prompting | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ | n/a | n/a | n/a | ✅ | ✅ | ✅ | ✅ | n/a |
Confirm (yes/no) prompting | ❔ | n/a | n/a | n/a | n/a | ✅ 8 | n/a | ✅ | n/a | n/a | n/a | ✅ | ✅ | ✅ | ✅ | n/a |
Press any key to continue prompting | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ❌ | n/a | n/a | n/a | ✅ | ❌ | ✅ | ❌ | n/a |
Inline list prompting | ❔ | n/a | n/a | n/a | n/a | ✅ 8 | n/a | ✅ 9 | n/a | n/a | n/a | ❌ | ❌ | ❌ | ✅ 10 | n/a |
Numbered select list prompting | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ❌ | n/a |
Scrollable select list prompting | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ✅ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ✅ | n/a |
Multi-select/checkbox list prompting | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ✅ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ✅ | n/a |
File/directory prompting | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ 11 | n/a | n/a | n/a | ❌ | ❌ | ❌ | ❌ | n/a |
Numeric-only prompting | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ❌ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ✅ | n/a |
Date/time prompting | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ✅ 12 | n/a | n/a | n/a | ❌ | ❌ | ❌ | ❌ | n/a |
Multiple prompt chaining | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ✅ | n/a |
External editor support | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ✅ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ❌ | n/a |
Custom value formatter/transformer | ❔ | n/a | n/a | n/a | n/a | ✅ 13 | n/a | ✅ 14 | n/a | n/a | n/a | ❌ | ✅ 15 | ✅ 13 | ✅ | n/a |
Custom validation | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ✅ | n/a | n/a | n/a | ❌ | ✅ | ✅ | ✅ | n/a |
Default prompt values | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ | n/a | n/a | n/a | ✅ | ✅ | ✅ | ✅ | n/a |
Prompt history | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ 16 | n/a | n/a | n/a | ❌ | ✅ | ❌ | ❌ | n/a |
Auto-suggest mismatch | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ 17 | n/a | n/a | n/a | ❌ | ✅ | ❌ | ❌ | n/a |
Autocomplete | ❔ | n/a | n/a | n/a | n/a | ✅ | n/a | ✅ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ✅ | n/a |
Custom prompt types/plugins | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ✅ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ❌ | n/a |
Multiple answers (repeat prompt) | ❔ | n/a | n/a | n/a | n/a | ❌ | n/a | ❌ | n/a | n/a | n/a | ❌ | ❌ | ❌ | ✅ | n/a |
Logging | cli-kit | arg | Caporal.js | Commander.js | dashdash | fields | getopts | inquirer | meow | minimist | mri | oclif | prompt | promptly | prompts | yargs |
Application logging | ✅ | n/a | ✅ 18 | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | ✅ | n/a | n/a | n/a | n/a |
Application debug logging | ✅ 19 | n/a | ❌ | n/a | n/a | n/a | n/a | n/a | ✅ | n/a | ❌ | ❌ | n/a | n/a | n/a | n/a |
Internal debug logging | ✅ 19 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ 20 | ❌ | ❌ | ❌ | ❌ |
Misc | cli-kit | arg | Caporal.js | Commander.js | dashdash | fields | getopts | inquirer | meow | minimist | mri | oclif | prompt | promptly | prompts | yargs |
Dedicated website | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ |
External CLI extensions | ✅ | ❌ | ❌ | ❌ | ❌ | n/a | n/a | n/a | ✅ | ❌ | ❌ | ✅ | n/a | n/a | n/a | ❌ |
Internal hook system | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
Bash completion | ❔ | ❌ | ✅ | ❌ | ✅ | n/a | ❌ | n/a | ❌ | ❌ | ❌ | ❌ | n/a | n/a | n/a | ❌ |
REPL | ❔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Built-in i18n support | ❔ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Project generator CLI | ❔ | ❌ | ❌ | ✅ 21 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ 22 |
Built-in update notifications | ❔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
1. Command actions only. The actually parsing is sync.
2. Requires reparsing with subcommand context or manually subprocessing.
3. Automatically spawns subcommand in new process, otherwise requires reparsing with subcommand context.
4. Subcommands must be prefixed with the parent command and a colon in order to be a valid topic name.
5. Only the last parsed invalid option error is raised.
6. Custom environment variable names are not supported. The names must match a prefixed option name.
7. Options only. (e.g no usage, etc)
8. Via select list input type.
9. Via expand input type.
10. Maximum 2 options via toggle input type.
11. Via inquirer-fuzzy-path plugin.
12. Via inquirer-datepicker-prompt plugin.
13. Via validator callback.
14. Via filter callback.
15. Via before()
callback.
16. Via inquirer-command-prompt plugin.
17. Via inquirer-prompt-suggest plugin.
18. Via winston.
19. Uses snooplogg.
20. Uses debug.
21. Via generator-commander and generator-node-cli-commander Yeoman plugin.
22. Via generator-yargs Yeoman plugin.
✨ If you find any inaccuracies (aside from the version numbers), please feel free to submit a PR.
Who Uses cli-kit?
License
MIT