this list is now archived - look inside https://github.com/sw-yx/brain if you would like an updated list! thank you.
helpful libraries and resources for building Node.js CLIs. Not a list of CLIs.
I put together a 90 minute Egghead.io Course and Workshop on how to put these tools together, if you like video learning. I also make some money if you watch those videos if you want to help :)
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 Guidelines (Guide, Source): An open-source guide to help you write better command-line programs, taking traditional UNIX principles and updating them for the modern day.
The Poetics of CLI Command Names: Command naming anti-patterns and excellent names
CLI State Machines (Gist): My little thoughts on state management
Add a dry run mode for expensive commands like gatsby dry-run
create-react-app
, vue-cli
, and many others. Key feature: pluggability. Vorpal is another framework inspired by Commander and is seeking maintainerswebpack-cli
, mocha
, react-native
, nyc
, and 14,343 other modules.vercel
, ncc
, micro
, serve
, and many others. Key Feature: tinycreate-nuxt-app
and many others.New: see CLUI https://blog.repl.it/clui
Inspiration from other languages - the http://charm.sh/ universe.
For performance logging, you can try process.htime()
instead of console.time()
(altho the latter uses the former under the hood)
Context from Git/CI
Context from filesystem/PATH
which
: Find the first instance of an executable in the PATH.require.resolve
relative('a/b/c', 'a/d') // ../../d
Config validation
**Loading config from json, rc file, etc***
searchPaths
to implement XDG spec compliance.
don't need but nice to know: https://www.npmjs.com/package/read-package-json
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
cat mydata.json | mycli
)Argument Parsing
⚠️ Your framework may come with parsing built in
Input/Stdin/Argument Processing
make sure to also normalize inputted stuff before you compare
path.resolve(str1) === path.resolve(str2)
Command execution
preferLocal: true
stdio: 'inherit'
to pipe stdout/stderr upshell: true
unless absolutely necessaryRemember 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:
Spinners/Loaders
Templating
Temp folders
Files
fs.existsSync(path.resolve/path.join)
http://npm.im/path-existsIcons & Coloring
Note that you may want to offer the option to FORCE_COLOR in CI logging.
PrettyPrinting
there are also react based renderers
Boxing
Tables
Banners
Debug Logging
util.debuglog
does a lot of the same h/t @stefanjudis)You often also find specialized logger tools for each domain, like @dazn/lambda-powertools-logger for AWS Lambda, but at their core they all support the core pattern of Log Levels DEBUG
, INFO
, WARN
and ERROR
.
⚠️ None of these are offline-first. Keen on finding one that respects offline first.
upgrade
command based on git diffsimport { spawn, hasYarn } from 'yarn-or-npm'
// optionalDir for installing?
const prefixFlag = hasYarn() ? '--cwd' : '--prefix'
spawn.sync(['install', prefixFlag, optionalDir], { stdio: 'inherit' })
serve
tmux
like UIgray-matter
remark
New: see CLUI https://blog.repl.it/clui