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?
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! ๐ค๐