dotnet-watch(1)

πŸ“¦
version 11.0.0~rc3 Β· 5 versions
, in alpine 3.24, centos-stream 10, centos-stream 9, fedora 43, fedora 44, nixpkgs unstable, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

dotnet-watch(1) Β· .NET Documentation Β· bestie edition πŸ’–

This article applies to: βœ”οΈ .NET 6 SDK and later versions

✨ NAME ✨

dotnet-watch β€” okay so this is the tool that restarts or hot reloads the app you point it at, or runs a dotnet command you name, the literal second it notices your source code changed. no cap. πŸ¦‹


🌸 SYNOPSIS 🌸

dotnet watch [<command>]
  [--artifacts-path <ARTIFACTS_DIR>] [--disable-build-servers]
  [--list] [--no-hot-reload] [--no-self-contained]
  [--non-interactive] [--project <PROJECT>] [--sc|--self-contained]
  [-q|--quiet] [-v|--verbose] [--version]
  [--] <forwarded arguments>

dotnet watch -?|-h|--help

πŸ’… DESCRIPTION πŸ’…

dotnet watch is a file watcher. the moment it clocks a change, it runs dotnet run or whatever dotnet command you told it to run. and if it's running dotnet run and your change is one that hot reload supports? it hot reloads your app. if the change isn't supported, it just restarts the whole app instead. either way, the vibe is fast iterative development straight from the command line and it is genuinely so good. πŸ”₯

while dotnet watch is doing its thing, you can force the app to rebuild and restart by smashing Ctrl+R in the command shell. but heads up, bestie β€” that only works while the app is running. like, if you run dotnet watch on a console app that finishes before you get to press Ctrl+R, pressing Ctrl+R does absolutely nothing πŸ’€. the good news though? dotnet watch is still watching your files in that case, and it'll restart the app the moment a file gets updated. main character behavior honestly.

πŸŽ€ Response compression πŸŽ€

if dotnet watch runs an app that uses response compression, the tool can't inject the browser refresh script. on .NET 7 and later, the tool throws a warning at you that looks like this:

warn: Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware[4]

Unable to configure browser refresh script injection on the response.  This may have been caused by the response's Content-Encoding: `br'.  Consider disabling response compression.

so if you don't wanna disable response compression, you can just manually add the browser refresh JavaScript reference to your app's pages instead:

@if (Environment.GetEnvironmentVariable("__ASPNETCORE_BROWSER_TOOLS") is not null)
{
    <script src="/_framework/aspnetcore-browser-refresh.js"></script>
}

πŸ¦‹ ARGUMENTS πŸ¦‹

  • <command>

on .NET 7 SDK and earlier, dotnet watch can run any command that gets dispatched through the dotnet executable β€” built-in CLI commands, global tools, all of it. if you can run dotnet <command>, you can run dotnet watch <command>. periodt.

on .NET 8 SDK and later, it's a tighter lineup: dotnet watch can run dotnet run, dotnet build, or dotnet test. so you specify run, build, or test for <command>.

if you don't specify the child command at all, it defaults to run for dotnet run. 🌈

  • <forwarded arguments>

anything you drop after a double dash (--) gets passed along to the child dotnet process. running dotnet watch run? then those arguments are options for dotnet run. running dotnet watch test? then they're options for dotnet test. simple as that, iykyk ✨


