CLI-ate with NodeJS

CLI-ate with NodeJS

I've always read about how easy it was to create a Command Line Utilities with node, but I never thought it was this easy... I'm doing this post(as always) for self documentation.

In this post, I'm documenting the steps I follow in the creation of a Command Line Interface tool using NodeJS. This is useful because we can take advantage of how NodeJS can handle the filesystem, system status, command line interface, among others... We can encapsulate scripts to execute them as applications, create scripts for tasks automation and so on.

3 steps:

  • We need to create a normal package.json file, adding the following 2 lines:
"preferGlobal": "true",
"bin": { "command-name": "script.js" }
  • Now, in our script.js (which will be the 'CLI' utility), we add #!/usr/bin/env node in the first line of the file. This should go in the first line since it tells the execution context what interpreter to use for the file, in our case, 'node'.

  • The last step is to create a globally-installed symbolic link to the folder of your command. This may sound overwhelming at first, thankfully we have a command in npm to take care of this, just do npm link in your terminal and it will create the symlink for you.

If all goes well, you can now use in the terminal (from anywhere), the newly created command via the command name you specified in the package.json, and it will execute your script application.

Now, to get a bit fancy, we can handle arguments for our CLI, which are contained in the global object process. Doing a console.log(process.argv), we get all the arguments passed in (this will also contain the interpreter(node) and the script's path. Since the process.argv returns an array, we can slice it removing the first two items (process.argv.slice(2)), which will give us only the actual arguments.

This is somewhat limited since you get everything after the command name separeted with whitespace, in the array. You will need to parse the array in order to use flags and variables. luckily, there are some good argument parsers out there. The one I recommend using is substack's minimist. Be sure to check it out, it'll help u a lot.

An example taken from minimist github readme:

$ command-name -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
# this will return:
{ _: [ 'foo', 'bar', 'baz' ],
  x: 3,
  y: 4,
  n: 5,
  a: true,
  b: true,
  c: true,
  beep: 'boop' }
comments powered by Disqus