DEV Community

Cover image for Building Node.js CLI Tool.
Mehak.
Mehak.

Posted on

Building Node.js CLI Tool.

Recently, while revising Node.js, I came across the project section Node.js roadmap on roadmap.sh(https://roadmap.sh).

The first project challenge there is to create a CLI (Command-Line Interface) tool using Node.js. So,I decided to build one to refresh my basics.

This post explains how CLI tools actually work under the hood and how to build one yourself from scratch.


How OS Executes Script Files

Before creating any CLI, we must understand how operating systems execute scripts.

Normally, when you run a Node.js file like this:

node index.js
Enter fullscreen mode Exit fullscreen mode

it’s Node.js that runs the file — not your operating system.

The OS doesn’t automatically know how to execute JavaScript — it just knows how to run:

  • Compiled binaries (bash, python, node, etc.)
  • Or scripts that explicitly tell it which program should interpret them.

If you want your script to be run directly (e.g., by typing mycli in the terminal), then the OS must know which program to use to interpret it.

By default, if you make a file executable, the OS will assume it’s a shell script unless you specify otherwise.

To tell the OS that your script should be run by Node.js, add this line at the top of your file:

#!/usr/bin/env node

Enter fullscreen mode Exit fullscreen mode

This line is called a shebang, and it tells the OS:
“Run this file using Node.js, wherever it’s installed.”


How npm Installs CLI Tools Globally

When we install any package globally using npm install -g npm do the following things:

  • Installs the package in your system’s global node_modules directory(the path depends on your OS).
  • Looks for the bin field inside the package’s package.json.
  • Creates a symlink (symbolic link) between the CLI command and the script file defined in bin. So, for example, if your package.json contains:
"bin": {
  "taskcli": "./bin/index.mjs"
}
Enter fullscreen mode Exit fullscreen mode

npm will create a command called taskcli that points to your script.


The bin Field in package.json

The bin field defines which commands your package exposes and what files they execute.

I like to keep all CLI entry files inside a bin/ folder for clarity.


Parsing Command-Line Arguments

When we execute a script, Node exposes the arguments through process.argv.

node script.js add "Buy groceries"
Enter fullscreen mode Exit fullscreen mode

process.argv will contain:

[
  '/usr/bin/node',
  '/path/to/script.js',
  'add',
  'Buy groceries'
]
Enter fullscreen mode Exit fullscreen mode

we could manually parse this array, but that’s tedious.Instead, use a library like Commander.js,which gives you:

  • Argument parsing
  • Subcommands
  • Automatic --help and --version support

Making the Tool Work Locally — npm link

Before publishing your CLI to npm, we can test it locally using:

npm link
Enter fullscreen mode Exit fullscreen mode

This creates a symlink between your local project and your global npm binaries directory,so your command (taskcli) behaves like a globally installed CLI.

Now you can run:

taskcli add "Learn Node.js"
taskcli list
Enter fullscreen mode Exit fullscreen mode

No global installation needed and everything runs locally.


Final Project

Here’s my implementation:

GitHub: MehakB7/task-cli
Roadmap.sh Submission: Task Tracker Project Solution

This small project helped me understand:
How the OS executes scripts
How npm sets up CLI tools under the hood
How to design structured, maintainable command-line apps

Top comments (0)