Awesome Open Source
Awesome Open Source


cli IO utilities

Version CircleCI Appveyor CI Known Vulnerabilities Downloads/week License


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?')


const {cli} = require('cli-ux')

cli.prompt('What is your name?')


Prompt for user input.

// just prompt for input
await cli.prompt('What is your name?')

// mask input after enter is pressed
await cli.prompt('What is your two-factor token?', {type: 'mask'})

// mask input on keypress (before enter is pressed)
await cli.prompt('What is your password?', {type: 'hide'})

// yes/no confirmation
await cli.confirm('Continue?')

// "press any key to continue"
await cli.anykey()

prompt demo

cli.url(text, uri)

Create a hyperlink (if supported in the terminal)

await cli.url('sometext', '')
// shows sometext as a hyperlink in supported terminals
// shows in unsupported terminals

url demo

Open a url in the browser



Shows a spinner

// start the spinner
cli.action.start('starting a process')
// show on stdout instead of stderr
cli.action.start('starting a process', 'initializing', {stdout: true})

// stop the spinner
cli.action.stop() // shows 'starting a process... done'
cli.action.stop('custom message') // shows 'starting a process... 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.

action demo


Shows an iterm annotation

cli.annotation('sometext', 'annotated with this text')

annotation demo


Waits for 1 second or given milliseconds

await cli.wait()
await cli.wait(3000)


Displays tabular data

cli.table(data, columns, options)


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-separated)'}),
  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 allow/block those flags from the returned object.

Table.Columns defines the table columns and their display options.

const columns: Table.Columns = {
  // where `.name` is a property of a data object
  name: {}, // "Name" inferred as the column header
  id: {
    header: 'ID', // override column header
    minWidth: '10', // column must display at this width or greater
    extended: true, // only display this column when the --extended flag is present
    get: row => `US-O1-${}`, // custom getter for data row object

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, // custom logger
  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 = {

  async run() {
    const {flags} = this.parse(Users)
    const {data: users} = await axios.get('')

    cli.table(users, {
      name: {
        minWidth: 7,
      company: {
        get: row => &&
      id: {
        header: 'ID',
        extended: true
    }, {
      printLine: this.log,
      ...flags, // parsed flags


$ example-cli users
Name                     Company
Leanne Graham            Romaguera-Crona
Ervin Howell             Deckow-Crist
Clementine Bauch         Romaguera-Jacobson
Patricia Lebsack         Robel-Corkery
Chelsey Dietrich         Keebler LLC
Mrs. Dennis Schulist     Considine-Lockman
Kurtis Weissnat          Johns Group
Nicholas Runolfsdottir V Abernathy Group
Glenna Reichert          Yost and Sons
Clementina DuBuque       Hoeger LLC

$ example-cli users --extended
Name                     Company            ID
Leanne Graham            Romaguera-Crona    1
Ervin Howell             Deckow-Crist       2
Clementine Bauch         Romaguera-Jacobson 3
Patricia Lebsack         Robel-Corkery      4
Chelsey Dietrich         Keebler LLC        5
Mrs. Dennis Schulist     Considine-Lockman  6
Kurtis Weissnat          Johns Group        7
Nicholas Runolfsdottir V Abernathy Group    8
Glenna Reichert          Yost and Sons      9
Clementina DuBuque       Hoeger LLC         10

$ example-cli users --columns=name
Leanne Graham
Ervin Howell
Clementine Bauch
Patricia Lebsack
Chelsey Dietrich
Mrs. Dennis Schulist
Kurtis Weissnat
Nicholas Runolfsdottir V
Glenna Reichert
Clementina DuBuque

$ example-cli users --filter="company=Group"
Name                     Company
Kurtis Weissnat          Johns Group
Nicholas Runolfsdottir V Abernathy Group

$ example-cli users --sort=company
Name                     Company
Nicholas Runolfsdottir V Abernathy Group
Mrs. Dennis Schulist     Considine-Lockman
Ervin Howell             Deckow-Crist
Clementina DuBuque       Hoeger LLC
Kurtis Weissnat          Johns Group
Chelsey Dietrich         Keebler LLC
Patricia Lebsack         Robel-Corkery
Leanne Graham            Romaguera-Crona
Clementine Bauch         Romaguera-Jacobson
Glenna Reichert          Yost and Sons


Generate a tree and display it

let tree = cli.tree()

let subtree = cli.tree()
subtree.insert('qux')'baz', subtree)



├─ foo
└─ bar
   └─ baz
      └─ qux


Generate a customizable progress bar and display it

const simpleBar = cli.progress()

const customBar = cli.progress({
                   format: 'PROGRESS | {bar} | {value}/{total} Files',
                   barCompleteChar: '\u2588',
                   barIncompleteChar: '\u2591',


progress [=====================-------------------] 53% | ETA: 1s | 53/100
PROGRESS | █████████████████████████████░░░░░░░░░░░ | 146/204 Files

To see a more detailed example, run

$ ts-node examples/progress.ts

This extends cli-progress see all of the options and customizations there, which can be passed in with the options object. Only the single bar variant of cli-progress is currently supported.

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
Typescript (305,149
Command Line (131,872
Progress (7,585
Flags (4,276
Spinner (1,557