5th chunk of `doc/manual/source/development/cli-guideline.md`
ad8171da3fdba9374ab0ab2e9d0fc5bca6deec5556bf10450000000100000fb5
But users won't stay beginners for long and what was once useful might quickly
become annoying. There is no golden rule that we can give in this guideline
that would make it easier how to draw a line and find best compromise.
What we would encourage is to **build prototypes**, do some **user testing**
and collect **feedback**. Then repeat the cycle few times.
First design the *happy path* and only after your iron it out, continue to work
on **edge cases** (handling and displaying errors, changes of the output by
certain `OPTIONS`, etc…)
## Follow best practices
Needless to say we Nix must be a good citizen and follow best practices in
command line.
In short: **STDOUT is for output, STDERR is for (human) messaging.**
STDOUT and STDERR provide a way for you to output messages to the user while
also allowing them to redirect content to a file. For example:
```shell
$ nix build > build.txt
------------------------------------------------------------------------
Error! Attribute `bin` missing at (1:94) from string.
------------------------------------------------------------------------
1| with import <nixpkgs> { }; (pkgs.runCommandCC or pkgs.runCommand) "shell" { buildInputs = [ (surge.bin) ]; } ""
```
Because this warning is on STDERR, it doesn’t end up in the file.
But not everything on STDERR is an error though. For example, you can run `nix
build` and collect logs in a file while still seeing the progress.
```
$ nix build > build.txt
Evaluated 1234 files in 1.2 seconds
Downloaded python3.8-poetry 1.2.3 in 5.3 seconds
Downloaded python3.8-requests 1.2.3 in 5.3 seconds
------------------------------------------------------------------------
Press `v` to increase logs verbosity
|> `?` to see other options
------------------------------------------------------------------------
Learn something new with every build...
|> See last logs of a build with `nix log --last` command.
------------------------------------------------------------------------
Evaluated my-project 1.2.3 in 14.43 seconds
Downloading [12 / 200]
|> firefox 1.2.3 [#########> ] 10Mb/s | 2min left
Building [2 / 20]
|> glibc 1.2.3 -> buildPhase: <last log line>
------------------------------------------------------------------------
```
## Errors (WIP)
**TODO**: Once we have implementation for the *happy path* then we will think
how to present errors.
## Not only for humans
Terse, machine-readable output formats can also be useful but shouldn’t get in
the way of making beautiful CLI output. When needed, commands should offer a
`--json` flag to allow users to easily parse and script the CLI.
When TTY is not detected on STDOUT we should remove all design elements (no
colors, no emojis and using ASCII instead of Unicode symbols). The same should
happen when TTY is not detected on STDERR. We should not display progress /
status section, but only print warnings and errors.
## Dialog with the user
CLIs don't always make it clear when an action has taken place. For every
action a user performs, your CLI should provide an equal and appropriate
reaction, clearly highlighting the what just happened. For example:
```shell
$ nix build
Downloaded python3.8-poetry 1.2.3 in 5.3 seconds
Downloaded python3.8-requests 1.2.3 in 5.3 seconds
...
Success! You have successfully built my-project.
$
```
Above command clearly states that command successfully completed. And in case
of `nix build`, which is a command that might take some time to complete, it is
equally important to also show that a command started.
## Text alignment
Text alignment is the number one design element that will present all of the
Nix commands as a family and not as separate tools glued together.
The format we should follow is:
```shell
$ nix COMMAND
VERB_1 NOUN and other words
VERB__1 NOUN and other words
|> Some details
```
Few rules that we can extract from above example:
- Each line should start at least with one space.