This article is part number 11 of the CLI design series.

While it is a rare thing to find, CLI-based applications can be interactive just like any other kind of application can. If you choose to interactively query the user for details in your program or script, you should be aware of the two scenarios that can result from this choice (which, interestingly, are the same scenarios that we already saw regarding output verbosity).

The first scenario is about “fast” applications: if the program is expected to complete in a short amount of time—where short is defined as an amount of time in which the user will not context-switch—it is alright to pop up interactive prompts at any point during the execution of the application. The user will be there watching the command prompt, and he will be ready to answer such questions. Nothing wrong here.

The second scenario is about “slow” applications and, in this case, popping up interactive questions should be carefully considered. The problem with this scenario is that the user is accustomed to use applications that are not interactive. Just think about how many of the tools you use on a daily basis prompt you for details… one? zero? If the user is not aware that the application may require input at some point in the future, he is likely to launch the long-running process and go away for hours expecting everything to have completed by the time he returns. So you can imagine the problem now; there are very few things as frustrating as coming back hours later and realizing that the program is stuck awaiting for input, often to a trivial and irrelevant question.

The guidelines to follow if your CLI-based application requires interactive input and the operation of the application is expected to take a noticeable amount of time are quite simple:

  1. Ask for all input upfront without delay. Once you have gathered all input, comfort the user in that the rest of the procedure will not be interactive.

    An example of this would be an installer: it is often very easy to ask all installation settings upfront before proceeding to the long-running operation of actually setting up the software.

  2. If you cannot ask for all input upfront because it is not possible to predict the kind of questions that may pop up without actually doing complex and long-running work, attempt to do as much as possible without knowing the answers and postpone all questions for the very end of the procedure. However, because the user might have chained your tool to another one, you should clearly mention upfront that further manual input will be necessary.

    An example of this is the p4 update command: this command brings a working copy in sync with the master repository and, if any conflicts are found, their resolution is postponed until the end of the update so that the long-running process of fetching data from a remote server is not interrupted.

  3. If you cannot do any of the above due to the design of your program, clearly mention the fact that further input will be needed at the beginning of the execution. The user will then be able to expect followup questions and by setting up the right expectations you will minimize frustration.

  4. Last, but not least, provide command-line options to disable any interactive prompts either by allowing the user to provide the answers as flags or by assuming a default behavior. A common example is a flag to override existing destination files during a copy.

Be aware that these guidelines apply to any CLI-based interactive procedure; applications are just a specific case. For example: the FreeBSD ports system is especially guilty of unexpectedly popping up questions (e.g. configuration dialogs) in the middle of long-running procedures. Yes, these prompts can be disabled or batched upfront (with make config-recursive in our example), but because this is not the default behavior, any new user is probably bitten by a rather annoying behavior.

Go to posts index

Comments from the original Blogger-hosted post: