# Mtp Hot Reload

> Set up or recover MTP hot reload for a long-lived edit/re-run loop. Use for "hot reload tests", "dotnet run or dotnet test for hot reload", a host that keeps running, unsupported/rude edits, or a watch-based VSTest fallback. Covers setup, run/watch, restarts, filters, and the VSTest no-mutation fallback. Never mutate VSTest for hot reload. For one-time runs, exact commands, filter errors, TRX/dumps, or merely a failing test, use run-tests. Excludes writing/debugging tests, CI, and Test Explorer hot reload.

- Skill: `managedcode/mtp-hot-reload` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add managedcode/mtp-hot-reload`
- Raw SKILL.md: https://api.skillmd.com/api/skills/managedcode/mtp-hot-reload/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: managedcode (https://skillmd.com/u/managedcode)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/managedcode/mtp-hot-reload

---


# MTP Hot Reload for Iterative Test Fixing

Set up and use a long-lived Microsoft Testing Platform host that applies code
edits and automatically reruns tests.

## When to Use

- User explicitly asks for test hot reload
- User wants a host to stay running and automatically rerun after repeated edits
- User needs to set up MTP hot reload in their project

## When Not to Use

- User needs to write new tests from scratch (use general coding assistance)
- User needs to diagnose why a test is failing (use diagnostic skills)
- User wants Visual Studio Test Explorer hot reload (different feature, built into VS)
- User wants one normal run without rebuilding (use `run-tests`)
- User needs CI/CD pipeline configuration

## Inputs

| Input | Required | Description |
|-------|----------|-------------|
| Test project path | No | Path to the test project (.csproj). Defaults to current directory. |
| Failing test name or filter | No | Specific test(s) to iterate on |

## Response sizing

- If setup is already complete and the user asks only which command to use,
  return one `dotnet run --project <path>` command and one sentence explaining
  that it starts the persistent host. Do not repeat package, launch profile, or
  rude-edit guidance.
- If the package is already installed, show only the remaining enable-and-run
  steps. Do not suggest reinstalling it or add optional persistence/recovery
  paths unless requested.
- For a named test, identify the framework and return one runnable command with
  that framework's filter syntax. Never substitute MSTest/NUnit `--filter` for
  xUnit v3 `--filter-method` or TUnit `--treenode-filter`.
- A directly launched MTP host is itself the persistent watcher: `dotnet run`
  stays alive and the HotReload extension reacts to edits. Do not replace it
  with `dotnet watch run` for the normal MTP path; reserve `dotnet watch` for the
  explicit restart fallback below.

## Workflow

### Step 1: Detect the platform before changing anything

Hot reload requires MTP. It does **not** work with VSTest.

Follow the complete evaluated-property procedure in the `platform-detection`
skill. Read imported props and package versions as well as the project file.
Do this before installing packages, editing files, or returning an MTP launch
command.

**Hard stop for VSTest:** report that MTP hot reload is unavailable for the
project as configured and stop the MTP setup path. Do not install the extension,
create `launchSettings.json`, set the environment variable, change runner
properties/packages, or return a `dotnet run` hot-reload command. Never turn a
setup request into an implicit VSTest-to-MTP migration.

Offer one valid non-MTP fallback that preserves the project:

```shell
dotnet watch --project <project-path> test
```

This rebuilds and reruns the existing VSTest project when files change; it is
not MTP hot reload. Offer an explicit migration as a separate option, but do not
perform it unless the user asks. Exact one-shot test commands remain owned by
`run-tests`.

### Step 2: Add the hot reload NuGet package

First inspect the effective package references. If
`Microsoft.Testing.Extensions.HotReload` is already installed, preserve its
version and skip this step. Otherwise install it:

```shell
dotnet add <project-path> package Microsoft.Testing.Extensions.HotReload
```

> **Note**: When using `Microsoft.Testing.Platform.MSBuild` (included transitively by MSTest, NUnit, and xUnit runners), the extension is auto-registered when you install its NuGet package -- no code changes needed.

### Step 3: Enable hot reload

Hot reload is activated by setting the `TESTINGPLATFORM_HOTRELOAD_ENABLED` environment variable to `1`.

**Option A -- Set it in the shell before running tests:**

```shell
# PowerShell
$env:TESTINGPLATFORM_HOTRELOAD_ENABLED = "1"

