Easy CLI with NodeJS
What is a CLI?
To start with some definition, CLI stands for command-line interface.
This is what you use every day with git
, curl
or other common commands, they are all CLI tools. They are running through what is commonly called a terminal, or a shell.
If you are not too familiar with "building CLI" or even the terminal, it might look like a black box for you. You might even think: "No way I'm going to learn bash, or whatever it is called, to build these tools".
The good news is: you do not need bash
to build a CLI tool! Even though I like bash.
You can build CLI tools with a lot of different languages, like: go
, python
, C++
and even... javascript
! NodeJS is great to build CLI tools.
All the following commands will be executed in a Unix Shell (bash).
Here is my favourite NodeJS CLI, type the following in your terminal:
npm install -g cowsay
cowsay "I'm running in NodeJS"
Which will output:
_______________________
< I'm running in NodeJS >
-----------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
A little trick, you can also run it without installing it, using npx:
npx cowsay "I'm running in NodeJS"
Get started building a CLI
To create a CLI with NodeJS, there are a few pieces to put together.
Execute a node script
The first part is the be able to execute a node script.
A common way
- Create a file
- Write some content
- Execute it with NodeJS
touch my-script.js
echo 'console.log("Hello");' > my-script.js
node my-script.js
A more elegant way
- create a file
- Tell the shell in which environment it should run the script (shebang)
- Make the file executable with chmod
- Execute the file without specifying NodeJS
touch my-script.js
echo '#!/usr/bin/env node' > my-script.js
echo 'console.log("Hello");' >> my-script.js
chmod +x my-script.js
./my-script.js
You can see the same type of file in the cowsay
repo: cli.js.
Execute the script as a binary
The second part is to transform this script into a command line.
There is an easy way to do that by adding the script to a bin
property of a package.json
:
{
"bin": {
"my-cli": "./my-script.js"
There is a little bit of magic around this: when this package gets installed, npm
will create symlinks for the scripts in a bin
folder so that your shell can find the "binaries".
For example, when you install cowsay
, the terminal outputs:
/usr/local/bin/cowthink -> /usr/local/lib/node_modules/cowsay/cli.js
/usr/local/bin/cowsay -> /usr/local/lib/node_modules/cowsay/cli.js
+ cowsay@1.5.0
added 41 packages from 10 contributors in 3.028s
These are the symlinks created and they are now ready to use in your terminal.
A little trick for local development, in the folder where the package.json
is located, you can simply run:
npm link
This command will also create the symlinks needed. They can be removed with:
npm unlink
Create a compliant CLI
Now you can execute a CLI you made yourself, you can simply write some NodeJS code. You create and modify some files, parse some JSON files, make some asynchronous requests to an API like Github, upload some files to an AWS S3, and so on.
You can now build your own tools, make them do what you need, and execute them easily.
What might seem less easy to do, is to write a proper Unix CLI like others would expect, like:
my-cli -v
my-cli --version
my-cli --help
my-cli do-something
my-cli do-something --some-option
You need to think about writing help output, version output, subcommands, options that can be chained, with short name options, and so on. And of course in a format that would make all your heavy Unix CLI users happy.
Here is a guideline: clig.dev.
Fortunately, some packages provide really good boilerplates for your CLI tools, for example, commander.
Some npm
packages will help you to make your CLI pretty and readable with some colours like chalk, while others will help you display complicated tables easily: cli-table3.
Distribution and usage
To distribute your CLI, you can simply publish your package to the npm
registry. This is will make it available to everyone, don't forget to write some tests and some thorough documentation!
In terms of usage, you can simply install it:
npm install -g my-cli
Another scenario is if you do not want to publish the npm
package because you want to keep the CLI in a private repo, you can simply clone your repo and execute the following:
npm install
npm link
It is also possible to execute the command without installing it before, for example on a CI, by using npx
and targeting the package:
npx -p my-npm-package my-cli --help