Environment Variables, Completion and Telemetry
|
This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The C# Reference bibliography lists the reference material consulted while preparing these pages. |
Besides its commands, the dotnet CLI is configured by environment variables, offers shell completion, reports
telemetry, and can describe itself as JSON for other tools. This page covers those parts with .NET SDK 10.0.402 on
Linux, showing the variables that change behaviour in practice.
Environment variables
| Variable | Effect |
|---|---|
|
Where an apphost ( |
|
|
|
|
|
Historical; no longer supported since .NET Core 3.0. |
|
Runtime roll-forward policy for apps started from this environment ( |
|
Turn the CLI’s native (AOT-compiled) fast path for common commands on or off. |
|
Use MSBuild Server (opt-in on .NET 10, on by default in .NET 11). |
|
The NuGet global-packages folder (Global Packages and Cache Folders). |
|
The CLI’s display language. |
Source: .NET environment variables: SDK and CLI variables, DOTNET_NOLOGO, DOTNET_CLI_TELEMETRY_OPTOUT, DOTNET_SKIP_FIRST_TIME_EXPERIENCE, DOTNET_CLI_ENABLEAOT.
DOTNET_ROLL_FORWARD and DOTNET_ROOT
An application built for net7.0 (out of support, so the build warns NETSDK1138) on a machine with the .NET 8, 9 and
10 runtimes, where .NET is installed in a user folder rather than /usr/share/dotnet:
./bin/Debug/net7.0/Rf
DOTNET_ROLL_FORWARD=Major ./bin/Debug/net7.0/Rf
env -u DOTNET_ROOT DOTNET_ROLL_FORWARD=Major ./bin/Debug/net7.0/Rf
You must install or update .NET to run this application.
App: ~/rf/bin/Debug/net7.0/Rf
Architecture: x64
Framework: 'Microsoft.NETCore.App', version '7.0.0' (x64)
.NET location: ~/.dotnet
The following frameworks were found:
…
Running on .NET 8.0.32
You must install .NET to run this application.
App: ~/rf/bin/Debug/net7.0/Rf
Architecture: x64
App host version: 7.0.20
.NET location: Not found
-
The default policy,
Minor, never moves an app to a new major version, so the .NET 7 app did not start. -
DOTNET_ROLL_FORWARD=Majorlet it run on the lowest higher major runtime installed — 8.0.32, not 10. Use it to keep an old tool running, not as a deployment strategy; the app should be retargeted. -
Without
DOTNET_ROOT, the apphost looked only in the default locations and found no .NET at all. A user-folder installation (thedotnet-installscript, CI) needsDOTNET_ROOTfor apphosts;dotnet app.dlldoes not, because the muxer knows where it is.
Source: DOTNET_ROOT, DOTNET_ROLL_FORWARD.
The first run
The first command on a new user profile prints a banner and creates the ASP.NET Core development certificate:
Welcome to .NET 10.0!
---------------------
SDK Version: 10.0.402
Telemetry
---------
The .NET tools collect usage data in order to help us improve your experience. It is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.
Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry
----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https
In CI, set DOTNET_NOLOGO=1 and DOTNET_CLI_TELEMETRY_OPTOUT=1 for the whole job, so the banner does not appear in
logs and nothing is sent (CI Builds and Caching).
Source: .NET environment variables.
Telemetry
The CLI sends usage data for each SDK command (dotnet build, dotnet run, …; running an app with dotnet app.dll
sends nothing): the command and the options used, the SDK and OS versions, whether global.json was valid, MSBuild
task-host statistics, hashed values of selected MSBuild properties, and exception information when the CLI crashes.
The installer also sends one entry on a successful installation. Two more facts are derived from environment variables
whose values are not collected:
-
CI detection — whether well-known CI variables (
TF_BUILD,GITHUB_ACTIONS,CI, …) are set. -
LLM detection — whether the CLI was started by an AI agent, from
GITHUB_COPILOT_CLI_MODE(copilot),CLAUDECODE(claude),CURSOR_EDITOR(cursor) orGEMINI_CLI(gemini); several matches are concatenated.
Opt out with DOTNET_CLI_TELEMETRY_OPTOUT=1 (or true), set before the first command. In .NET 11 the CLI moves its
telemetry pipeline to OpenTelemetry; the opt-out variable is unchanged.
Tab completion
dotnet complete call per keystroke:dotnet completions script bash | head -9
dotnet completions script bash | wc -l
#!/usr/bin/env bash
_dotnet() {
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
COMPREPLY=()
opts="build build-server clean format fsi msbuild new nuget pack package project publish reference restore run solution store test tool vstest help sdk workload completions --help --diagnostics --version --info --list-sdks --list-runtimes"
2347
The shells are bash, fish, nushell, pwsh and zsh (SDK 10.0.402 already generated fish completions, which
the .NET 11 what’s-new page lists as new). Add eval "$(dotnet completions script bash)" to ~/.bashrc, or the
equivalent for the shell. The older dynamic scripts, which call dotnet complete and work with every SDK version,
remain available for shells and versions without native scripts.
--cli-schema
Every command describes its arguments and options as JSON with --cli-schema (.NET 10), for tools, agents and IDEs
that build dotnet command lines:
dotnet build --cli-schema | head -20
{
"name": "build",
"version": "10.0.402",
"description": ".NET Builder",
"hidden": false,
"arguments": {
"PROJECT | SOLUTION | FILE": {
"description": "The project or solution or C# (file-based program) file to operate on. If a file is not specified, the command will search the current directory for a project or solution.",
"order": 0,
"hidden": false,
"valueType": "System.String[]",
"hasDefaultValue": false,
"arity": {
"minimum": 0
}
}
},
"options": {
"--arch": {
dotnet build declared 33 options. Pass-through MSBuild switches (-p, -bl) are not in the schema.
Elevated access
Only a few commands are meant to run elevated (sudo, an administrator prompt): installing or running tools that
need it (dotnet tool install --tool-path into a system folder), dotnet run --no-build, and the uninstall tool.
Commands that run MSBuild — restore, build, run — should not be run elevated: they write obj, bin and
the NuGet caches, and switching between root and a normal account leaves files the normal account cannot overwrite.
Running everything as root, as in a container, is fine as long as nothing switches back.
Source: Elevated access for dotnet commands.
Common mistakes
-
Apphosts failing in CI with "You must install .NET" — export
DOTNET_ROOTfor user-folder installs. -
DOTNET_ROLL_FORWARD=Majorset globally — every old app silently runs on a newer major runtime. -
Opting out of telemetry after the first command — set the variable before it.
-
sudo dotnet build— root-ownedobjfolders and caches.