We're planting a tree for every job application! Click here to learn more

How to make beautiful, simple CLI apps with Node

Hugo Di Francesco

21 Jun 2018

•

2 min read

How to make beautiful, simple CLI apps with Node
  • Node.js

Channel your inner Sindre Sohrus and ship a beautifully simple CLI app using Node.

Command line apps are a neat way to package repetitive tasks. This will walk you through some tools that are useful to build CLI apps.

  • The idea đź’ˇ
  • Piping to the command line 🚇
  • Dealing with sequential actions ✨
  • Executable JavaScript files 🦅
  • Adding package binaries 📦
  • Publishing to npm 🚀

The idea đź’ˇ

When merging/rebasing, the file that always seems to cause trouble is the package-lock. We’ll go through how to make a simple utility that deletes the package-lock.json file, regenerates it (npm install) and adds it to the git index.

You can find it here: and run it using npx fix-package-lock.

Piping to the command line 🚇

To start off, we’ll leverage a package from Sindre Sohrus, execa, which is described as “a better child_process”. For the following snippet to work, run npm install --save execa:

index.js

const execa = require('execa');
execa('ls').then(result => console.log(result.stdout));
node index.js
index.js
node_modules
package-lock.json
package.json

Dealing with sequential actions ✨

To re-generate the package-lock we’ll need to first delete it, then run an npm install.

To this end, we can use Listr, it allows us to do things that look like:

Hugo article gif.gif

Run npm install --save listr and add leverage Listr as follows:

index.js:

const execa = require('execa');
const Listr = require('listr');
new Listr([
  {
    title: 'Removing package-lock',
    task: () => execa('rm', ['package-lock.json'])
  },
  {
    title: 'Running npm install',
    task: () => execa('npm', ['install'])
  },
  {
    title: 'Adding package-lock to git',
    task: (ctx, task) =>
        execa('git', ['add', 'package-lock.json'])
        .catch(() => task.skip())
  }
]).run();

Now the output of node index.js looks like the following:

Hugo article image# 2.jpeg

Listr gives you a loading state when you have a long-running task that returns a Promise (like the execa invocation of npm install).

It’s also possible to display a message that changes using Observables, for more information see the Listr docs

Executable JavaScript files 🦅

It’s ideal to be able to execute our script using ./index.js instead of node index.js.

To do this, we need the file to be executable on UNIX systems that’s: chmod +x. So

chmod +x index.js

We then need to inform the system how it should attempt to run the file, that’s using the following hashbang:

#!/usr/bin/env node

If we add it to index.js we get:

#!/usr/bin/env node
const execa = require('execa');
const Listr = require('listr');
new Listr([
  {
    title: 'Removing package-lock',
    task: () => execa('rm', ['package-lock.json'])
  },
  {
    title: 'Running npm install',
    task: () => execa('npm', ['install'])
  },
  {
    title: 'Adding package-lock to git',
    task: (ctx, task) =>
        execa('git', ['add', 'package-lock.json'])
        .catch(() => task.skip())
  }
]).run();

Which we can now run using:

./index.js

Adding package binaries

npm has a bin field which we can use like the following (in package.json):

{
  "name": "beautiful-cli",
  "version": "1.0.0",
  "description": "A simple CLI",
  "main": "index.js",
  "bin": {
    "fix-package-json": "./index.js"
  }
  "dependencies": {
    "execa": "^0.10.0",
    "listr": "^0.14.1"
  }
}

Publishing to npm 🚀

This is left to the reader as an exercise, although using the np package, it’s super straightforward.

Hint: run npx np in whatever package you’re trying to publish.

You can find the full package here and run it using npx fix-package-lock.

Did you like this article?

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub