How to build your own CLI tool with NodeJS

How to build your own CLI tool with NodeJS

We use the command line every day - but do you know how you can create your own commands?

ยท

3 min read

We're using the command line every day (I believe), you use it when you create a commit with git, start your project in NodeJS or for any other task.

But have you every thought of building your own command for the command line?

What is a CLI

CLI stands for "Command line interface". As the name suggests, it's a way to interact with your software using the command line. Most likely, you'll have one main command, something like git, node, npm, and then different subcommands like commit or push for different actions. Commands may also have arguments to customize the behavior of the command.

How to build your own CLI

This won't be a complex tutorial - I'll show how to use the package comander to create custom commands and use arguments. The final logic of your CLI is something you need to come up with.

Initialize your project

Create a new folder and run npm init -y to initialize a new project.

To build the CLI, we'll use the NPM package commander.

npm install commander

Create the main file

Entry points for CLIs are located in bin directories. So let's create a new file inside this folder your-project/bin/index.js:

#!/usr/bin/env node
const program = require("commander")

We can also add some information to our program:

program
    .version("1.0.0")
    .description("That's my CLI and it's doing awesome stuff")
    .parse()

The first command

You see, it's not very complicated - so let's create our first command:

program.command("hello-world").action(() => {
    console.log("Hello :)")
})

// You can also add a description
program.command("hello-world").description("Just says hello").action(() => {
    console.log("Hello :)")
})

Commands with arguments

We can add arguments directly in the command function. You can add <required> or [optional] arguments:

program
    .command("hello <name>")
    .description("Say hello to someone")
    .action((name) => {
        console.log(`Hello, ${name}!`)
    })

The arguments will be passed in the same order as in the command function to the action callback.

The full example

#!/usr/bin/env node
const program = require("commander")

program
    .version("1.0.0")
    .description("That's my CLI and it's doing awesome stuff")
    .parse()

program
    .command("hello-world")
    .description("Just says hello")
    .action(() => {
        console.log("Hello :)")
    })

program
    .command("hello <name>")
    .description("Say hello to someone")
    .action((name) => {
        console.log(`Hello, ${name}!`)
    })

program.parse(process.argv)

Test the CLI

Before we can test the CLI, we have to add one last line at the end of the file:

program.parse(process.argv)

This sends the arguments passed from the command line to the commander package that manages our commands.

Now we can test the CLI with the following command:

node ./bin/index.js -V
# 1.0.0

node ./bin/index.js hello-world
# Hello :)

node ./bin/index.js hello Linus
# Hello, Linus!

node ./bin/index.js hello "Linus Benkner"
# Hello, Linus Benkner!

Finish the CLI

When you're done building your CLI, let's make it ready to share it with others. Now think of a name for your command and add this to your package.json. For this example, I'll use custom-cli-example:

{
  "name": "custom-cli-with-nodejs",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": {
    "custom-cli-example": "./bin/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "commander": "^8.3.0"
  }
}

For the final testing, let's install it on our own computer:

npm install -g

You can now run custom-cli-example with all your commands and options.

That was pretty simple, wasn't it? ๐Ÿ˜Ž

Thank you for reading and have a nice day! ๐Ÿค—๐Ÿ‘‹

Did you find this article valuable?

Support linu.us by becoming a sponsor. Any amount is appreciated!

ย