# How to build your own CLI tool with NodeJS

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](https://www.npmjs.com/package/commander).

```bash
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`:

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

We can also add some information to our program:

```js
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:

```js
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:

```js
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

```js
#!/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:

```js
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:

```bash
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`:

```json
{
  "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:

```bash
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! 🤗👋
