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

Build a Cross Platform Command Line Executable in Node.js

anaptfox profile image Taron Foxworth ・2 min read

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


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')

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
$ ./add.js --digit=12

Now, onto the magic. Install, pkg:

$ npm i -g pkg

To convert your program to a binary, run:

$ pkg add.js

Running this command will generate three files:

$ ls 
add-linux   add-macos   add-win.exe

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:


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. Stay Tuned 🖖🏽

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.


Editor guide
g2000ny profile image

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?!?

dfieldfl profile image
Brandon Groves

What terminal/theme are you using these days

anaptfox profile image
Taron Foxworth Author

Currently, I use Hyper. I love it.

justingorham profile image
Luke Jwage

I have immediate use cases for this. Thank you.

ben profile image
Ben Halpern

Looks super useful. Thanks.

alex_escalante profile image
Alex Escalante

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

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.