What is cli-ux?
The cli-ux npm package provides a set of utilities for building command-line interfaces (CLIs). It offers features such as progress bars, spinners, prompts, and table formatting to enhance the user experience of CLI applications.
What are cli-ux's main functionalities?
Progress Bar
This feature allows you to display a progress bar in the terminal. The code sample demonstrates how to create and update a progress bar that increments by 5% every 100 milliseconds until it reaches 100%.
const cli = require('cli-ux');
const progress = cli.progress({ format: 'progress [{bar}] {percentage}% | ETA: {eta}s' });
progress.start(100, 0);
let value = 0;
const interval = setInterval(() => {
value += 5;
progress.update(value);
if (value >= 100) {
clearInterval(interval);
progress.stop();
}
}, 100);
Spinner
This feature provides a spinner to indicate ongoing processes. The code sample shows how to start a spinner with a message and stop it after 3 seconds with a 'done' message.
const cli = require('cli-ux');
cli.action.start('Processing');
setTimeout(() => {
cli.action.stop('done');
}, 3000);
Prompt
This feature allows you to prompt the user for input. The code sample demonstrates how to ask the user for their name and then greet them with the provided input.
const cli = require('cli-ux');
(async () => {
const name = await cli.prompt('What is your name?');
console.log(`Hello, ${name}!`);
})();
Table
This feature allows you to display data in a table format. The code sample shows how to create a table with two columns: 'name' and 'age', and display two rows of data.
const cli = require('cli-ux');
const data = [
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 }
];
cli.table(data, {
name: {
minWidth: 7
},
age: {
header: 'Age'
}
});
Other packages similar to cli-ux
ora
Ora is a lightweight and elegant terminal spinner. It provides similar functionality to the spinner feature in cli-ux but focuses solely on spinners, offering more customization options and better performance.
inquirer
Inquirer is a powerful library for creating interactive command-line prompts. It offers more advanced and flexible prompt types compared to cli-ux, making it a better choice for complex user interactions.
blessed
Blessed is a comprehensive library for building terminal interfaces. It provides a wide range of widgets, including tables, forms, and more, offering greater flexibility and customization than cli-ux.
progress
Progress is a simple and flexible progress bar library for Node.js. It offers similar functionality to the progress bar feature in cli-ux but with a more minimalistic approach and fewer dependencies.
cli-ux
cli IO utilities
Usage
The following assumes you have installed cli-ux
to your project with npm install cli-ux
or yarn add cli-ux
and have it required in your script (TypeScript example):
import cli from 'cli-ux'
cli.prompt('What is your name?')
JavaScript:
const {cli} = require('cli-ux')
cli.prompt('What is your name?')
cli.prompt()
Prompt for user input.
await cli.prompt('What is your name?')
await cli.prompt('What is your two-factor token?', {type: 'mask'})
await cli.prompt('What is your password?', {type: 'hide'})
await cli.confirm('Continue?')
await cli.anykey()
cli.url(text, uri)
Create a hyperlink (if supported in the terminal)
await cli.url('sometext', 'https://google.com')
cli.open
Open a url in the browser
await cli.open('https://oclif.io')
cli.action
Shows a spinner
cli.action.start('starting a process')
cli.action.start('starting a process', {stdout: true})
cli.action.stop()
cli.action.stop('custom message')
This degrades gracefully when not connected to a TTY. It queues up any writes to stdout/stderr so they are displayed above the spinner.
cli.annotation
Shows an iterm annotation
cli.annotation('sometest', 'annotated with this text')
cli.wait
Waits for 1 second or given milliseconds
await cli.wait()
await cli.wait(3000)
cli.table
Displays tabular data
cli.table(data, columns, options)
Where:
cli.table.flags()
returns an object containing all the table flags to include in your command.
{
columns: Flags.string({exclusive: ['additional'], description: 'only show provided columns (comma-seperated)'}),
sort: Flags.string({description: 'property to sort by (prepend '-' for descending)'}),
filter: Flags.string({description: 'filter property by partial string matching, ex: name=foo'}),
csv: Flags.boolean({exclusive: ['no-truncate'], description: 'output is csv format'}),
extended: Flags.boolean({char: 'x', description: 'show extra columns'}),
'no-truncate': Flags.boolean({exclusive: ['csv'], description: 'do not truncate output to fit screen'}),
'no-header': Flags.boolean({exclusive: ['csv'], description: 'hide table header from output'}),
}
Passing {only: ['columns']}
or {except: ['columns']}
as an argument into cli.table.flags()
will whitelist/blacklist those flags from the returned object.
Table.Columns
defines the table columns and their display options.
const columns: Table.Columns = {
name: {},
id: {
header: 'ID',
minWidth: '10',
extended: true,
get: row => `US-O1-${row.id}`,
},
}
Table.Options
defines the table options, most of which are the parsed flags from the user for display customization, all of which are optional.
const options: Table.Options = {
printLine: myLogger,
columns: flags.columns,
sort: flags.sort,
filter: flags.filter,
csv: flags.csv,
extended: flags.extended,
'no-truncate': flags['no-truncate]',
'no-header': flags['no-header]',
}
Example class:
import {Command} from '@oclif/command'
import {cli} from 'cli-ux'
import axios from 'axios'
export default class Users extends Command {
static flags = {
...cli.table.flags()
}
async run() {
const {flags} = this.parse(Users)
const {data: users} = await axios.get('https://jsonplaceholder.typicode.com/users')
cli.table(users, {
name: {
minWidth: 7,
},
company: {
get: row => row.company && row.company.name
},
id: {
header: 'ID',
extended: true
}
}, {
printLine: this.log,
...flags,
})
}
}
Displays:
$ example-cli users
Name Team
Jordan Sales
Jamie Engineering
$ example-cli users --extended
Name Team ID
Jordan Sales 100
Jamie Engineering 200
$ example-cli users --columns=name
Name
Jordan
Jamie
$ example-cli users --filter="team=sales"
Name Team ID
Jordan Sales 100
$ example-cli users --sort=team
Name Team ID
Jamie Engineering 200
Jordan Sales 100
cli.tree
Generate a tree and display it
let tree = cli.tree()
tree.insert('foo')
tree.insert('bar')
let subtree = cli.tree()
subtree.insert('qux')
tree.nodes.bar.insert('baz', subtree)
tree.display()
Outputs:
├─ foo
└─ bar
└─ baz
└─ qux