# bash/zsh
export TESTINGPLATFORM_HOTRELOAD_ENABLED=1
```

**Option B -- Add it to `launchSettings.json` (recommended for repeatable use):**

Create or update `Properties/launchSettings.json` in the test project:

```json
{
  "profiles": {
    "<ProjectName>": {
      "commandName": "Project",
      "environmentVariables": {
        "TESTINGPLATFORM_HOTRELOAD_ENABLED": "1"
      }
    }
  }
}
```

### Step 4: Run the tests with hot reload

Run the test project directly (not through `dotnet test`) to use hot reload in console mode:

```shell
dotnet run --project <project-path>
```

To filter to specific failing tests, pass the filter after `--`. The syntax depends on the test framework -- see the `filter-syntax` skill for full details. Quick examples:

| Framework | Filter syntax |
|-----------|--------------|
| MSTest | `dotnet run --project <path> -- --filter "FullyQualifiedName~TestMethodName"` |
| NUnit | `dotnet run --project <path> -- --filter "FullyQualifiedName~TestMethodName"` |
| xUnit v3 | `dotnet run --project <path> -- --filter-method "*TestMethodName"` |
| TUnit | `dotnet run --project <path> -- --treenode-filter "/*/*/ClassName/TestMethodName"` |

The test host will start, run the tests, and **remain running** waiting for code changes.

### Step 5: Iterate on the fix

1. Edit the source code (test code or production code) in your editor
2. The test host detects the changes and re-runs the affected tests automatically
3. Review the updated results in the console
4. Repeat until all targeted tests pass

> **Important**: Hot reload currently works in **console mode only**. There is no support for hot reload in Test Explorer for Visual Studio or Visual Studio Code.

#### Unsupported edits and rude edits

Method-signature changes, new types, and other unsupported edits cannot be
applied to the active process. Never imply that the stale host picked them up.

For a directly launched MTP host:

1. Preserve the exact command, profile, environment, filter, and arguments that
   started the current host.
2. Stop it with `Ctrl+C`.
3. Rebuild the same project: `dotnet build <project-path>`.
4. Rerun the **same original host command**. Do not replace an unknown existing
   invocation with a generic `dotnet run` command.

If repeated unsupported edits are expected, offer a watch-managed restart
fallback:

```shell
# PowerShell
$env:TESTINGPLATFORM_HOTRELOAD_ENABLED = "1"
$env:DOTNET_WATCH_RESTART_ON_RUDE_EDIT = "1"
dotnet watch --project <project-path> run -- <existing-MTP-arguments>
```

`dotnet watch` restarts the process when a rude edit cannot be applied. Without
the auto-restart variable, accept the restart prompt or press `Ctrl+R`. Preserve
any existing test filter after `--`.
`DOTNET_WATCH_RESTART_ON_RUDE_EDIT` is a documented .NET SDK switch, not an MTP
extension setting. When correctness may be questioned, cite the `dotnet watch`
documentation and say that it makes the watcher restart instead of prompting.
Never omit the original filter or replace the requested watch-managed fallback
with a one-shot `dotnet run`.

### Step 6: Finalize

Once all tests pass:

1. Stop the test host (Ctrl+C)
2. Use `run-tests` when the user requests an exact one-shot validation command,
   flags, filter, TRX, or dump
3. Optionally remove `TESTINGPLATFORM_HOTRELOAD_ENABLED` from the environment or keep `launchSettings.json` for future use

## Validation

- [ ] Project uses Microsoft Testing Platform (not VSTest)
- [ ] `Microsoft.Testing.Extensions.HotReload` package is installed
- [ ] `TESTINGPLATFORM_HOTRELOAD_ENABLED` environment variable is set to `1`
- [ ] Tests run and the host remains active waiting for changes
- [ ] Code changes are picked up without manual restart

## Common Pitfalls

| Pitfall | Solution |
|---------|----------|
| Using `dotnet test` instead of `dotnet run` | Hot reload requires `dotnet run --project <path>` to run the test host directly in console mode |
| Project uses VSTest, not MTP | Do not mutate it. Offer `dotnet watch --project <path> test` as a rebuild/rerun fallback or a separate explicit migration |
| Forgetting to set the environment variable | Set `TESTINGPLATFORM_HOTRELOAD_ENABLED=1` before running |
| Expecting Test Explorer integration | Console mode only -- no VS/VS Code Test Explorer support |
| Making unsupported code changes (rude edits) | Stop, rebuild, and rerun the same host invocation, or use `dotnet watch` with restart-on-rude-edit behavior |

