A Guide to Creating a NodeJS Command-Line Package

A Guide to Creating a NodeJS Command-Line Package image


Photo by: Carolin Zöbelein

Feeling inspired to create a NodeJS command-line script to solve a specific issue? Do you want to ship your command-line as an installable package? It should be simple, right? Fortunately, it is!

Here is a concise guide on things we should do to create a NodeJS command-line package.

This guide will walk you through the creation, mapping, and linking of a NodeJS command-line script.


1. Create a NodeJS package

Before doing anything else, we need to create NodeJS package, i.e. just a directory containing a package.json file. We can easily do that in 2 steps.

  1. Create an empty directory.
  2. Run: npm init from inside the new directory.

That is nothing new, nor specific to creating a NodeJS command-line package as it is the starting point of any NodeJS package. Now that we have that let us create what will be our NodeJS command-line script.


2. Create a NodeJS command-line script

You may already know that we can execute a NodeJS script file by running: node script.js. That is fine in most cases, but a NodeJS command-line script is a regular JavaScript file, except that it contains a special shell-instruction. More about that shortly; first let us create a JavaScript file that will become the NodeJS command-line script.

Create a JavaScript file

The npm.js docs and popular NodeJS projects use to name JavaScript command-line file as cli.js. This a good practice because the name itself tells its purpose.

Convert the JavaScript file into a NodeJS command-line script

Similar to other shell scripts, we want to make our JavaScript file executable by the locally installed program. We do that by adding a shebang character sequence at the very top of our JavaScript file that looks as follow:

That way, we are telling *nix systems that the interpreter of our JavaScript file should be /usr/bin/env node which looks up for the locally-installed node executable.

In Windows, that line will just be ignored because it will be interpreted as a comment, but it has to be there because npm will read it on a Windows machine when the NodeJS command-line package is being installed.

Make the JavaScript command-line file executable

In most cases, new files are not allowed to be executed. As we are creating a NodeJS command-line script that will be executed, we need to modify its file permissions. In a *nix system you can do that as follows:

chmod +x cli.js

Now, let us add some code to our script file. We will create a simple Hello World that will also print any provided arguments.

Add code to our NodeJS command-line script file

The code on line 4 will grab all given command line arguments after the third. Moreover, on line 7, we are just printing out Hello World, and we are adding any provided arguments (if any).

Awesome! Now we can run it on Linux or Mac OS X as ./cli.js or in Windows with node.cmd cli.js. Try it! Also, pass some argument to it.

So far, we can run our NodeJS command-line file as a regular script in Linux and Mac OS X, but with still need to add node.cmd in Windows. Also, we are bound with the filename to execute our command-line script, which is not nice. In the next section, we will circumvent those issues.


3. Map a command-line script to a command name

So far, we converted a JavaScript file into a NodeJS command-line script file. However, we want to give it a more meaningful name that does not need to be the name of the NodeJS command-line script file. For that, we have to map our command-line script by configuring our package.json. About this topic the npmjs.com docs say:

supply a bin field in your package.json which is a map of the command name to the local file name.

This means we can specify a ‘command name’ for our local ‘command-line script’. Let us say we want our cli.js command-line file to be mapped to say-hello. We can do that by modifying our package.json and adding a bin field as aforementioned:

To see its full potential, we are assigning to the bin field an object where the keys become the command names, and the values are the NodeJS command-line script files mapped. That format allows us as developers to provide more than one script mapping. However, if we want to provide a single NodeJS command-line script with the same name as its file, we could just set a string instead of an object where the string would be the local file path.

Notes on naming a command

We can choose any name for a command, but we do not want it to clash with existing popular command names such as ls, cd, dir, and so on. If we use one existing name, chances are it will not be executed; instead, the already installed one will be (results may vary).


4. Link your command for development

As developers, sanity is more than just a word; it is life. That is why we need to be confident enough on how our NodeJS command-line script will be shipped as a package. Thankfully, npm comes with the link command that will provide our regular dose of sanity.

The npm link command allows us to locally ‘symlink a package folder’, and for our needs, it will locally install any command listed in the bin field of our package.json. In other words, npm link is like a NodeJS package installation simulator. It is worth to mention that npm link has a wider usage that exceeds the scope of this guide.

The npm link command is used from within the NodeJS package directory we want to symlink:

npm link

Once executed, we will see our command being symlinked globally. Now, we can execute our NodeJS command-line script with its own ‘command name’ say-hello:

Pretty neat, right? That way, we can play with our NodeJS command-line script locally before even npm publish‘ing them.

Under the hood, npm link (also applies to npm install) symlink all files specified in the bin field of package.json. The npmjs docs add:

On install, npm will symlink […] file[s] into prefix/bin for global installs, or ./node_modules/.bin/ for local installs.

On *nix systems, the npm link linking process is like creating a shortcut to our specified command file, which will be executed by the shell and then by node as specified with the shebang (#!/usr/bin/env node). While on Windows, npm will do the same (only if the shebang is specified) but will also create a {command-name}.cmd that calls node to execute our specified command file.

Keep your room clean

When we finish testing our symlinked command, we may want to remove it. We can achieve that by running the following code from inside the package directory.

npm unlink

Conclusion

That is it for a concise guide to creating a NodeJS command-line package. With those four steps, we have the basics to ship a NodeJS package that will install a command-line package.

Now, it is up to you to commit, push and unleash your creativity by coding a NodeJS command-line package. If you do so, please, drop me a message in the comments with the GitHub link so I can take a peek.


Recommendations

Finally, here are some utilities I have used in my own personal command-line projects:

  • meow – Simple command-line helper.
  • chalk – Terminal string styling.
  • yargs – Command-line opt-string parser.

Personal command-line projects

Here are some of my personal NodeJS command-line packages:

KEEP MOVING FORWARD

Rubens Mariuzzo / node