|
| 1 | +## CLI Guidelines for the dotnet CLI and related commands |
| 2 | + |
| 3 | +The `dotnet` CLI is the entrypoint for the .NET experience for all users, and as such it needs to be usable, performance, and consistent. |
| 4 | +This document outlines a series of UX guidelines, CLI grammars, and behavioral expectations for the `dotnet` CLI and related commands so that |
| 5 | +users have consistent experiences with all `dotnet` commands - even those that do not ship directly with the SDK like dotnet tools. |
| 6 | + |
| 7 | +- [CLI Guidelines for the dotnet CLI and related commands](#cli-guidelines-for-the-dotnet-cli-and-related-commands) |
| 8 | +- [Common Options](#common-options) |
| 9 | + - [Verbosity](#verbosity) |
| 10 | + - [Framework selection](#framework-selection) |
| 11 | + - [RID selection](#rid-selection) |
| 12 | + - [Explicit RID](#explicit-rid) |
| 13 | + - [OS-specific RID](#os-specific-rid) |
| 14 | + - [Architecture-specific RID](#architecture-specific-rid) |
| 15 | + - [SDK-matching RID](#sdk-matching-rid) |
| 16 | + - [MSBuild Properties](#msbuild-properties) |
| 17 | + - [Output modes/formatting](#output-modesformatting) |
| 18 | +- [NuGet-related options](#nuget-related-options) |
| 19 | + - [NuGet.Config File selection](#nugetconfig-file-selection) |
| 20 | + - [Package source management](#package-source-management) |
| 21 | + - [Additive package sources](#additive-package-sources) |
| 22 | + - [Exclusive package sources](#exclusive-package-sources) |
| 23 | + - [Feed Authentication support](#feed-authentication-support) |
| 24 | +- [Contextual behaviors](#contextual-behaviors) |
| 25 | + - [Implicit project/solution file discovery](#implicit-projectsolution-file-discovery) |
| 26 | + - [Determining interactive sessions](#determining-interactive-sessions) |
| 27 | +- [Interaction patterns](#interaction-patterns) |
| 28 | + - [Support structured (JSON) output](#support-structured-json-output) |
| 29 | + - [StdOut/StdErr usage](#stdoutstderr-usage) |
| 30 | + - [Advanced terminal output capabilities](#advanced-terminal-output-capabilities) |
| 31 | + - [Disabling advanced terminal output capabilities](#disabling-advanced-terminal-output-capabilities) |
| 32 | +- [References](#references) |
| 33 | + |
| 34 | +## Common Options |
| 35 | + |
| 36 | +These options are present on a (sub)set of commands, and should be consistent in their behavior and usage regardless of the context in which they are used. Users expect these kinds of options to be generally available and will often unconsciously reach for them as best guesses/first attempts. |
| 37 | + |
| 38 | +### Verbosity |
| 39 | + |
| 40 | +Short Form: `-v` |
| 41 | + |
| 42 | +Long Form: `--verbosity` |
| 43 | + |
| 44 | +Allowed values: `[q]uiet`, `[m]inimal`, `[n]ormal`, `[d]etailed`, `[diag]nostic` |
| 45 | + |
| 46 | +The CLI uses MSBuild verbosity level names. Commands should at minimum have support for three of these: |
| 47 | +* `quiet` mode should output nothing except the specific data output of the command. |
| 48 | +* `normal` mode should include high-priority messages in addition to the output |
| 49 | +* `diagnostic` mode should include all messages, including low-priority/debug/verbose messages. |
| 50 | + |
| 51 | +If you only support a subset of these values, map the missing ones to the closest semantic match. |
| 52 | +For example, if you don't support `minimal`, map it to `quiet`. If you don't support `detailed`, map it to `diagnostic`. |
| 53 | + |
| 54 | +For feedback on when to write to stderr or stdout, see the [StdOut/StdErr usage](#stdoutstderr-usage) section. |
| 55 | +For guidance on laying out output for users, see the [Advanced terminal output capabilities](#advanced-terminal-output-capabilities) section. |
| 56 | + |
| 57 | +### Framework selection |
| 58 | + |
| 59 | +Short form: `-f <TFM>` |
| 60 | + |
| 61 | +Long form: `--framework <TFM>` |
| 62 | + |
| 63 | +### RID selection |
| 64 | + |
| 65 | +#### Explicit RID |
| 66 | + |
| 67 | +Short form: `-r <RID>` |
| 68 | + |
| 69 | +Long form: `--runtime <RID>` |
| 70 | + |
| 71 | +#### OS-specific RID |
| 72 | + |
| 73 | +Short form: `-o <OS>` |
| 74 | + |
| 75 | +Long form: `--os <OS>` |
| 76 | + |
| 77 | +#### Architecture-specific RID |
| 78 | + |
| 79 | +Short form: `-a <ARCH>` |
| 80 | + |
| 81 | +Long form: `--arch <ARCH>` |
| 82 | + |
| 83 | +#### SDK-matching RID |
| 84 | + |
| 85 | +Short form: `--ucr` |
| 86 | + |
| 87 | +Long form: `--use-current-runtime` |
| 88 | + |
| 89 | +### MSBuild Properties |
| 90 | + |
| 91 | +Short form: `-p <MSBuild property expression(s)>` |
| 92 | + |
| 93 | +Long form: `--property <MSBuild property expression(s)>` |
| 94 | + |
| 95 | +If at all possible we _strongly encourage_ not parsing the `<MSBuild property expression(s)>` syntax yourself. It is much more complex than you think it is. |
| 96 | +At _best_ you should detect and forward along any of these arguments to any MSBuild invocations you make. |
| 97 | + |
| 98 | +### Output modes/formatting |
| 99 | + |
| 100 | +Long form: `--format` |
| 101 | + |
| 102 | +Allowed values: `text`, `json`, others are relevant for your use case |
| 103 | + |
| 104 | +Users value scriptability of CLI commands, and some form of structured output is key to supporting this. JSON is a common structured output format, |
| 105 | +but other formats may be more appropriate for your use case. If you use a structured format like `csv`, please for the love of Turing use a proper |
| 106 | +CSV writer and not just a hand-rolled comma-separated list of values so that you don't break [RFC 4180][4180]. |
| 107 | + |
| 108 | +When you write JSON outputs you are explicitly creating a data contract with users. Be _very intentional_ about changes to the format of this contract. |
| 109 | +Design up-front for extensibility. For example, instead of just emitting a list of versions as an array of strings, consider emitting them as an |
| 110 | +array of objects with a named property: `[{"workload_set_version": "1.0.0"}]` instead of `"1.0.0"`. |
| 111 | + |
| 112 | +## NuGet-related options |
| 113 | + |
| 114 | +NuGet is key to delivering package management and security functionality to end users. We should strive to make the NuGet experience as consistent |
| 115 | +as possible across all `dotnet` commands, by following the same patterns and behaviors. |
| 116 | + |
| 117 | +### NuGet.Config File selection |
| 118 | + |
| 119 | +Long form: `--config-file` |
| 120 | + |
| 121 | +Default value: directory-based probing implemented in the [`NuGet.Configuration`][nuget-configuration] library |
| 122 | + |
| 123 | +### Package source management |
| 124 | + |
| 125 | +There are two semantics of behaviors that we have adopted in the dotnet CLI: additive and exclusive package sources. |
| 126 | + |
| 127 | +#### Additive package sources |
| 128 | + |
| 129 | +Long form: `--add-source <source_uri>` |
| 130 | + |
| 131 | +When this is used, you should load the sources list from the NuGet configuration (using the [libraries][nuget-configuration]) and create a |
| 132 | + new `PackageSource` to add to that set. This should be additive and not destructive. |
| 133 | + |
| 134 | +#### Exclusive package sources |
| 135 | + |
| 136 | +Long form: `--source <source_uri>` |
| 137 | + |
| 138 | +When this is used, you should ONLY use the sources supplied by this parameter and ignore any sources in the NuGet configuration. This is useful |
| 139 | +for scenarios where you want to ensure that you're only using a specific source for a specific operation. |
| 140 | + |
| 141 | +### Feed Authentication support |
| 142 | + |
| 143 | +Long form: `--interactive <bool>` |
| 144 | + |
| 145 | +Default value: `true` when in an [interactive session](#determining-interactive-sessions), `false` otherwise |
| 146 | + |
| 147 | +NuGet authentication often requires some interactive action like going to a browser page. You should 'prime' the NuGet credential services by calling |
| 148 | +`NuGet.Credentials.DefaultCredentialServiceUtility.SetupDefaultCredentialService(ILogger logger, bool nonInteractive)` with the value of `nonInteractive` |
| 149 | +being the inverted value of this parameter. This will ensure that the credential service is set up correctly for the current session type. |
| 150 | + |
| 151 | +## Contextual behaviors |
| 152 | + |
| 153 | +### Implicit project/solution file discovery |
| 154 | + |
| 155 | +When a command is run in a directory that contains a project or solution file, the command should automatically use that file as the |
| 156 | +target for the command. |
| 157 | +If the command is run in a directory that contains multiple project or solution files, the command should fail with an error message |
| 158 | +indicating that the user should specify which file to use. |
| 159 | + |
| 160 | +Consider the use of an option like `--project <path to project or solution>` to allow for executing the command against a specific |
| 161 | +project or solution file at an arbitrary location - but be aware that many mechanisms in .NET are hierarchical from Current Working |
| 162 | +Directory and may have different behaviors when used in this detached mode. |
| 163 | + |
| 164 | +### Determining interactive sessions |
| 165 | + |
| 166 | +Commands should be able to determine if they are running in an interactive session or not. This is important for determining |
| 167 | + |
| 168 | +* whether to prompt the user for input or not, |
| 169 | +* what the default value for NuGet's `--interactive` option should be |
| 170 | +* how to format output (along with terminfo probing) |
| 171 | + |
| 172 | +In general the easiest way to check this is if the `stdin` file descriptor is a TTY, or in .NET Terms: `Console.IsInputRedirected` is `false`. |
| 173 | + |
| 174 | +## Interaction patterns |
| 175 | + |
| 176 | +### Support structured (JSON) output |
| 177 | + |
| 178 | +All commands should support structured (JSON) output. This is a key part of the CLI experience and allows for easier scripting and automation of the CLI. |
| 179 | +See the [`--format`](#output-modesformatting) option for more details. When structured output is requested, the command should output the structured |
| 180 | +data to `stdout` and any non-structured data to `stderr` - this is to make it easier to parse the structured data without having to deal with the |
| 181 | +non-structured data. |
| 182 | + |
| 183 | +### StdOut/StdErr usage |
| 184 | + |
| 185 | +StdErr is a perfectly reasonable output channel. It should be the default channel for |
| 186 | + |
| 187 | +* warnings and errors |
| 188 | +* verbose logging |
| 189 | +* outputs that aren't directly related to the command's primary purpose - for example 'workload manifest update' notices |
| 190 | + |
| 191 | +There is some contention here because older versions of PowerShell treat any stderr output as an error, but this is not the |
| 192 | +case in modern PowerShell (> 7.3) via the [$PSNativeCommandUseErrorActionPreference](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_preference_variables#psnativecommanduseerroractionpreference) preference setting. |
| 193 | + |
| 194 | +### Advanced terminal output capabilities |
| 195 | + |
| 196 | +You are encouraged to make use of advanced terminal capabilities like colors, weights, and other formatting options to make your output |
| 197 | +more readable. Instead of writing entire lines of text as a single color, consider how the use of color and formatting present the |
| 198 | +output to the user. When performing long-running operations, provide a progress bar or ticker or some other form of feedback to the user. |
| 199 | + |
| 200 | +DO NOT rely entirely on color to convey information. Colorblind users will not be able to distinguish between different colors. Instead, |
| 201 | +consider color, symbols, and layout holistically to convey information. |
| 202 | + |
| 203 | +### Disabling advanced terminal output capabilities |
| 204 | + |
| 205 | +If stderr or stdout are redirected, do not emit color/weight/progress on those channels. |
| 206 | +If NO_COLOR is set, do not emit color/weight/progress on any channel. |
| 207 | +If TERM is `dumb`, do not emit color/weight/progress on any channel. |
| 208 | + |
| 209 | +## References |
| 210 | + |
| 211 | +[Command-line interface guidelines][clig] |
| 212 | + |
| 213 | +[clig]: https://clig.dev/ |
| 214 | +[4180]: https://www.loc.gov/preservation/digital/formats/fdd/fdd000323.shtml |
| 215 | +[nuget-configuration]: https://nuget.org/packages/NuGet.Configuration |
| 216 | +[pwsh-output-streams]: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_output_streams |
0 commit comments