DEV Community

Cover image for Building a CLI tool using node - An Ultimate Beginners guide ๐Ÿš€
Meer Hamza
Meer Hamza

Posted on • Updated on

Building a CLI tool using node - An Ultimate Beginners guide ๐Ÿš€

What is a CLI Tool

A tool that allows you to perform certain tasks or operations right from your terminal is a CLI tool.

As a programmer ๐Ÿ‘จโ€๐Ÿ’ป, we use CLI tools on daily basis, from creating projects to managing versions of the projects, CLI is everywhere. In this article, we will explore how you can create a CLI tool on your own from scratch and publish it on npm. We will use Nodejs for this purpose, but first, letโ€™s understand what are the perks of using nodejs:

  • Nodejs has a handful of packages and libraries to do variety of tasks.
  • npmjs is the worlds largest software registry with thousand of packages, where we can publish ours.
  • By creating a CLI in node:
    • We can automate repetitive tasks.
    • We can create and publish open-source npm packages like create-react-app.
    • We can create troubleshooting tools, etc

Prerequisites

To build a CLI in Node, you should have the prior knowledge of:

  • Fundamental JavaScript (not vanilla)
  • Basics of nodejs & npm
  • Asynchronous JavaScript

In this article, we will create a CLI tool which generates random passwords from your terminal.

Setting up the project

First we will create a directory that will keep our cli code:

mkdir random-password-generator
cd random-password-generator
Enter fullscreen mode Exit fullscreen mode

After creating the project folder we have to initialized our nodejs project

npm init
Enter fullscreen mode Exit fullscreen mode

It will ask some questions from you, you can also use npm init -y to set the default values. This will create a package.json file.

What is package.json file

The package.json file is the heart of any Node project. It records important metadata about a project which is required before publishing to npm, and also defines attributes of a project that npm uses to install dependencies, run scripts, and identify the execution point to our package.

Creating the CLI tool:

Create a file index.js in the root of the project directory. This will be the main starting point of the execution and it'll run all the associated functions and commands.
Now let's begin to create our cli tool. Our cli tool consists of the following features:

  • Randomly generates strong passwords.
  • Automatically copy passwords to the clipboard, when created.
  • Have a history feature that shows the lastly created password.

To implement the random password generation functionality paste the following code.

const chars = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let passwordLength = 30;
let password = "";

for (let i = 0; i <= passwordLength; i++) {
    let randomNumber = Math.floor(Math.random() * chars.length);
    password += chars.substring(randomNumber, randomNumber + 1);
}
Enter fullscreen mode Exit fullscreen mode

This will generate a random password on every run.

Console Output

Perfect a strong random password is generating on every run but if you notice to generate the password you have to run node index.js every time which is not ideal especially in case of a cli tool. We are supposed to write a command for example passgen or pswdgen to generate the passwords. So, to achieve this functionality we have to modify our index.js and package.json files. In the index.js file add this line

#!/usr/bin/env node
Enter fullscreen mode Exit fullscreen mode

The above line is called shebang. It tells the system to execute the code using the node environment. Make sure to add it to the first line of your main execution file. In package.json add the following code above the main key in such format "main-command-name": "main-file-path", In our case:

"bin": {
    "pswdgen": "./index.js"
  },
Enter fullscreen mode Exit fullscreen mode

Now, to generate the password you simply type pswdgen on the terminal but to enable it and test your cli locally you have to link it first. To link the cli run the following command.

npm link
Enter fullscreen mode Exit fullscreen mode

if you face any error try to run it with a -f flag

The output would be

Image description

Now we work on the auto copy feature of the cli. For this purpose, we use a package named clipboardy. To install run

npm i clipboardy@2.3.0
Enter fullscreen mode Exit fullscreen mode

To automatically copy the password on the clipboard we simply have to add this line after the loop

 clipboard.writeSync(password)
Enter fullscreen mode Exit fullscreen mode

Make sure you import clipboardy

Now, we implement history feature through which we can view the lastly created password through the -h or --history flag. For this purpose we use conf package. But first, let's create the flag feature. We use process.argvfor this purpose, process.argv is an inbuilt API used to get the arguments passed via command line like -h. We will slice it to remove the first two indexes of it to get relevant data only.

