The jib Command Line Framework

This project is meant to serve as a lightweight, reusable, TypeScript first CLI framework for projects with any level of CLI command functionality.

Why 'jib'

OK, so there's actually some method to the madness... The @jib/cli was inspired by the extremely popular Commander.js CLI development framework. In sailing, the jib is an essential component to commanding a ship - thus the name.

| jib |: A triangular staysail set forward of the forwardmost mast.

While it's not a dependency, this package was also somewhat influenced by Heroku's @oclif/command - namely that it's designed to be highly performant for large CLI applications. Other similiarities are:

NOTE: because of certain nuances in local development enviromments, it is best to use a static file as the bin, rather than a file emitted by TypeScript. Generally it's a good idea to ensure this file has executable permissions (ie chmod +x bin/jib in the example above).

Configure the new CLI({ /* options */ }) for your implementation:

Option

Description

Default

Required

baseDir

Used to specify an alternate project directory. ⚠️ Unlikely to be necessary - approach with caution

'.'

commandDelim

Use a custom delimiter for subcommands. Must have length === 1

' '

commandDir

Directory where command implementations are stored. This should be the transpiled output directory, such as "build/commands"

null

✅

rootCommand

Run a single command implementation when arguments don't resolve as subcommands. For example, create a main.ts implementation and specify rootCommand: "main"

Value processing function, especially useful for accepting multiple values with a single flag

null

Option Flag Syntax

Each flag may be written in the format [-{short}, ]--{name}[ [value]|<value>]. Some examples:

-c, --cheese <type> requires "type" in cheese option

-p, --project [path] "path" is optional for the project option

-d, --debug simple boolean option

--test a longhand only flag

Short boolean flags may be passed as a single argument, such as -abc. Multi-word arguments like --with-token become camelCase, as options.withToken. Also note that multi-word arguments with --no prefix will result in false as the option name value. So --no-output would parse as options.output === false.

Naturally it is the job of each command implementation to do whatever magic it must do according to its user's wishes. Hmm... sort of like a genie. All the program needs is for this method to return a Promise.

As is shown in the call signature above, the first argument will be the resolved options as defined in the decorator. Note that each property key will be defined as the long, camelCased option name (unless using the --no prefix as mentioned).

Then, all resolved args will be passed in the order which they are defined, again by using the decorator. Note that if an argument is declared as multi: true, then its value will be the final argument, and of type string[].

Plugins

Support for plugins is in it's early stages. Once stable, more information will be added here. Stay tuned...

TypeScript

This project is designed to embody the many benefits of using TypeScript, and recommends that users do the same. While vanilla JS is technically possible, it is not officially supported at this time.

TODOs

[x] Add support for single, named, command - this is configured as "rootCommand"

[ ] Enable command ordering with ICommand.priority annotation

[ ] Support command group with file implementation (descriptor) & directory of same name