CLI tool
dotnet/cli-lab avatar
dotnet/cli-lab

dotnet-core-uninstall: removing .NET SDKs and runtimes cleanly

A guided tool will be provided to enable the controlled clean up of a system such that only the desired versions of the Runtime and SDKs remain.

780 stars73 forksC#MIT

At a glance

What is it?
dotnet-core-uninstall is the .NET Foundation command line tool for removing .NET Core SDKs, runtimes, ASP.NET Core runtimes and hosting bundles. Its most interesting design decision is negative: it is deliberately not a .NET global tool, because a runtime-dependent tool can end up trying to uninstall the runtime it is running on.
Who is it for?
Adopt dotnet-core-uninstall if your build agents accumulate SDK and runtime versions and you need to remove them deliberately rather than by hand, and check first whether the versions you delete are the ones your applications pin. Do not reach for it to remove a single runtime casually, because the tool's own documentation points out that you may not know which runtime an SDK bundles.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the tool removes from a .NET installation

The dotnet/cli-lab repository holds one tool, dotnet-core-uninstall, which is a command line program for uninstalling versions of the .NET Core SDK, the .NET Core Runtime, the ASP.NET Core Runtime and the Hosting Bundles. The repository description frames it as a guided tool for a controlled clean up of a system, so that only the desired versions of the runtimes and SDKs remain.

That list of four component types is the scope, and each one is a separate thing with its own version number on a developer machine. A developer box that has been in use for a few years tends to accumulate several SDK versions, each with a matching runtime, plus ASP.NET Core runtimes pulled in by web projects and hosting bundles installed for machine-wide serving. The tool exists to remove selected versions of those, rather than the whole dotnet directory, which is what deleting the folder by hand amounts to.

The code is C#, and the project is under the dotnet organisation with the .NET Foundation behind it. The official documentation lives at the aka.ms link given in the README, and the compiled tool is distributed through the GitHub releases page rather than from a package feed.

The repository layout follows the standard .NET repository shape, with src/ and test/ directories, a lab.sln solution, eng/ for the build engineering scripts, global.json for SDK pinning, a NuGet.config, and the Azure Pipelines definitions in .vsts-ci.yml and .vsts-pr.yml.

Why it is deliberately not a .NET global tool

The most substantive part of the README is the section asking why the tool is not a .NET Core Global Tool, and the answer is a design constraint rather than a preference.

Global tools are runtime-dependent applications, which means a global tool uses a version of the .NET Core Runtime installed on the machine. The purpose of this tool is to uninstall arbitrary SDKs and runtimes, so it may attempt to uninstall the version that is running the current process. When that happened, the team says they did not find a way to recover from the error and continue uninstalling the other SDKs and runtimes.

The failure mode is worth spelling out, because it explains the whole architecture. A tool that removes runtimes while depending on a runtime has a self-destruction hazard: it can pull the floor out from under itself, and in the middle of a cleanup run the machine ends up in a state that is worse than the one you started with.

The team also judged the situation particularly problematic because users might not be clear which runtimes are included in SDKs that are being uninstalled, or which runtime is currently in use. Both halves of that sentence are the user-facing risk of an automated cleanup, and the second half is the reason the tool ships as a standalone binary with its own runtime rather than as a package that depends on the thing it deletes.

Building the repository and the runtime identifier requirement

The build instructions are short because the project is a.NET repository with the usual build engineering layout. You run the build script at the root of the repository, build.sh or build.cmd depending on the platform, and you have to supply a runtime identifier:

bash
build /p:RID=win-x86

The runtime identifier is the point of that example. It tells the build which platform the produced binary should target, and the README links the runtime identifier catalogue in the Microsoft documentation for the full list. Building without one is not the path the project documents, which is unusual for a.NET repository and is a direct consequence of the runtime independence discussed above. A self-contained executable for a specific platform is what a tool like this needs to be.

Other build inputs sit at the repository root. Directory.Build.props, Directory.Build.targets and Directory.Build.rsp carry the shared MSBuild settings, and global.json pins the SDK version used to build, so a machine with several SDKs installed still builds the same way.

The result of a successful build is a tool you can run against a machine without installing anything else on it, which is the property that lets it remove a runtime safely.

Where the tool and its documentation live

Installation is a download rather than a package install, and the README is explicit about both places to go. The tool itself comes from the releases page of the repository, and the documentation for using it is at the aka.ms link, which the README describes as the place for more information about the use of the tool.

The README in the repository is short by design, and it does not enumerate the command line switches, the component types it can list, or the confirmation prompts it presents. If you are deciding whether the tool covers your situation, the release notes and the hosted documentation are the places to look, not this file. That is a real limitation for a reader who wants to know what the tool will and will not touch before running it, and it is a limitation of the repository rather than of the tool.

The two build scripts sit next to the sources:

bash
build.sh
build.cmd

A SECURITY.md file is present at the root, alongside CONTRIBUTING.md and the code of conduct, which the README notes is the code of conduct defined by the Contributor Covenant. The project asks people to try the tool, file issues, make feature requests and join design conversations, which is the normal posture for a .NET Foundation project of this kind.