const flags = process.argv.slice(2);
Enter fullscreen mode Exit fullscreen mode

Now to store password we use following code

config.set('prevPassword', password);
Enter fullscreen mode Exit fullscreen mode

Make sure to import and initialized conf as follow

const Conf = require('conf');
config = new Conf();
Enter fullscreen mode Exit fullscreen mode

To use -h feature only when requested we make it sure to use the get history code of the conf in a if statement as follow:

 if (flags[0] === '-h' || flags[0] === '--history') {
        console.log(config.get('prevPassword'));
    }
Enter fullscreen mode Exit fullscreen mode

Also make sure to use the mentioned code above the config.set code.

The output would be
Image description

Our cli is complete ๐ŸŽ‰๐ŸŽ‰ but if you notice at the codebase all things are coded on a single function and file which makes codebase messy and also it will become hard to debug as it increases and the interface of the cli is also not good and user friendly, the user didn't get any idea of the password, as it copies on the clipboard or not.

Image description

First, instead of a single function letโ€™s divide it into multiple functions according to their functionality. It will be divided into four functions passwordGenerator, copyToClipboard, savePassword and history. Now we will create a separate folder named functions and create a file for each function respectively. Now, we work on the interface of the cli. For this purpose, we use 2 packages.

To install cli-welcome, run

npm i cli-welcome
Enter fullscreen mode Exit fullscreen mode

We will create a folder name utils and create a file header in it where we add the following code

const welcome = require('cli-welcome');

module.exports = () => {
    welcome({
        title: `password-generator-cli`,
        tagLine: `by Meer Hamza`,
        bgColor: `#00ff00`,
        color: `#ffffff`,
        description: `randomly generates strong passwords`,
        bold: true,
        clear: true,
        version: `1.0`
    });
}
Enter fullscreen mode Exit fullscreen mode

and now simply import this file and call the header function above all the function calls. This will generate this beautiful header

Image description

Now, in the utils we create a file, name cli or body and paste the following code and its associated imports from the index.js to it.

    const config = new Conf();
    const flags = process.argv.slice(2);

    if (flags[0] === '-h' || flags[0] === '--history') {
        history(config)
    }
    else {
        const password = passwordGenerator();
        copyToClipBoard(password);
        savePassword(password, config);
    }
Enter fullscreen mode Exit fullscreen mode

Now, we beautify the output and the copy to clipboard message using the chalk. To install chalk, run

npm i chalk@4.1.2
Enter fullscreen mode Exit fullscreen mode

Now, we will style different things like password, previous password etc. for example to style copy to clipboard message we write following code

console.log(chalk.gray('Password copy to the clipboard'))
Enter fullscreen mode Exit fullscreen mode

The final look of the cli will be:

Image description

with -h flag

Image description

Publishing the CLI tool

After creating the cli, to make it accessible to everyone we publish it to npm js, which is the home of thousands of packages, as a package. So, make sure you have created an account on the npmjs. After the account creation, run the following command in your terminal

npm login
Enter fullscreen mode Exit fullscreen mode

You will be asked to enter your username, password, and email. If all correct, you will be logged in.

Then, to publish your cli run

npm publish
Enter fullscreen mode Exit fullscreen mode

This command publicly published your cli on npm with the name specified in project's package.json.

"name": "package-name",
Enter fullscreen mode Exit fullscreen mode

It can also give the error if another package with the same name exist. Keep in mind there's a difference in name and command-name we specified in the bin attribute, name is used to download package from npmjs while command-name specified in the bin used to run cli and functions. To install your package from npm simply run

npm i -g pswd-generator-cli
Enter fullscreen mode Exit fullscreen mode

Whenever you make changes in the CLI, you have to change the version in the package.json and then republished the changes otherwise it will give error.

Conclusion

Congratulations, you learned how to create a CLI tool using Node.js ๐ŸŽ‰๐ŸŽ‰. The sky is the limit, go create something awesome. I also created an open-source template so you don't need to start everything from scratch.
github.com/meerhamzadev/node-cli-template

code link: code

Discussion (0)