Managed dotnet-install for developers who want the familiar shell-script workflow in a compiled, NativeAOT-oriented CLI.
dotnet-install resolves .NET release metadata, builds an install plan, downloads the selected SDK or runtime artifact, and runs the install flow from a single command. The project aims to stay close to dotnet-install.sh and dotnet-install.ps1 while making the developer experience easier to inspect, test, and automate.
You can use dotnet-install in two supported ways:
- As a .NET global or local tool from NuGet
- As a single native executable downloaded from a GitHub release
Install globally:
dotnet tool install --global spark.dotnet-installInstall into a local tool manifest:
dotnet new tool-manifest
dotnet tool install --local spark.dotnet-installUpdate an existing global install:
dotnet tool update --global spark.dotnet-installEach GitHub release publishes a single-file executable per RID:
dotnet-install-<version>-win-x64.exedotnet-install-<version>-win-arm64.exedotnet-install-<version>-linux-x64dotnet-install-<version>-linux-arm64dotnet-install-<version>-linux-musl-x64dotnet-install-<version>-linux-musl-arm64dotnet-install-<version>-osx-x64dotnet-install-<version>-osx-arm64
Download the asset that matches the target machine, place it in a directory of your choice, and run it directly. On Linux and macOS, mark it executable first:
mv ./dotnet-install-<version>-<rid> ./dotnet-install
chmod +x ./dotnet-install
./dotnet-install --help
./dotnet-install versionIf you want to invoke the release binary as dotnet-install from any shell, rename it to dotnet-install (or dotnet-install.exe on Windows) and place that file in a directory that is already on your shell PATH.
See docs/github-releases.md for a release-first setup guide.
Install the tool:
dotnet tool install --global spark.dotnet-installThen use the commands most developers need first:
# Explore the CLI
dotnet-install --help
# See the tool version
dotnet-install version
# Preview what would be installed
dotnet-install --dry-run --channel LTS
# Install the latest SDK in a feature band
dotnet-install --version 10.0.x
# Install the SDK pinned by global.json
dotnet-install --jsonfile ./global.json
# Upgrade an installed SDK band and remove obsolete versions in that channel
dotnet-install upgrade 10.0.x --dry-run
# Upgrade multiple SDK bands in one command
dotnet-install upgrade 10.0.x 11.0.x
# Update the dotnet-install executable itself from GitHub releases
dotnet-install self-update --dry-run
# Include preview GitHub releases when self-updating
dotnet-install self-update --prereleaseIf you prefer a standalone executable instead of a .NET tool, jump to Install The Tool.
- Familiar
dotnet-installsemantics without depending on shell scripts - Strong CLI parsing and validation powered by
System.CommandLine - Flexible version selection with channels, exact versions, and wildcard bands
- Release metadata resolution and candidate URL planning you can inspect with
--dry-run - Proxy, feed, and timeout controls for CI, enterprise networks, and custom feeds
- NativeAOT-oriented packaging for fast startup and simple distribution
Install the latest LTS SDK:
dotnet-install --channel LTSInstall the latest SDK in a specific feature band:
dotnet-install --version 10.0.xInstall a specific SDK exactly:
dotnet-install --version 10.0.201Install the SDK pinned by global.json:
dotnet-install --jsonfile ./global.jsonWhen global.json contains sdk.rollForward, the tool maps permissive SDK roll-forward policies to the closest supported version selector. For example, feature and latestFeature map 10.0.100 to 10.0.x, while minor, latestMinor, major, and latestMajor map it to 10.x.
Install only a runtime:
dotnet-install --runtime aspnetcore --version 10.0.xPreview the plan without downloading:
dotnet-install --dry-run --channel STSInstall into a custom location:
dotnet-install --version 10.0.x --install-dir ./tools/dotnetKeep the downloaded archive for inspection or reuse:
dotnet-install --version 10.0.x --keep-zipPreview removal before deleting anything:
dotnet-install remove 8.0.204 --dry-runPreview an SDK upgrade before installing/removing anything:
dotnet-install upgrade 10.0.x --dry-runUpgrade multiple SDK bands in one command:
dotnet-install upgrade 10.0.x 11.0.xUpgrade an SDK and keep the related runtime installed:
dotnet-install upgrade 10.0.x --sdk-onlyUpgrade only the .NET runtime in a channel:
dotnet-install upgrade 10.0.x --runtimePreview a self-update from GitHub releases:
dotnet-install self-update --dry-runInclude preview releases when self-updating:
dotnet-install self-update --prereleaseThis repository also ships a first-party composite action at action.yml for workflows that want to install an SDK through this repo's managed dotnet-install release binary instead of actions/setup-dotnet.
When the action is used from a release tag such as @v1, it downloads the matching release binary for that action version. If it is used from a branch or local path, it resolves the latest published release asset from WeihanLi/dotnet-install and uses that binary with the local action scripts. The resolver prefers the latest stable release and falls back to the latest published prerelease only when no stable release exists yet.
Example:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: WeihanLi/[email protected]
with:
version: 10.0.x
- run: dotnet --infoTo install multiple SDK bands in one action step, pass a newline-delimited version value:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: WeihanLi/[email protected]
id: setup-dotnet
with:
version: |
10.0.x
11.0.x
- run: dotnet --list-sdksAction inputs:
versionoptional SDK version selector such as10.0.201,10.0.x, or a newline-delimited list of selectorsglobal-json-fileoptional path to aglobal.jsonfile whosesdk.versionshould be installed; cannot be combined withversioninstall-diroptional SDK install location
Action outputs:
resolved-versionsingle resolved SDK version or a newline-delimited list in request orderinstall-dirdotnet-rootdotnet-path
The project is already useful for developer workstations, CI setup, and install-plan inspection:
- Command-line parsing and validation with
System.CommandLine - Channel, quality, exact version, and wildcard version selection
- Release metadata lookup and candidate URL generation
- Artifact download, extraction, install verification, and feed/proxy override options
- Existing-install detection with confirmation prompts
- PATH updates for the current process, plus optional user PATH persistence on Windows
- Removal planning and deletion of installed SDK/runtime assets under the selected install root
Parity with the original shell scripts is still in progress, so behavior should continue to align with dotnet-install.sh and dotnet-install.ps1 where possible.
Current behavior boundaries:
--dry-runstops after install plan generation--qualitycan only be combined with--version Latest--jsonfileinstalls the SDK version pinned byglobal.json, honors SDKrollForwardwith the closest supported wildcard selector, and cannot be combined with runtime-only installs--internaland--osare parsed compatibility switches; full shell-script parity for these switches is still in progress- If the requested SDK/runtime version is already installed, the command warns and asks for confirmation unless
--yesis set - In CI,
--yesdefaults totrue --persist-pathis supported only on Windows and cannot be combined with--no-path- If another existing .NET installation is already discoverable from known locations, PATH mutation is skipped to avoid shadowing that install
removeis destructive and should be previewed with--dry-runfirst when targeting a shared install rootupgraderesolves the requested SDK/runtime version, skips installation when that resolved version is already present, and removes other installed versions in the same major.minor channel- SDK upgrades remove the related runtime by default when pruning obsolete SDKs; use
upgrade --sdk-onlyto keep the runtime installed self-updatereplaces the current executable with the latest matching GitHub release asset for the current RIDself-update --prereleaseincludes preview releases, and prerelease builds enable that behavior by default
The root command mirrors the install flow from the shell scripts. Frequently used options include:
--channel--quality--version--internal--jsonfile--runtime--shared-runtime--install-dir--architecture--dry-run--yes--no-path--persist-path--azure-feed--uncached-feed--feed-credential--proxy-address--proxy-use-default-credentials--proxy-bypass-list--skip-non-versioned-files--download-timeout--keep-zip--zip-path--runtime-id--os--verbose
Notes:
--versionis reserved for the .NET SDK/runtime version to install- Use the
versionsubcommand to print the tool version - Exact versions such as
8.0.205are supported, and wildcard selectors such as8.xand8.0.xresolve to the latest matching release --yesskips the existing-install confirmation prompt--shared-runtimeis a legacy compatibility switch that maps to--runtime dotnet--jsonfilereadssdk.versionand compatiblesdk.rollForwardvalues from aglobal.jsonfile for SDK installs--internaland--osare accepted by the parser but are not fully wired into install planning yet
The remove subcommand currently accepts:
- A required
<version>argument --install-dir--sdk-only--dry-run--verbose
The upgrade subcommand currently accepts:
- One or more required
<version>arguments such as10.0.201,10.0.x, or10.0.x 11.0.x --runtimeto upgrade only the .NET runtime--sdk-onlyto keep the related runtime when upgrading an SDK--install-dir--dry-run
The self-update subcommand currently accepts:
--dry-run--prerelease
dotnet-install manages two different PATH concerns:
- The PATH used to locate the
dotnet-installtool itself - The PATH used to locate the SDK/runtime installation root after the tool completes
Tool acquisition from NuGet or GitHub Releases does not automatically change PATH for you. Put the tool binary in a directory that is already on PATH, or invoke it by full path.
If you installed the tool from a GitHub release binary, dotnet-install self-update updates that executable in place. If you installed from NuGet, prefer dotnet tool update.
For SDK/runtime installs, the command behaves as follows:
- By default it prepends the resolved install root to the current process
PATH --no-pathdisables all PATH mutation and prints the install location instead--persist-pathalso prepends the install root to the userPATHfor future shells on Windows- PATH updates are skipped entirely when an existing .NET installation is already discoverable from the selected install root,
DOTNET_INSTALL_DIR,DOTNET_ROOT, the currentdotnetcommand location, or well-known default install roots
.NET 10 SDK or newer for building from source
Verify the environment:
dotnet --list-sdksBuild and test the full solution:
dotnet build DotNetInstall.slnx
dotnet test DotNetInstall.slnxCreate the global tool package:
dotnet pack src/DotNetInstall/DotNetInstall.csproj -c ReleasePublish a self-contained build to dist:
dotnet publish src/DotNetInstall/DotNetInstall.csproj -c Release -f net10.0 --use-current-runtime -o distsrc/DotNetInstall/application codesrc/DotNetInstall/Application/startup and host wiringsrc/DotNetInstall/Cli/commands and optionssrc/DotNetInstall/Options/immutable option modelssrc/DotNetInstall/Services/metadata resolution, planning, downloading, extraction, and orchestrationtests/DotNetInstall.Tests/unit testsdotnet-install.shanddotnet-install.ps1reference shell-script behavior
