|
| 1 | +.NET Core Command-Line Tools UX Guidelines |
| 2 | +------------------------------------------- |
| 3 | + |
| 4 | +This document outlines the User Experience (UX) of the .NET Core command lline tools (CLI).These guideliens are intended for anyone that wants to add a new command to the CLI. |
| 5 | + |
| 6 | +The guidelines presented in this document have been adopted to provide a clear and concise |
| 7 | +command line syntax that is easy to learn, remember and work with, and that has an added benefit |
| 8 | +of being familiar to people who have used other command-line interfaces as well as existing |
| 9 | +Visual Studio users. |
| 10 | + |
| 11 | +## Naming the commands |
| 12 | + |
| 13 | +In the .NET Core CLI, commands should be **verbs**. This rule was adopted |
| 14 | +because most of the commands do *something*. |
| 15 | + |
| 16 | +Sub-commands are supported in the CLI, and they are usually nouns. A good |
| 17 | +example of this is the “dotnet add reference” command. If there is a need to add |
| 18 | +a subcommand, that subcommand should usually specialize what the parent command |
| 19 | +does. |
| 20 | + |
| 21 | +## Create/Read/Update/Delete (CRUD) commands |
| 22 | +New CRUD commands should be named according to the following logic: |
| 23 | + |
| 24 | +- Does the command work on data in the project (either properties or |
| 25 | + items)? If yes, then it should be added as a noun to the “dotnet |
| 26 | + add/list/remove/update”, e.g. “dotnet add foo”. |
| 27 | + |
| 28 | +- Does the command work on the solution (SLN) file? If yes, then it should be |
| 29 | + added as a verb to the “dotnet sln” command. |
| 30 | + |
| 31 | +- Does the command work on a completely new artifact (e.g. a new metadata file |
| 32 | + that is added in the future)? If yes, it should be created as a top level |
| 33 | + noun with all of the underlying operations defined as sub-commands. |
| 34 | + |
| 35 | +- If the command adds a new artifact to the project, it should become an item |
| 36 | + template that is dropped with “dotnet new” command. |
| 37 | + |
| 38 | + |
| 39 | +If none of the above applies, the proposal should clearly outline why none of |
| 40 | +the above applies and suggest an alternative naming that will be decided on |
| 41 | +during the process described above. |
| 42 | + |
| 43 | +If the command works on the project or solution, it must also accept an optional |
| 44 | +argument that specifies which project or solution to work on. The current |
| 45 | +convention is for that argument to follow the verb in the CRUD command. For |
| 46 | +example: |
| 47 | + |
| 48 | +> dotnet add \<PROJECT\> reference \<REFERENCE\> |
| 49 | +
|
| 50 | +All the existing CRUD commands have this argument defined and it will be passed |
| 51 | +to the sub-command as part of the overall options. The sub-command is expected |
| 52 | +to consider this optional argument. |
| 53 | + |
| 54 | +## Options |
| 55 | +CLI follows the [GNU convention](https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html) for options’ format, which is based on the POSIX |
| 56 | +standard. The summary is: |
| 57 | + |
| 58 | +- Command can have both short and long options. |
| 59 | + |
| 60 | +- The short format starts with a single dash (“-“), and has **exactly** one |
| 61 | + letter. The letter is usually the start letter of the longer form of the |
| 62 | + option, e.g. “-o” for “--output” or any of its words. This provides a good |
| 63 | + mnemonic. |
| 64 | + |
| 65 | + - **Example:** “dotnet build -o path/to/where/to/put/output” |
| 66 | + |
| 67 | +- The long format starts with double dashes (“--“) and can have one or more |
| 68 | + words. Multiple words are separated by a single dash (“-“). |
| 69 | + |
| 70 | + - **Example:** “dotnet test --test-case-filter” |
| 71 | + |
| 72 | +- The double dashes (“--“) on their own mark the **argument separator**. |
| 73 | + Anything after this option is passed verbatim to whatever the command starts |
| 74 | + as a sub-process. |
| 75 | + |
| 76 | + - **Example:** “dotnet run -- --app-arg-1” |
| 77 | + |
| 78 | +- Windows-style forward slash options (e.g. “/p”) are supported **only for |
| 79 | + MSBuild parameters.** |
| 80 | + |
| 81 | +- PowerShell-style single dashes with a word (e.g. “-Filter”) are **not |
| 82 | + supported**. |
| 83 | + |
| 84 | +- Help options are predefined as “-h \| --help” and those should be used. |
| 85 | + |
| 86 | +There are common options in the CLI that are reserved for certain concepts. The |
| 87 | +table below outlines those common options. If a command needs to accept the same |
| 88 | +options, it should use these and it must not replace their semantics (e.g. use |
| 89 | +“--output” to mean something different or redefine what “-f” means for just that |
| 90 | +command). |
| 91 | + |
| 92 | +| Long option | Short option | Description | |
| 93 | +|------------------|--------------|--------------------------------------------------------------| |
| 94 | +| \--framework | \-f | Specifies which framework (target) to use in the invocation. | |
| 95 | +| \--output | \-o | Specifies where the output of the command should be placed. | |
| 96 | +| \--runtime | \-r | Specifies the runtime ID (RID) to use in the invocation. | |
| 97 | +| \--configuration | \-c | Specifies the configuration to use in the invocation. | |
| 98 | +| \--verbosity | \-v | Specifies the verbosity level of the command. | |
| 99 | +| \--help | \-h | Shows the help for the command. | |
| 100 | + |
| 101 | +One special area is interacting with MSBuild. If a command has the need to do |
| 102 | +that, there are two additional requirements with regards to options: |
| 103 | + |
| 104 | +1. The commands need to be able to take “/p” parameters in addition to whatever |
| 105 | + other properties they require. |
| 106 | + |
| 107 | +2. If the command invokes a predefined MSBuild target, it needs to block |
| 108 | + “/t:\<target\>” and “/target:\<target\>” options and throw an error that is |
| 109 | + pre-defined in the CLI. |
| 110 | + |
| 111 | +It is important to note that commands that invoke user-specified targets |
| 112 | +should not be submitted to the CLI, since the CLI comes with “dotnet msbuild” |
| 113 | +command that does precisely that. |
| 114 | + |
| 115 | +## Arguments |
| 116 | +Arguments can have any name that authors of the commands being added need. We do have predefined |
| 117 | +argument names for the SLN file and project file. They are defined in the CLI |
| 118 | +source code and should be used if the command has the need to use those two |
| 119 | +arguments. |
| 120 | + |
| 121 | +## Help messages |
| 122 | +Help messages are automatically generated based on the arguments, options and |
| 123 | +command name. No other work should be required here apart from setting up the |
| 124 | +above mentioned and their descriptions. |
| 125 | + |
| 126 | +## Output |
| 127 | +For commands that are invoking MSBuild, the output will be controlled by MSBuild |
| 128 | +itself. |
| 129 | + |
| 130 | +In case of a long running operation, the command needs to provide a feedback |
| 131 | +mechanism to the user to help the user reason about whether the command has |
| 132 | +crashed or is just waiting for I/O. The feedback mechanism guidelines are below: |
| 133 | + |
| 134 | +1. Feedback should not require fonts with special glyphs for display. |
| 135 | +2. Pure text is acceptable (e.g. `Running background process...`) as a feedback mechanism. |
| 136 | +3. Spinners that conform to rule \#1 above are also acceptable. |
| 137 | + |
| 138 | + |
| 139 | +### Verbosity |
| 140 | +If the command interacts with MSBuild, it is required that it can accept a |
| 141 | +“--verbosity \| -v” argument and pass it to MSBuild verbatim. |
| 142 | + |
| 143 | +If the command’s verbosity levels cannot fit naturally in [MSBuild’s verbosity levels](https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference) or the command does not interact with MSBuild but still has an option to set the verbosity, it |
| 144 | +is the job of the command to map them in the most appropriate way. This way, the |
| 145 | +verbosity levels will be uniform across all commands which brings consistency to |
| 146 | +the toolset. |
| 147 | + |
| 148 | +#### Example |
| 149 | +As an example, let us consider a “dotnet configure” command. It doesn’t interact |
| 150 | +with MSBuild. I wish to have verbosity on it, but it really has only two levels: |
| 151 | +quiet (just successes or errors) and verbose (every operation) that I've defined for the command. To satisfy the |
| 152 | +above-mentioned requirement, in my command I would define the “--verbosity \| |
| 153 | +-v” option and would map the arguments in the following way: |
| 154 | + |
| 155 | +- “Quiet” gets mapped naturally to “quiet” |
| 156 | + |
| 157 | +- “Minimal”, “Normal” and “Diagnostic” get mapped into “verbose” |
0 commit comments