Build Your Own CLI Application with Node.js
Today we are going to build a custom Command-line interface (CLI) application with Node.js. I’m planning to make a CLI to browse the topics of my blog. Let’s get started:
Table of Contents
Initialize Project
Let’s initialize our CLI project:
# create project
mkdir mnp-cli && cd mnp-cli
# init package.json
npm init -y
Install a few libraries:
npm install --save commander inquirer colors pad open
The important packages are commander and inquirer. We’ve installed colors, pad to beautify our project. These are optional. Also we’ve installed open package to open URLs in the browser.
Now we need to edit package.json. We’re going to set mnp as our command name. To do this, we’ve to add a bin field like:
{
"name": "mnp-cli",
"version": "1.0.0",
"description": "Mynotepaper CLI App",
"bin": {
"mnp": "./bin/index.js"
},
"author": "Md Obydullah",
"license": "ISC",
"dependencies": {
"colors": "^1.4.0",
"commander": "^5.1.0",
"inquirer": "^7.1.0",
"open": "^7.0.4",
"pad": "^3.2.0"
}
}
Create CLI Menus
Create a folder called lib and create a file under lib named data.js. We’ll store menu’s values in this file.
// topics
exports.topics = [
{name: 'Laravel', slug: 'laravel'},
{name: 'Vue.js', slug: 'vue-js'},
{name: 'Linux Server', slug: 'linux-server'},
];
// convert topic names to one line
exports.topicsNamePlain = exports.topics.map(function(o) {
return o.name;
});
// open in browser
exports.openInBrowser = [
"Yes",
"No"
];
Create another file named topics.js. This is our first menu. Here we’ll print menu names only.
const colors = require('colors');
const { topics } = require('./data');
// export function to list coffee
module.exports = function() {
console.log('MNP TOPICS');
console.log('------------------');
// list on separate lines
topics.forEach((topic) => {
console.log('%s', colors.bold(topic.name));
});
};
Let’s create another file called browse.js. This is our second menu. From here, we’ll show options to select a topic. Then we’ll ask user to open the topic URL in browser.
const inquirer = require('inquirer');
const colors = require('colors');
const pad = require('pad');
const data = require('../lib/data');
const open = require('open');
const questions = [
{ type: 'list', name: 'topic', message: 'Choose a topic', choices: data.topicsNamePlain },
{ type: 'confirm', name: 'openInBrowser', message: 'Open the topic in browser?', choices: data.openInBrowser },
];
module.exports = function () {
inquirer
.prompt(questions)
.then(function (answers) {
// get topic slug from topics array
var getTopicArry = data.topics.filter(t => t.name == answers.topic);
var getSlug = getTopicArry[0]['slug'];
var topicUrl = 'https://shouts.dev/topics/' + getSlug;
// print answers
console.log('\n');
console.log('YOUR ANSWERS');
console.log('------------------');
console.log(pad(colors.grey('Topic: '), 30), answers.topic);
console.log(pad(colors.grey('Topic URL: '), 30), topicUrl);
console.log(pad(colors.grey('Open in browser: '), 30), answers.openInBrowser);
// open topic in browser
if(answers.openInBrowser) {
(async () => {
// opens in the default browser
await open(topicUrl);
})();
}
});
};
Create Index File
Create a folder named bin and under bin folder create a file called index.js. We’ll add shebang line at the top of the file and will import commander and menus. We’ll also set command names here:
#!/usr/bin/env node
const program = require('commander');
// import menus
const topics = require('../lib/topics');
const browse = require('../lib/browse');
// print topic menu
program
.command('topics')
.alias('t')
.description('All topics')
.action(function () {
topics();
});
// print browse menu
program
.command('browse')
.alias('b')
.description('Browse a topic')
.action(function () {
browse();
});
// allow commander to parse `process.argv`
program.parse(process.argv);
Install Our App & Test
It’s time to install our app globally from local source code. Run this command to install globally:
npm install -g ./
Now we’re able to use mnp command. Run this command to check if our command works or not:
# these commands will show same info:
# command 1
mnp
# command 2
mnp -h
# command 3
mnp help
The commands will show the info like:
Usage: index [options] [command]
Options:
-h, --help display help for command
Commands:
topics|t All topics
browse|b Browse a topic
help [command] display help for command
Yeah. Our CLI application is working. We’re seeing our all commands using the help command. Let’s test the topics and browse commands:
# command topics
mnp topics
# or
mnp t
# command browse
mnp browse
# or
mnp b
Have a look at the GIF file:

Note: Look at the Commander.js‘s GitHub repo to get more info.
We’ve created our own CLI app and tested. You can download this project from GitHub. Thank you. ?Comment
Preview may take a few seconds to load.
Markdown Basics
Below you will find some common used markdown syntax. For a deeper dive in Markdown check out this Cheat Sheet
Bold & Italic
Italics *asterisks*
Bold **double asterisks**
Code
Inline Code
`backtick`Code Block```
Three back ticks and then enter your code blocks here.
```
Headers
# This is a Heading 1
## This is a Heading 2
### This is a Heading 3
Quotes
> type a greater than sign and start typing your quote.
Links
You can add links by adding text inside of [] and the link inside of (), like so:
Lists
To add a numbered list you can simply start with a number and a ., like so:
1. The first item in my list
For an unordered list, you can add a dash -, like so:
- The start of my list
Images
You can add images by selecting the image icon, which will upload and add an image to the editor, or you can manually add the image by adding an exclamation !, followed by the alt text inside of [], and the image URL inside of (), like so:
Dividers
To add a divider you can add three dashes or three asterisks:
--- or ***

Comments (0)