.NET SDK in .NET 11 Preview 4 - Release Notes
May 12, 2026 · View on GitHub
.NET 11 Preview 4 includes new SDK and CLI improvements:
dotnet watchadds device selection for MAUI and mobile projectsdotnet watchreliability fixes for Ctrl+R restart, iOS, and the TFM prompt- Fish shell completions match Bash, Zsh, and PowerShell
dotnet referenceand similar commands fall back to the current directorydotnet nuget <subcommand> --helpforwards to the NuGet CLI again- Launch settings notice moved to stderr
- Asset Groups for Static Web Assets
- OpenTelemetry replaces Application Insights for CLI telemetry
- NativeAOT entry point for the
dotnetCLI (foundation) - Smaller SDK archives continue to shrink
- Partial Ready-to-Run for upstack tooling
- Breaking changes
- Bug fixes
- Community contributors
.NET SDK updates in .NET 11:
dotnet watch adds device selection for MAUI and mobile projects
dotnet watch now mirrors the dotnet run device-selection flow for MAUI and
mobile targets (dotnet/sdk #53631).
After picking a target framework, dotnet watch calls the
ComputeAvailableDevices MSBuild target, auto-selects when there is a single
device, and shows an interactive Spectre.Console prompt with search when there
are several. The chosen device flows through to dotnet build (-p:Device,
-p:RuntimeIdentifier) and the launched dotnet run subprocess, including a
re-restore when the device requires a RuntimeIdentifier not present in the
original restore.
You can also pre-select a device on the command line:
dotnet watch --device <device-id>
dotnet watch works for Android devices and emulators, in addition to iOS
Simulators.

The framework prompt itself was upgraded to use Spectre.Console as well, so
arrow-key navigation, search, and pagination now work the same way as in
dotnet run (dotnet/sdk #53540).
dotnet watch reliability fixes for Ctrl+R restart, iOS, and the TFM prompt
Several long-standing dotnet watch issues are fixed in Preview 4:
- The Spectre.Console TFM picker no longer appears stuck because two readers
were both calling
Console.ReadKey(). Keys now flow through a singlePhysicalConsole.KeyPressedevent (dotnet/sdk #53675). - Ctrl+C and Ctrl+R no longer surface a spurious
WebSocketException/ObjectDisposedExceptionwhen the WebSocket transport tears down (dotnet/sdk #53648). - Hot Reload no longer deadlocks on iOS when
UIKitSynchronizationContextis installed before the startup hook runs (dotnet/sdk #54023).
Together these make dotnet watch usable end-to-end on a dotnet new maui
project running in the iOS Simulator.

Known issue: dotnet watch requires MtouchLink=None for iOS Simulator
dotnet watch does not work for iOS projects unless <MtouchLink>None</MtouchLink>
is set in the .csproj file
(dotnet/macios #25295). Add the
following to your project file:
<PropertyGroup>
<MtouchLink>None</MtouchLink>
</PropertyGroup>
Fish shell completions match Bash, Zsh, and PowerShell
The fish shell provider previously emitted a one-liner that delegated every
completion to a dynamic dotnet complete call. Preview 4 replaces it with a
full static + dynamic completion generator, matching the Bash, Zsh, and
PowerShell providers
(dotnet/sdk #53716). The generated
script walks the tokenized command line, emits static completions for
subcommands, options, and positional arguments, and falls back to dynamic
complete calls only where required.
Thank you @slang25 for this contribution!
dotnet reference and similar commands fall back to the current directory
dotnet reference add and dotnet reference remove now fall back to the
current directory when no --project is supplied, matching the long-standing
behavior of dotnet reference list
(dotnet/sdk #53594, fixes
dotnet/sdk #51897).
cd ClassLib2
dotnet reference add ../ClassLib1/ClassLib1.csproj # now works
dotnet reference remove ../ClassLib1/ClassLib1.csproj # now works
Previously these commands failed with Could not find project or directory ''
when run from a directory that already contained a project file.
dotnet nuget <subcommand> --help forwards to the NuGet CLI again
dotnet nuget add source --help and other NuGet subcommands now correctly
forward to the NuGet CLI's help output instead of falling back to generic
System.CommandLine help
(dotnet/sdk #53723, fixes
dotnet/sdk #53673). This was a
regression in the 11.0 SDK.
Launch settings notice moved to stderr
The Using launch settings from ... informational message now writes to
stderr instead of stdout
(dotnet/sdk #53797, fixes
dotnet/sdk #45640). Scripts that
capture the standard output of dotnet run no longer have to strip this line
out.
Thank you @Christian-Sidak for this contribution!
Asset Groups for Static Web Assets
The Static Web Assets SDK adds support for Asset Groups, a way to declare
groups of related assets that share publish, fingerprinting, and endpoint
metadata (dotnet/sdk #53187). The
related DefineStaticWebAssetEndpoints task gains an
AdditionalEndpointDefinitions parameter, and the glob matcher exposes the
captured ** stem so additional endpoints (for example default-document routes
like / for **/index.html) can be defined declaratively without
suffix-stripping logic in user MSBuild
(dotnet/sdk #53593).
This is plumbing for ASP.NET Core component authors and SDK extension authors; most app developers will see the result indirectly as their Razor and Blazor component packages ship cleaner static-asset metadata.
OpenTelemetry replaces Application Insights for CLI telemetry
The dotnet CLI now uses OpenTelemetry (with the Azure Monitor and OTLP
exporters) for its opt-in telemetry, replacing the previous
Microsoft.ApplicationInsights dependency
(dotnet/sdk #53181 and
dotnet/sdk #53800).
The user-facing behavior is unchanged — the same telemetry is collected, with
the same opt-out via DOTNET_CLI_TELEMETRY_OPTOUT. The motivation is to make
the CLI AOT-friendly: Microsoft.ApplicationInsights was not, and removing it
unblocks the NativeAOT entry point work below. As a side effect of the
exporters not yet being source-buildable, telemetry is currently emitted only
on Windows builds; non-Windows builds remain telemetry-free until the
OpenTelemetry packages are available in source-build.
NativeAOT entry point for the dotnet CLI (foundation)
Preview 4 lays the groundwork for a NativeAOT-compiled dotnet CLI host
(dotnet/sdk #54002). The work
introduces three layers:
dn.exe— a NativeAOT host that resolvesDOTNET_ROOTandhostfxrand marshals arguments into a NativeAOT shared library. This is for SDK-repo dogfooding, not for production usage.dotnet-aot.dll— a NativeAOT shared library that handles simple commands such as--versionand--infodirectly, and falls back to the full managed CLI viahostfxrfor everything else.dotnet.dll— the existing managed CLI, with#if CLI_AOTconditionals so the same source files can be compiled into both paths.
The goal is near-instant startup for the most common CLI invocations while
preserving full functionality for the rest. The new entry point is not yet the
default dotnet binary; it ships as architectural foundation in this preview
and you can read the included DESIGN.md for the build and debugging workflow.
Smaller SDK archives continue to shrink
Preview 2 introduced smaller SDK installers on Linux and macOS by deduplicating
assemblies. Preview 4 trims the SDK further by skipping crossgen for assemblies
that only exist under DotnetTools/
(dotnet/sdk #53659). Assemblies
that also exist outside DotnetTools/ are still crossgen'd — they get the
startup benefit and the duplicate is then removed — but assemblies unique to
DotnetTools/ are left as IL only. The Microsoft.CodeAnalysis.VisualBasic*
crossgen exclusion was also broadened to apply globally rather than only under
Roslyn/bincore.
On a linux-x64 dev build this reduces the SDK tarball by 23.6 MB.
Partial Ready-to-Run for upstack tooling
A new MSBuild property lets upstack tooling (for example dotnet/macios and
dotnet/maui) declare a list of assemblies that should be partially R2R-compiled
and excluded from the composite image
(dotnet/sdk #53635). The motivating
scenario is precompiling generated XAML code in Debug builds to speed up F5,
without paying the full crossgen cost for the rest of the app. App developers
do not set this property directly — it is a hook the mobile workloads will use
in their targets.
Breaking changes
- Template engine drops
netstandard2.0. All template engine projects (Microsoft.TemplateEngine.Abstractions,Core,Core.Contracts,Edge,IDE,Orchestrator.RunnableProjects,Utils, andTemplateLocalizer.Core) now target only$(NetMinimum),$(NetCurrent), and$(NetFrameworkToolCurrent)(dotnet/sdk #54041). NuGet 7.0 dropped netstandard support, so keeping the template engine onnetstandard2.0had become impractical. Tools that consume the template engine libraries directly will need to retarget; thedotnet newCLI is unaffected.
Bug fixes
- CLI
dotnet publishno longer removes native DLLs on subsequent runs of single-file publish (dotnet/sdk #52755, fixes dotnet/sdk #52151).NET10_0_OR_GREATER(and the cumulativeNET*_OR_GREATERdefines) is now emitted when targetingnet10.0on MSBuild < 18 (for example VS 17.14) (dotnet/sdk #53976).
- Containers
- Ubuntu codename resolution updated for the noble → resolute change so SDK container builds work on .NET 11 (dotnet/sdk #53371). Thank you @hwoodiwiss!
- Container image digest validation aligns more closely with the OCI spec,
using anchored digest regexes and centralizing format checks in
DigestUtils(dotnet/sdk #53724, dotnet/sdk #53933).
- Workloads
- Built-in workload manifests in preview SDK archives are now placed under
the preview feature band (for example
sdk-manifests/11.0.100-preview.4/) instead of the stable band (dotnet/sdk #53857, fixes dotnet/sdk #53234).
- Built-in workload manifests in preview SDK archives are now placed under
the preview feature band (for example
- Aspire integration
dotnet runcorrectly launches the Aspire host again (dotnet/sdk #53877).
- Process redirection
dotnet watchand the underlying process launcher no longer redirect child process output unnecessarily, which previously prevented a child process console from being created on Windows (dotnet/sdk #53539, fixes dotnet/sdk #53091).
Community contributors
Thank you contributors! ❤️