Improve the UX of CLI tools with version update warnings

David Barral
Trabe
Published in
3 min readApr 30, 2018
Photo by rawpixel.com on Unsplash

CLI tools are like any other user facing software: they need to provide a good user experience. UX is about more than having a great UI. For instance, software evolves, and users must be given the tools to upgrade, either by using some kind of auto update feature or by using a distribution channel with versioning support. The latter approach relies on the user asking if something is outdated and that’s not the best UX. Tools should be proactive and warn the user about new versions.

Several well-known tools like npm or yarn follow this pattern. If you use npm I’m sure you’ve seen a message like this one:

╭─────────────────────────────────────╮                                  │   Update available 5.5.1 → 6.0.0    │ 
│ Run npm i -g npm to update │ ╰─────────────────────────────────────╯

It’s a nice touch when you distribute your CLI tools using a package manager.

A version checker for npm packages

Let’s add version checking to a hello CLI command (I assume you know how to build a command line tool in node). To detect new versions we need to query the npm registry. If the local version of the package is outdated, a message in the console will invite the user to update to the latest version.

We start with a simple executable script. It just imports the hello function from a lib module and call it (it’s easier to test the logic this way).

The hello function will use a versionCheck utility before doing its thing.

To look for new versions:

  • We use package-json to fetch the package metadata from the registry. This library also deals gracefully with npmrc config files and that’s a plus!
  • To compare versions we use semver, the semantic version parser used by npm itself.

Notice that we use the latest dist-tag in getLatestVersion, but your mileage may vary. It should be adapted to your package versioning policy (skip or use non stable channels, etc.).

Improvement: periodic checks

If you try the code above you’ll probably notice a lag on each run depending on your connection speed. We are issuing a network request to the npm registry on each execution. That’s overkill. Nobody releases packages that often.

To remove the lag we just need to check for updates periodically. We can store the last time we checked and wait for a defined period of time to pass before attempting a new check.

In this example we store the last check time as a timestamp in a file under the OS’s temp folder.

Improvement: synchronous API

CLI tools tend to be synchronous. It’s not nice to force the use of async functions just to await for the version check. We can fix that by adding a versionCheck.sync() method. We use DeAsync.js. It allows us to wait for async code without blocking the entire event loop.

Wrapping up

With a few lines of code we can improve the UX of our CLI tools. We’ve seen the Javascript/npm version but the same approach can be used with other languages/package managers, like Ruby and RubyGems, Python and pip, etc.

--

--

David Barral
Trabe
Editor for

Co-founder @Trabe. Developer drowning in a sea of pointless code.