The failure mode to plan for: runtimes inside SDKs

The risk the README names is not hypothetical for a shared build machine. A .NET SDK bundles a runtime, and the version of that runtime is tied to the SDK version, not to whatever else happens to be installed. Removing an SDK therefore removes a runtime as a side effect, and it may remove a runtime that an application on the machine depends on, or that the current tool process is using.

Two questions have to be answered before any cleanup, and the README states both of them: which runtimes are included in the SDKs that are going to be removed, and which runtime is currently in use. A tool that can answer the second question reliably has to be independent of the runtimes it manages, which is exactly what the decision not to ship as a global tool buys.

The second failure mode is more mundane. The tool removes four categories of component, and the ASP.NET Core Runtime and the Hosting Bundle are not the same thing. A hosting bundle is the machine-wide installation that makes ASP.NET available to a web server, so removing one on a machine serving applications affects those applications. The README does not walk through these interactions, which is why the safe procedure is to list what is installed, identify the versions that nothing needs, and remove those one at a time.

The alternative that was tried, and the manual route

The alternative approach is described in the project itself, which is more useful than naming a competing tool. The early prototype of the uninstall tool was a .NET Core Global Tool, and the team moved away from it for the reason described above: a global tool is bound to an installed runtime, so it can remove the runtime it is executing on and then fail without a way forward.

The manual route is the other obvious comparison. Deleting the versioned folders under the dotnet installation root removes an SDK or a runtime without any tooling, and it works. What it does not do is distinguish the components, tell you which runtime an SDK carries, or check what a given application is pinned to. The tool's argument is not that the manual route is impossible but that the information needed to do it safely is exactly what the tool provides.

A third option is simply to install fewer versions in the first place. On a machine provisioned from a script, pinning the SDK rather than letting it accumulate makes the cleanup question disappear. That is a pipeline decision rather than a tool, and it is often the better one for a build agent, but for a workstation that has already collected years of versions, the removal tool is the direct answer.

Licence, governance and the release cadence

The licence is MIT, and the README states it in one line: .NET Core, including this repository, is licensed under the MIT licence. The licence text is in LICENSE.TXT at the repository root. For a tool that deletes files from a machine, that permissiveness is unremarkable but worth noting, since it means redistribution of the tool itself is not restricted.

The governance is the .NET Foundation. The README says the tool is a .NET Foundation project and points to the .NET home repository for the other projects in the family, and the project follows the Foundation code of conduct. The build and test infrastructure sits in eng/ and in the Azure Pipelines definitions, and the .editorconfig, .config/ and .gitattributes files show the repository keeps the usual .NET formatting and tooling conventions.

On release cadence, the versions tell the story. The three most recent are 1.7.618124 from 2025-04-07, 1.7.656206 from 2025-11-13 and 1.7.661902 from 2026-01-08, so the build numbers move on every publish while the tool itself has stayed on the 1.7 line for a long stretch. The last push to the repository was on 2026-10-19, which is well after that release, so work has continued on the default branch without a new tagged build. For a tool that only has to work against a stable set of component versions, that is a reasonable pace, and it also means the newest tagged build is what most users will be running.

Editorial conclusion

Adopt dotnet-core-uninstall if your build agents accumulate SDK and runtime versions and you need to remove them deliberately rather than by hand, and check first whether the versions you delete are the ones your applications pin. Do not reach for it to remove a single runtime casually, because the tool's own documentation points out that you may not know which runtime an SDK bundles. Before running it, record the runtime identifier you build with, since the repository's build script requires one explicitly.

Frequently asked questions

What does dotnet-core-uninstall remove from a machine?

It uninstalls versions of the .NET Core SDK, the .NET Core Runtime, the ASP.NET Core Runtime and the Hosting Bundles. The goal stated in the repository is a controlled clean up so that only the desired versions remain.

Why is dotnet-core-uninstall not a .NET global tool?

Global tools depend on a runtime installed on the machine, and this tool uninstalls runtimes, so it could try to remove the runtime it is running on and then fail with no way to continue. The team says they did not find a way to recover from that error.

How do I build dotnet-core-uninstall from source?

Run the build script at the repository root, build.sh or build.cmd, and pass a runtime identifier, for example build /p:RID=win-x86 on Windows. The runtime identifier is required because the tool has to be independent of the runtimes it removes.

Where do I download dotnet-core-uninstall and find its documentation?

The README points to the releases page of the repository for the latest build, and to the documentation at the aka.ms/dotnet-core-uninstall-docs link for how to use it.

What licence is dotnet-core-uninstall released under?

It is MIT licensed, and the README states that .NET Core, including this repository, is licensed under the MIT licence, with the text in the LICENSE.TXT file at the repository root.

Official sources

  1. dotnet/cli-lab on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dotnet-cli-lab.svg)](https://hysenlabs.com/projects/dotnet-cli-lab)

Was this useful?