πŸ’– OPTIONS πŸ’–

  • --artifacts-path <ARTIFACTS_DIR> β€” all the build output files from the executed command go into subfolders under the path you specify, split up by project. for more info, see Artifacts Output Layout. available since .NET 8 SDK. πŸ“
  • --disable-build-servers β€” forces the command to ignore any persistent build servers. it's the consistent way to kill all use of build caching and force a build from scratch. why would you want that? because a build that doesn't lean on caches is chef's kiss when the caches might be corrupted or just plain wrong for some reason. available since .NET 7 SDK. 🧚
  • --list β€” lists every discovered file without starting the watcher. like window shopping but for files πŸ‘‘
  • --no-self-contained β€” equivalent to --self-contained false. that's it, that's the whole thing.
  • --no-hot-reload β€” suppress hot reload for supported apps. sometimes you just want the restart, you know?
  • --non-interactive β€” runs dotnet watch in non-interactive mode. use this when you want to prevent console input from ever being requested. and btw, when hot reload is enabled and a rude edit gets detected, dotnet watch restarts the app. available since .NET 7 SDK. πŸ™ˆ
  • --project <PATH> β€” specifies the path of the project file to run. you can give it just the folder, or the folder plus the project file name. if you don't say anything, it defaults to the current directory. πŸŽ€
  • --sc|--self-contained β€” publishes the .NET runtime right along with your application, so the runtime does not need to be installed on the target machine. the default is true. ✨
  • -q|--quiet β€” suppresses all output generated by the dotnet watch command, except warnings and errors. important: this option is not passed on to child commands. so for example, output from dotnet restore and dotnet run still comes through. πŸ’…
  • -v|--verbose β€” shows verbose output for debugging. when you need to see everything.
  • --version β€” shows the version of dotnet watch. πŸ‘‘
  • -- β€” the double-dash option (–) can be used to delimit dotnet watch options from arguments that get passed to the child process. using it is optional. when you don't use it, dotnet watch treats the first unrecognized argument as the beginning of the arguments it should pass into the child dotnet process. πŸ¦‹
  • -?|-h|--help β€” prints out a description of how to use the command. the classic. the icon. 🌸
  • DOTNET_HOTRELOAD_NAMEDPIPE_NAME β€” dotnet watch sets this one itself when it's about to launch your app, and it says which named pipe to use.
  • DOTNET_USE_POLLING_FILE_WATCHER β€” set it to 1 or true and dotnet watch swaps to a polling file watcher instead of <xref:System.IO.FileSystemWatcher?displayProperty=nameWithType>. Polling is literally required on some file systems β€” network shares, Docker mounted volumes, and other virtual file systems, iykyk. The <xref:Microsoft.Extensions.FileProviders.PhysicalFileProvider> class reads DOTNET_USE_POLLING_FILE_WATCHER to decide whether the <xref:Microsoft.Extensions.FileProviders.PhysicalFileProvider.Watch%2A?displayProperty=nameWithType> method will lean on the <xref:Microsoft.Extensions.FileProviders.Physical.PollingFileChangeToken>.
  • DOTNET_WATCH β€” dotnet watch sets this to 1 on every single child process it launches. no cap.
  • DOTNET_WATCH_AUTO_RELOAD_WS_HOSTNAME β€” the browser refresh server mechanism inside dotnet watch reads this to figure out the WebSocket host environment. Fun part: the value 127.0.0.1 gets replaced with localhost, and the http:// and https:// schemes get swapped for ws:// and wss:// respectively.
  • DOTNET_WATCH_ITERATION β€” dotnet watch sets this to 1, and then bumps it by one every time a file changes and the command restarts or hot reloads your app. it's the lil counter of character development ✨
  • DOTNET_WATCH_SUPPRESS_BROWSER_REFRESH β€” set to 1 or true and dotnet watch will not refresh browsers when it detects file changes.
  • DOTNET_WATCH_SUPPRESS_EMOJIS β€” starting with the .NET SDK 6.0.300, dotnet watch emits non-ASCII characters to the console, like this:
dotnet watch πŸ”₯ Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
  πŸ’‘ Press "Ctrl + R" to restart.
dotnet watch πŸ”§ Building...
dotnet watch πŸš€ Started
dotnet watch ⌚ Exited
dotnet watch ⏳ Waiting for a file to change before restarting dotnet...

On certain console hosts those characters can come out garbled 😭. To avoid seeing garbled characters, set this variable to 1 or true.

  • DOTNET_WATCH_SUPPRESS_LAUNCH_BROWSER β€” set to 1 or true and dotnet watch won't launch or refresh browsers for web apps that have launchBrowser configured in launchSettings.json.
  • DOTNET_WATCH_SUPPRESS_MSBUILD_INCREMENTALISM β€” by default dotnet watch optimizes the build by skipping certain operations, like running restore or re-evaluating the set of watched files on every file change. Set this variable to 1 or true and all those optimizations get disabled. periodt.
  • DOTNET_WATCH_SUPPRESS_STATIC_FILE_HANDLING β€” set to 1 or true and dotnet watch stops doing special handling for static content files. It also sets the MSBuild property DotNetWatchContentFiles to false.
  • DOTNET_WATCH_RESTART_ON_RUDE_EDIT β€” set to 1 or true and dotnet watch will always restart on rude edits instead of asking you. no more "are u sure" texts, it just goes.

