DEV Community

Anupam Chakrawarti
Anupam Chakrawarti

Posted on

Make CLI Great Again: Crafting a User-Friendly Command Line

Table Of Contents

Handling Invalid Commands

❌ Silently fail on invalid commands or options.
✅ Provide clear suggestions or a list of similar commands instead of simply failing silently.

Scenario:

User types git staus instead of git status. Without proper handling, the CLI would just say "command not found." However, a well-designed CLI would respond with: "git: 'staus' is not a git command. Did you mean git status?" This immediately guides the user to the correct command, saving them time and frustration.

$ git poll

git: 'poll' is not a git command. See 'git --help'.

Did you mean this?

pull
Enter fullscreen mode Exit fullscreen mode
$ npm ragrragr
Usage: npm <command>
where <command> is one of:
    access, add-user, adduser, apihelp, author, bin, bugs, c,
    cache, completion, config, ddp, dedupe, deprecate, dist-tag,
    dist-tags, docs, edit, explore, faq, find, find-dupes, get,
    help, help-search, home, i, info, init, install, issues, la,
    link, list, ll, ln, login, logout, ls, outdated, owner,
    pack, prefix, prune, publish, r, rb, rebuild, remove, repo,
    restart, rm, root, run-script, s, se, search, set, show,
    shrinkwrap, star, stars, start, stop, t, tag, test, tst, un,
    uninstall, unlink, unpublish, unstar, up, update, upgrade,
    v, verison, version, view, whoami
    
npm <cmd> -h     quick help on <cmd>
npm -l           display full usage info
npm faq          commonly asked questions
npm help <term>  search for help on <term>
npm help npm     involved overview

Specify configs in the ini-formatted file:
    /Users/robert/.npmrc
or on the command line via: npm <command> —key value

Config info can be viewed via: npm help config
npm@5.5.1 /Users/robert/.nvm/versions/node/v9.1.0/lib/node_modules/npm
Enter fullscreen mode Exit fullscreen mode

Providing Helpful Error Messages

❌ Show technical jargon (stack trace) without proper context when the program crashes.
✅ If the order of the command is wrong, show the correct usage with examples.
✅Allow issue reporting via link. Display the stack trace and application version. Prompt the user to copy the stack trace when submitting an issue.

Scenario:

A user attempts to connect to a database using a tool, but the connection fails. A poor error message might say "Connection failed." A helpful error message would say: "Connection failed: Unable to connect to database at 192.168.1.100:5432. Please check the database server's status and your network connection." This gives the user specific information to troubleshoot the problem.

$ nmo cluster dsf
ERR! Usage:
nmo cluster get [<clustername>], [<nodename>]
nmo cluster add <nodename>, <url>, <clustername>
nmo cluster join <clustername>
Enter fullscreen mode Exit fullscreen mode
$ nmo cluster join anemone

ERR! df is not defined

ERR! ReferenceError: df is not defined

ERR!     at /Users/robert/apache/nmo/lib/cluster.js:84:5

ERR!     at cli (/Users/robert/apache/nmo/lib/cluster.js:68:27)

ERR!     at /Users/robert/apache/nmo/bin/nmo-cli.js:32:6

ERR!

ERR! nmo: 1.0.1 node: v9.1.0

ERR! please open an issue including this log on https://github.com/robertkowalski/nmo/issues
Enter fullscreen mode Exit fullscreen mode

Enabling User-Friendly Shortcuts

❌ Make commands explicitly clear using long names.
✅ Provide shortcuts or aliases for frequently used commands to improve efficiency and reduce typing.

Scenario:

A developer frequently uses the command npm install. By providing the shortcut npm i, they can significantly reduce the amount of typing required, especially during rapid development cycles. This small convenience adds up to a substantial time saving. Or a user might create a shortcut such as gco for the git command git checkout.

# npm 
npm install

npm i

# git

git checkout

git co

Enter fullscreen mode Exit fullscreen mode

Utilizing Exit Codes for Status

❌ Use the same exit code irrespective of whether the commands succeeds or fails.
✅ Use distinct exit codes based on status. Exit code 0 indicates success, while 1 indicates failure. This allows for proper error and crash handling.

Scenario:

A script runs a backup command. If the backup fails, the command should return a non-zero exit code (e.g., 1). The script can then check the exit code and take appropriate action, such as sending an alert or retrying the backup. This is crucial for reliable automation.

$ git poll

git: 'poll' is not a git command. See 'git --help'.

Did you mean this?

  pull

$ echo $?

1
Enter fullscreen mode Exit fullscreen mode

Supporting JSON Output for Data Processing

❌ Do not allow output on successful execution.
✅ Commands that return information support JSON-formatted output. This facilitates seamless integration and separate data processing with other tools and scripts, which is invaluable.

Scenario:

A system administrator uses a CLI to retrieve server information. By outputting the data in JSON format, they can easily parse and process the information using tools like jq or scripting languages like Python, enabling automated monitoring and reporting.

$ nmo cluster get --json

{ anemone:

   { node1: 'http://node1.local',

     node2: 'http://node2.local',

     node3: 'http://node3.local' } }
Enter fullscreen mode Exit fullscreen mode

Exposing APIs for Extensibility

❌ Do not expose functions or API to be used by application developer to plug that in their existing solution.
✅ Provide an API layer that allows developers to integrate the CLI's core functionality into their own applications.

Scenario:

A developer wants to build a web dashboard that displays the status of a cluster managed by a CLI tool. By exposing an API, the developer can programmatically retrieve cluster information and display it in their dashboard, creating a customized user interface.

const nmo = require('nmo');

nmo.load({}).then(() => {

  nmo.commands.cluster

    .get('testcluster', 'node1@127.0.01')

    .then((res) => {

      console.log(res);

    });

})
Enter fullscreen mode Exit fullscreen mode

Implementing Robust Validation

❌ Don't show error and fail silently.
✅ Validate user input early and provide clear error messages when invalid input is detected, preventing unexpected errors and crashes.

Scenario:

A user is attempting to add a URL to a configuration file. The CLI should validate that the URL is in a correct format. If the url is malformed, the application should display an error, and prevent the malformed URL from being added. This prevents the application from possibly crashing later, when it tries to use the malformed URL.

if (!/^(http:|https:)/.test(url)) {

  const err = new Error([

    'invalid protocol, must be https or http',

    'Usage: lounger isonline <url>'

  ].join('\n'));

  err.type = 'EUSAGE';

  return reject(err);

}
Enter fullscreen mode Exit fullscreen mode
function errorHandler (err) {
  if (!err) {
    process.exit(1);
  }
  if (err.type === 'EUSAGE') {
    err.message && log.error(err.message);
    process.exit(1);
  }
  log.error(err);
  process.exit(1);
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.