Skip to content
Branch: master
Find file Copy path
Find file Copy path
9 contributors

Users who have contributed to this file

@sw-yx @Aghassi @anubhavsrivastava @styfle @M0nica @jeroenouw @jamesgeorge007 @dominikwilkowski @bnb
280 lines (196 sloc) 14.3 KB


helpful libraries and resources for building Node.js CLIs. Not a list of CLIs.

CLI Design Thinking

  • 12 Factor CLI Apps (Blogpost, Talk): Jeff Dickey's list of requirements for UX.

  • Heroku CLI Style Guide (Guide, Talk, Talk): Heroku's CLI Style Guide.

  • CLI State Machines (Gist): My little thoughts on state management

  • Add a dry run mode for expensive commands like gatsby dry-run


  • Commander: Built by TJ, used in create-react-app, vue-cli, and many others. Key feature: pluggability. Vorpal is another framework inspired by Commander and is seeking maintainers
  • Oclif: Built by Heroku, used in Heroku and Salesforce CLI's. Key feature: pluggability.
  • Sade: Built by lukeed, used in tsdx. Key feature: lightweight?
  • Gluegun: Built by Infinite Red, used in Ignite and AWS Amplify. Key feature: templating/filesystem
  • Ink: Built by Vadim & Sindre. Key Feature: React Components and Yoga Layout. See also import-jsx
  • Scritch: Built by Jamie, used at Eventbrite. Key Feature: compose multiple scripts regardless of language into one CLI.
  • Yargs: Built by bcoe, used by webpack-cli, mocha, react-native, nyc, and 14,343 other modules.
  • arg: Built by ZEIT, used by now, ncc, micro, serve, and many others. Key Feature: tiny
  • cac: Built by Egoist, used by create-nuxt-app and many others.

Utility Libraries

Performance Optimization

For performance logging, you can try process.htime() instead of console.time() (altho the latter uses the former under the hood)

Update Management/Nagging


Context from Git/CI

Context from filesystem/PATH

Config validation

Loading config from json, rc file, etc*

don't need but nice to know:

Beware the race condition when you check if file exists and then open it. the file could be deleted in betwee. instead, just open the file and handle the error if it doesnt exist.

Loading/Storing config from a persistent store

⚠️ Be aware of the XDG spec. Sindre's libraries use env-paths to get paths compliant with this.


Stdin Parsing

Argument Parsing

⚠️ Your framework may come with parsing built in

Input/Stdin/Argument Processing

make sure to also normalize inputted stuff before you compare


Command execution

Remember Windows users for cross-platform nodejs (Guide). e.g. dont execute pkg.json or shell commands with single quotes instead of escaped double quotes

Sometimes processes can spawn processes. This is troublesome for watch/reload features. Kill them all with tree-kill.

You'll probably also use these in conjunction with port monitors (e.g. the process you're working with opens a port, like CRA for Netlify Dev):

If child_processes are going to be a key part of your CLI, be sure to read the docs and this guide to be aware of the API.

You may also want to poll for conditions to be true to execute async processes:



Temp folders



Icons & Coloring

Note that you may want to offer the option to FORCE_COLOR in CI logging.





Debug Logging

Plugin/Release Management

⚠️ None of these are offline-first. Keen on finding one that respects offline first.

Dependency installs and Upgrading Scaffolds

import { spawn, hasYarn } from 'yarn-or-npm'
// optionalDir for installing?
const prefixFlag = hasYarn() ? '--cwd' : '--prefix'
spawn.sync(['install', prefixFlag, optionalDir], { stdio: 'inherit' })


Other useful lists

Beginner Tutorials

You can’t perform that action at this time.