DEV Community

Cover image for Build a Cross Platform Command Line Executable in Node.js
Taron Foxworth
Taron Foxworth

Posted on • Edited on

Build a Cross Platform Command Line Executable in Node.js

Before we begin, this article assumes you know a couple of things: Javascript, Terminal, and Node.js.

Terminal

Creating a command line tool in Node.js is easy, especially with tools like yargs, commander, inquirer.

However, secretly, I’ve been jealous of CLI tools built in Go. The CLI tools build in Go get shipped as a single binary file, with no dependencies.

Then, as I started using Zeit’s tools, I came across pkg. With pkg, I can create my tool in Node.js but, ship it as a single binary. 🙌🏽

For example, let’s create a simple command line tool:

#!/usr/bin/env node
const argv = require('yargs').argv

if (argv.digit) {
  console.log(argv.digit + 1)
} else {
  console.log('Hmmm. I\'m confused')
}
Enter fullscreen mode Exit fullscreen mode

This program will add 1 to a parameter named digit . If you put this in a file called add.js (make sure you run npm install yargs ), you’ll have a command line tool:

$ ./add.js --digit=1
2
$ ./add.js --digit=12
13
Enter fullscreen mode Exit fullscreen mode

Now, onto the magic. Install, pkg:

$ npm i -g pkg
Enter fullscreen mode Exit fullscreen mode

To convert your program to a binary, run:

$ pkg add.js
Enter fullscreen mode Exit fullscreen mode

Running this command will generate three files:

$ ls 
add-linux   add-macos   add-win.exe
Enter fullscreen mode Exit fullscreen mode

You have just created a single file binary for Linux, Mac OS X and Windows.

You also run it as you would any other binary:

./add-macos
Enter fullscreen mode Exit fullscreen mode

If you’re like me and was curious as to how this works, this video was enlightening:

I didn’t make this tool. I just wanted others to bask in the awesomesauce that is Javascript.

I’ll be using this tool in upcoming projects.


Hi, thanks for reading. I’m Fox, a Technical Evangelist at Losant. My dream is to translate technology for people to learn, love, and be inspired. Feel free to follow me on Twitter.

Top comments (7)

Collapse
 
g2000ny profile image
g2000ny

Your example shows the parameters. How about config file? My use case is to store app user and id. They are jibberish and I do not want to pass in as parameters.

I tried to pass in the config file name. Debugging the application, it shows the 'snapshot' folder which doesn't even exist in my computer. Not sure why?!?

Collapse
 
justingorham profile image
Luke Jwage

I have immediate use cases for this. Thank you.

Collapse
 
dfieldfl profile image
Brandon Groves

What terminal/theme are you using these days

Collapse
 
anaptfox profile image
Taron Foxworth

Currently, I use Hyper. I love it.

Collapse
 
alex_escalante profile image
Alex Escalante

I guess it will generate huge packages, but it's nice to have it!

Collapse
 
obstschale profile image
Hans-Helge Buerger

I had the same thought. I compiled a very simple CLI program from me and it already had 33+ MBs. This could grow quickly.

I am fairly new to JS but maybe using webpack and its tree-shaking feature could reduce the size.

Collapse
 
ben profile image
Ben Halpern

Looks super useful. Thanks.