πŸ¦‹ Files watched by default πŸ¦‹

dotnet watch watches all items in the Watch item group in the project file. By default that group includes every item in the Compile and EmbeddedResource groups. It also scans the entire graph of project references and watches all files within those projects. obsessed with the thoroughness honestly.

By default, the Compile and EmbeddedResource groups include all files matching these glob patterns:

  • **/*.cs
  • *.csproj
  • **/*.resx
  • Content files in web apps: wwwroot/**

By default, .config and .json files don't trigger a dotnet watch restart, because the configuration system has its own mechanisms for handling configuration changes. it's giving "i handle my own business".

Files can be added to the watch list or removed from it by editing the project file. You can name files individually or use glob patterns.


🌈 Watch additional files 🌈

You can watch more files by adding items to the Watch group. For example, this markup extends that group to include JavaScript files:

<ItemGroup>
  <Watch Include="**\*.js" Exclude="node_modules\**\*;**\*.js.map;obj\**\*;bin\**\*" />
</ItemGroup>

πŸ’… Ignore specified files πŸ’…

dotnet watch will ignore Compile and EmbeddedResource items that have the Watch="false" attribute, like this:

<ItemGroup>
  <Compile Update="Generated.cs" Watch="false" />
  <EmbeddedResource Update="Strings.resx" Watch="false" />
</ItemGroup>

It'll also ignore project references that have the Watch="false" attribute, like this:

<ItemGroup>
  <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" Watch="false" />
</ItemGroup>

✨ Advanced configuration ✨

dotnet watch performs a design-time build to find the items to watch. When that build runs, dotnet watch sets the property DotNetWatchBuild=true. You can use that property like this:

<ItemGroup Condition="'$(DotNetWatchBuild)'=='true'">
  <!-- only included in the project when dotnet-watch is running -->
</ItemGroup>

πŸ”₯ Hot Reload πŸ”₯

Starting in .NET 6 SDK, dotnet watch includes support for hot reload. Hot reload is a feature that lets you apply changes to a running app without having to rebuild and restart it. The changes can be to code files or to static assets like stylesheet files and JavaScript files. This feature streamlines the local development experience, because it gives you immediate feedback when you modify your app. main character energy, genuinely.

For information about app types and .NET versions that support hot reload, see Supported .NET app frameworks and scenarios.


πŸ™ˆ Rude edits πŸ™ˆ

When a file is modified, dotnet watch determines if the app can be hot reloaded. If it can't be hot reloaded, the change is called a rude edit, and dotnet watch asks if you want to restart the app:

dotnet watch ⌚ Unable to apply hot reload because of a rude edit.
  ❔ Do you want to restart your app - Yes (y) / No (n) / Always (a) / Never (v)?
  • Yes: Restarts the app.
  • No: Leaves the app running without the changes applied.
  • Always: Restarts the app and doesn't prompt anymore for rude edits.
  • Never: Leaves the app running without the changes applied and doesn't prompt anymore for rude edits.

For information about what kinds of changes are considered rude edits, see Edit code and continue debugging and Unsupported changes to code.

To disable hot reload when you run dotnet watch, use the --no-hot-reload option, like this:

.NET CLI dotnet watch --no-hot-reload

🌟 EXAMPLES 🌟

  • Run dotnet run for the project in the current directory whenever source code changes:
dotnet watch

Or:

dotnet watch run
  • Run dotnet test for the project in the current directory whenever source code changes:
dotnet watch test
  • Run dotnet run --project ./HelloWorld.csproj whenever source code changes:
dotnet watch run --project  ./HelloWorld.csproj
  • Run dotnet run -- arg0 for the project in the current directory whenever source code changes:
dotnet watch run -- arg0

Or:

dotnet watch -- run arg0

🫢 SEE ALSO 🫢

  • Tutorial: Develop ASP.NET Core apps using a file watcher
  • Hot reload in Visual Studio
  • Hot reload supported apps
  • Hot reload supported code changes
  • Hot reload test execution
  • Hot reload support for ASP.NET Core

okay bestie that's the whole page, we made it to the end πŸŽ€ this cutie is from the dotnet-watch(1) manual, dated 2025-10-30. go forth and hot reload responsibly, you've got this πŸ’–

πŸ“¦ where this page comes from