Setting up your Node package to be run from the command-line

I've got my Node package built, now how do I run it as a CLI tool?

Have you ever used Node packages like knex, aws-cli, or mocha and wondered how they are able to be run from the command-line?

Something like:

$ my-awesome-tool -v

A lot of people think of Node apps as libraries that you include in your code... or Node REST API's that live on the server. But the ability to build CLI's is sometimes overlooked.

Or maybe you are aware of the CLI ability, but you're trying to do that and hitting some dreaded package.json issues...

In this post we'll go over - from the ground up - how to take your Node package and set it up so that anyone can run it as a fancy CLI program.

Once you've got the hang of it, I think you'll understand the whole new world that Node packages as CLI's unlocks... you can build sweet, slick tools that save you lots of time, impress your team and make their lives easier, and help users of your library more easily use it.

First step - add a CLI script file

Whether you're starting from scratch or already have a package you want to CLI-ify, you need to add a CLI script and set its execution context.

I like to call my CLI scripts cli.js, and I usually put them in the root directory, just as a convention. You of course can name it however you want and put it wherever you want. Just make sure it's a .js file, as it will still be a Node/JS file.

At the top of the file, add the following:

#!/usr/bin/env node

Basically, when you run this package from the command line, this tells your shell to use the Node execution context, so that it will actually run as a normal Node program.

Second step - package.json

The next step is defining in your package.json where the CLI script is located and what the CLI command should be to invoke your package.

In your package.json add the following:

"bin": {
  "my-awesome-tool": "./cli.js"

my-awesome-tool is the command used to invoke the program, so change this to whatever you want your command to be.

Third step - configure it to do stuff

Next, we'll add commander so that we can more easily specify command line options. These are things like --version, -l, -s and other options you're probably used to using with standard CLI utilities.

This installs it: npm install commander --save

Then, we'll add some options:

#!/usr/bin/env node

const program = require('commander')

const { toUpperCase, toLowerCase } = require('./')

  .description('An example CLI for formatting names')
  .option('-u, --uppercase ', 'To all uppercase')
  .option('-l, --lowercase ', 'To all lowercase')

if (program.uppercase) console.log(toUpperCase(program.uppercase))
if (program.lowercase) console.log(toLowerCase(program.lowercase))

If you've never worked with commander before, that code might look like a lot or confusing, but it's really not.

const { toUpperCase, toLowerCase } = require('./') imports our program functions.

Then we specify the CLI options using chainable methods from commander (which we imported as program). In this example, the CLI program will take a name, and turn it to all uppercase or all lowercase, depending on what option the user passes in.

If you look at the option for uppercase: '-u, --uppercase <name>' - because we've specified <name>, this value can be used later in the code, as program.uppercase. That's how we get the value to pass to our toUpperCase and toLowerCase functions we imported to start with.

Lastly, we do some 'if checks' to see what option the user entered from the command-line and we pass that value to the program function to be called. This code is essentially what runs our program.

commander offers a lot, so definitely check out the documentation on it if you want to explore CLI options more!

Lastly - test it out

Now you might be wondering - this is great, but how do I actually test it out? How can I run my-awesome-tool from my command-line and test its options?

Easiest way to do that is to run npm link from the root of the package directory. This will create a local symlinked version of the package.

You can now test it out by running my-awesome-tool from the command line. Pass in --version to make sure it's working!

Here's an example output:

$ my-awesome-tool --version
$ my-awesome-tool -l Corey
$ my-awesome-tool -u Corey

Wrapping up

Next time you're getting stuck setting up your Node package to be run as a CLI program (or you're just researching how to do it), the key things to remember are:

  • add #!/usr/bin/env node
  • add "bin" to package.json, name your command, and specify the CLI program file path

And again, CLI's unlock so much potential - with this new ability you may have already started thinking about cool, helpful utilities you can now build / add to your Node programs!

And if you want an example to reference with all the code and package.json configuration in one place, sign up below to get the reference package! You'll also receive all my new posts directly to your inbox without having to remember to check back here.

Subscribe for the repo!

No spam ever. Unsubscribe any time.