apt or brew, unpacking raw tarballs into custom directories, running elevated Windows installers, or scripting around dotnet-install.ps1 and dotnet-install.sh. Worse, once those SDKs and runtimes landed on your drive, cleaning up obsolete servicing builds often required a separate utility—or manual folder surgery.
On October 15, 2026, Microsoft officially moved to end that friction by announcing the public preview of dotnetup, a cross-platform toolchain manager for.NET. Introduced in a Microsoft.NET Blog post by Program Manager Chet Husk, dotnetup brings a dedicated, user-local version manager to the.NET ecosystem, explicitly drawing inspiration from tools that developers in other languages have relied on for years, such as Rust’s rustup and Node’s nvm.
While dotnetup has been quietly taking shape in public repositories—even bootstrapping the .NET SDK repository’s own main branch builds since its soft internal launch in June 2026 —the public preview opens the workflow to everyday developers and CI/CD engineers. Here is a complete technical breakdown of how dotnetup works, how it handles Windows and cross-platform environments, its exact command workflows, and the critical caveats you need to know before adopting it.
Why.NET Needed a Dedicated Toolchain Manager
Historically,.NET’s installation story suffered from a split personality. On Windows, Visual Studio or standalone MSI/EXE installers typically dropped SDKs and runtimes into system-wide Program Files directories, requiring administrator privileges. On Linux and macOS, developers bounced between distribution feeds, Homebrew formulas, and standalone install scripts.
That patchwork created four recurring headaches for developers and IT administrators:
- Privilege Collisions: System-wide package managers and installers require
sudoor local Administrator rights, which creates friction on locked-down enterprise workstations and containerized build agents. - State and Cleanup Drift: While
dotnet-installscripts are great for pulling down binaries, they do not track why a version was installed or clean up old monthly servicing releases when a newer patch arrives. - Nightly and Preview Friction: Testing a daily runtime build or a preview SDK meant hunting down archive links on GitHub, unpacking them into isolated folders, and manually manipulating
PATHorDOTNET_ROOTenvironment variables. - Inconsistent Cross-Platform UX: The commands used to provision a developer laptop on macOS bore no resemblance to provisioning an Ubuntu container or a Windows PowerShell environment.
According to Microsoft’s announcement and the accompanying Microsoft Learn documentation, dotnetup solves these problems by storing all SDKs, runtimes, and tracking metadata inside user-owned directories rather than system-managed paths. Even more importantly, it separates installation requirements (your intent, such as tracking the .NET 10 channel or honoring a repository's global.json) from the concrete resolved versions on disk.
| Capability | Legacy dotnet-install Scripts | System Installers (apt, brew, MSI) | dotnetup (Public Preview) |
|---|---|---|---|
| Default Privilege Level | User-local (or custom path) | Admin / sudo required | User-local (non-admin by default) |
| Tracks Channel Intent | No (one-shot download) | Limited to OS feed cadence | Yes (latest, 10.0, preview, daily) |
| Automatic Garbage Collection | No | Varies by package manager | Yes (removes unreferenced versions on update) |
| Signature & Checksum Validation | Basic / manual | Handled by OS package manager | Built-in validation |
global.json Integration | Partial (reads version, no state tracking) | None | Native requirement tracking & optional file updating |
| Unified Cross-Platform CLI | Separate .sh and .ps1 syntax | Completely different per OS | Identical dotnetup CLI across OSes |
Summary: By decoupling user-level toolchain management from OS-level package managers and stateless download scripts, dotnetup brings stateful, non-admin lifecycle management to.NET.
The Windows Nuance: User-Local Now, System-Wide Later
Before Windows developers rush to replace their entire Visual Studio SDK setup, it is important to understand a key architectural boundary in this initial public preview.
Right now, dotnetup is strictly built for non-admin, user-local operation. Everything it downloads and manages lives inside your user profile directory. However, on Windows, system-level.NET installations (those living in C:\Program Files\dotnet installed via Visual Studio, Winget, or standalone installers) are ubiquitous.
Chet Husk notes in the launch announcement that dotnetup does not currently manage system-level Windows installations, though adding support for Windows admin installers is explicitly on the roadmap for a future release. In the meantime, Microsoft’s dotnet/sdk documentation notes that dotnetup setup can detect SDKs and runtimes in the system-managed.NET directory and install matching native-architecture versions into the dotnetup-managed user directory. Furthermore, when performing runtime updates on Windows, dotnetup properly accounts for Windows Desktop runtime requirements alongside the core .NET and ASP.NET Core runtimes.
Getting Started: Installation and Environment Modes
Microsoft provides one-line bootstrap scripts for macOS, Linux, and PowerShell (pwsh) that download the dotnetup binary.
- PowerShell (
pwsh):
irm [url]https://aka.ms/dotnetup/get-dotnetup.ps1[/url] | iex - Linux (Bash):
curl -fsSL [url]https://aka.ms/dotnetup/get-dotnetup.sh[/url] | bash - macOS (Zsh):
curl -fsSL [url]https://aka.ms/dotnetup/get-dotnetup.sh[/url] | zsh
Once the binary is on your machine, you have three distinct ways to initialize and expose the managed .NET toolchain, as detailed in Microsoft Learn’s dotnetup overview:
1. Interactive Initialization (Recommended for Workstations)
Running the standard initialization command launches an interactive prompt:
dotnetup init
By default, init suggests installing the latest stable SDK channel and configuring Terminal Mode, which updates your shell profile so that dotnet is immediately available in your terminal sessions.
2. Non-Interactive Setup (Ideal for Scripts and CI)
If you are provisioning a machine or container via an automated script and cannot answer interactive prompts, you can install a channel and configure your shell profile in two discrete steps:
dotnetup install latest
dotnetup env set shell
(Note: According to the Microsoft Learn CLI reference, invoking a bare dotnetup command with no arguments also runs the SDK install workflow.) After setting the shell environment, you either run the outputted shell-specific refresh command or open a new terminal session.
3. Zero-Profile-Modification Mode (env set none)
What if you are testing dotnetup on a machine where you already have a delicately balanced system-wide .NET installation and you refuse to let a preview tool touch your PATH or shell profile? Microsoft built an escape hatch specifically for this scenario:
dotnetup install latest
dotnetup env set none
In this mode, dotnetup is placed on your PATH, but the managed dotnet binary is not. Existing system-wide .NET installations remain your default. Whenever you want to invoke the dotnetup-managed toolchain, you use the forwarding command:
dotnetup dotnet --version
dotnetup dotnet build
To inspect your environment at any time, run:
dotnetup list
If you are building automation scripts around dotnetup and need to parse the state programmatically, the tool supports JSON output:
dotnetup list --format json
Summary: Whether you want an interactive setup, an unattended CI bootstrap, or a quarantined installation that never touches your default PATH, dotnetup provides explicit environment modes to match your risk tolerance.
Tracking Intent: Channels, Pinning, and Monthly Servicing
The standout architectural feature of dotnetup is how it handles monthly.NET servicing updates (Patch Tuesday for developers). Instead of forcing you to manually download 10.0.4 when 10.0.3 is superseded—and then manually delete 10.0.3—dotnetup tracks your intent.
When you request an installation, you can specify a rolling channel or an exact version:
latest: Tracks the latest stable SDK, including jumping to new major releases when they ship.10.0: Tracks servicing and feature updates strictly within the.NET 10 channel.10.0.3: Pins an exact version. It will never advance during an update.
When Microsoft ships its monthly servicing updates, refreshing your local development machine requires a single command:
dotnetup update
Granular Update Scopes and Garbage Collection
According to Microsoft Learn’s update documentation, dotnetup gives you fine-grained control over what gets refreshed:
dotnetup update: Updates all tracked SDK and runtime requirements across your manifest.dotnetup sdk update: Updates tracked SDK requirements only.dotnetup sdk update --all: Updates both SDK and runtime requirements.dotnetup runtime update: Updates tracked runtime requirements only (covering core.NET, ASP.NET Core, and, on Windows, Windows Desktop runtimes).dotnetup update --install-path D:\tools\dotnet: Restricts the update operation to a specific installation root.
If you only need a specific runtime flavor—such as refreshing the ASP.NET Core runtime on.NET 10 without pulling down the entire SDK—you can target it directly:
dotnetup runtime install [email][email protected][/email]
Crucially, after a successful update, dotnetup automatically runs garbage collection. Any previously installed SDK or runtime component that is no longer referenced by an active channel or an exact-version requirement is automatically removed from your disk. If another tracked channel or pinned requirement still depends on an older version, dotnetup leaves it intact. Furthermore, each requirement is processed independently during an update; if one channel fails to resolve or download, dotnetup continues processing the remaining requirements before reporting the failure at the end.
To remove a tracked channel or pinned version entirely, run the corresponding sdk uninstall or runtime uninstall command, which removes the requirement and cleans up the orphaned binaries. And to update the dotnetup binary itself as new preview features ship, run:
dotnetup self update
Testing Previews, Daily Builds, and Managing global.json
For library authors and enterprise teams preparing for upcoming.NET releases (such as.NET 11), testing preview and nightly builds has historically been a chore. dotnetup treats pre-release channels as first-class citizens that sit cleanly alongside your stable toolchains:
- Install the latest preview SDK:
dotnetup sdk install preview - Install the latest daily (nightly) runtime build to verify a bug fix:
dotnetup runtime install daily - Install an entire daily SDK toolchain:
dotnetup sdk install daily
The global.json Workflow (and a Important Caveat)
In professional.NET repositories, global.json is the source of truth that keeps every developer and build agent on a deterministic SDK version. dotnetup integrates directly with global.json files, allowing you to navigate into a repository and install the exact SDK required by the nearest global.json.
However, Microsoft Learn’s documentation highlights two critical operational details that development teams must keep in mind:
- Updating does not rewrite
global.jsonby default: Whendotnetuptracks an SDK requirement sourced from a repository’sglobal.json, runningdotnetup sdk updatewill install the newly resolved SDK version on disk, but it will not edit your repository'sglobal.jsonfile unless you explicitly pass the--update-global-jsonflag:
dotnetup sdk update --update-global-json - Syncing manual
global.jsonedits: Becausedotnetup updateprocesses stored requirements before garbage collection refreshes changedglobal.jsonsources, if you manually edit a repository’sglobal.jsonfile, you should rundotnetup sdk installinside that repository before running an update. Otherwise, your first update pass may still process the old cached requirement.
Critical Realities: Security, CI/CD, and Roadmap
As exciting as a unified.NET version manager is, veteran IT administrators and lead developers know to read the fine print. Based on Microsoft’s announcement and documentation, here are the practical boundaries of dotnetup today:
- Updating Your Machine Does Not Patch Shipped Apps: Chet Husk explicitly reminds developers of a fundamental.NET deployment rule: updating the SDKs and runtimes on your development machine (or build server) helps you build and test against monthly security patches, but it does not patch applications you have already deployed. Specifically, if you publish self-contained applications (which bundle the.NET runtime alongside your executable), you must rebuild, republish, and redeploy those applications after running
dotnetup updatefor the security fixes to reach production. - Performance and Validation Claims: Microsoft states that
dotnetupprovides signature and checksum validation of installed SDKs and runtimes, as well as faster installation of multiple components compared todotnet-installscripts. While welcome improvements, Microsoft has not yet published formal benchmark numbers or architectural security whitepapers detailing the validation pipeline in the launch post. - Preview Status:
dotnetupis currently in public preview. Microsoft Learn cautions that commands, options, and behaviors may change before general availability, and the formal support lifecycle for the GA release is not yet finalized. - CI/CD and AI Agent Roadmap: Because
dotnetuprequires zero root/admin privileges and runs non-interactively, you can use it in containerized or ephemeral CI workers right now. Looking ahead, Microsoft plans to integratedotnetupdirectly into official GitHub Actions and Azure DevOps tasks—replacing the underlyingdotnet-installscript implementations those pipelines rely on today. Additionally, the team plans to build out "agent skills" so that automated AI coding assistants reach fordotnetupnaturally when configuring.NET environments.
Bottom Line for Windows and.NET Developers
For developers who split their time between Windows, WSL2, macOS, and Linux containers—or anyone tired of hunting down orphaned SDK folders eating up gigabytes of SSD space—dotnetup is one of the most practical quality-of-life improvements the.NET CLI team has delivered in years. While Windows developers who rely heavily on Visual Studio's system-wide Program Files installations will need to wait for future roadmap updates to manage those elevated installs via dotnetup, its user-local mode (dotnetup env set none or shell profile integration) is ready for testing today.
Have you spun up dotnetup in your local PowerShell profile or WSL2 instance yet, or are you waiting for system-wide Windows installer support to land? Let us know how it handles your global.json workflows in the WindowsForum community discussions!
References
- Introducing dotnetup: A toolchain manager for .NET .NET Blog · 2026-10-15T16:50:00+00:00
- (Awareness) .NET SDK `main` branch is using `dotnetup` to `build` · Issue #54601 · dotnet/sdk github.com
- sdk/documentation/general/dotnetup at release/dnup · dotnet/sdk github.com