If you are a developer, you should be some how or familiar with command-line user interface(cli) because a lot of tools provide CLI such git, npm-cli, python-cli, dotnet-cli, aws-cli and more. CLI tools have many advantages than GUI tools like launch easily, development easily and cross-platform easily. Cli tool is good for you at some scenarios, for example, csv files import, batch jobs or schedule jobs. Therefore, this blog-post will show you a easy way to build a cross-platform CLI tool.
I use Nodejs to build the CLI tool. There are 3 benefits:
- Nodejs is cross-platform, CLI tools can be run on Windows, Mac and Linux.
- Easy to distribution. You can publish the cli tool to NPM or just make a package to install privately.
- Easy to build. Only few lines, the project can be turned to a CLI tool.
Try this command to see your computer has nodejs installed.
node --version
You can go to Nodejs to install it if you haven't installed on your computer.
Let's start an easiest example.
mkdir build-cli-example
cd build-cli-example
npm init --yes
Those commands will create a package.json.
{
"name": "build-cli-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"bin":{
"my-cli" : "./my-cli"
}
}
bin
is the command name and we named it my-cli
. Its value is a file like below.
#!/usr/bin/env node
require("./index.js")
The first line tells NPM what kind of environment the file is. It is very important because without this line. NPM cannot generate bin files correctly.
The other lines are regular Nodejs code. There just calls ./index.js
.
console.log("hello would")
For our first step, we just print the greeting word.
npm pack
npm install -g build-cli-example-1.0.0.tgz
my-cli
when you run
npm install -g build-cli-example-1.0.0.tgz
to install the package, npm will generatemy-cli
(sh file) andmy-cli.cmd
in the npm file. Because the npm file is inPATH
, so when we typemy-cli
. The OS can findmy-cli
to execute.
The really CLI tool usually can allow users input some parameters to change its behaviors. You can use process.argv
to get input parameters and parse them, but don't build your own wheels if there are many parsers you can use. I recommend command-line-args, it is a very good parameter parser.
npm install --save command-line-args
const commandLineArgs = require('command-line-args')
const optionDefinitions = [
{ name: 'env', alias: "e", type: String, defaultValue: "local" },
{ name: 'files', alias: "t", type: String, multiple: true },
{ name: 'help', alias: "h", type: Boolean },
{ name: 'new', alias: "n", type: Boolean },
{ name: 'size', alias: "s", type: Number, defaultValue: 100 }
]
const options = commandLineArgs(optionDefinitions, { partial: true });
if (options.help || options._unknown) {
if (options._unknown) {
console.log("Unknown options:", options._unknown);
}
// TODO:Print Help
} else {
// Do some jobs
}
The command-line-args is straight forward to use, you can see command-line-args for complete information.
my-cli -e qa --files ./a.txt ./b.txt
One thing I complain command-line-args is that its usage generation is separated to another package command-line-usage
. So you have to define parser and usage on the different place.
npm install -S command-line-usage
const usage = require('command-line-usage');
const sections = [
{
header: 'My CLI',
content: 'description'
},
{
header: 'Options',
optionList: [
{
name: 'new',
alias: "n"
},
{
name: 'size',
alias: "s",
description: 'Batch Size, default is 100'
},
{
name: 'files',
alias: "f",
multiple: true,
typeLabel: '[underline]{file} ...'
},
{
name: 'env',
alias: "e",
description: 'Environment, default is local'
},
{
name: 'help',
alias: "h",
description: 'Print the usage guide'
}
]
},
{
header: 'Examples',
content: [
{
desc: "env",
example: "my-cli --env dev"
},
{
desc: "files",
example: "my-cli --files a.txt b.txt"
}
]
},
]
console.log(usage(sections))
you can see command-line-args for complete information.
Run npm pack
and npm install -g
as below to reinstall the package.
my-cli --help