VOOZH about

URL: https://www.nuget.org/packages/FsHotWatch/

⇱ NuGet Gallery | FsHotWatch 0.8.0-alpha.32




FsHotWatch 0.8.0-alpha.32

This is a prerelease version of FsHotWatch.
dotnet add package FsHotWatch --version 0.8.0-alpha.32
 
 
NuGet\Install-Package FsHotWatch -Version 0.8.0-alpha.32
 
 
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FsHotWatch" Version="0.8.0-alpha.32" />
 
 
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FsHotWatch" Version="0.8.0-alpha.32" />
 
Directory.Packages.props
<PackageReference Include="FsHotWatch" />
 
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FsHotWatch --version 0.8.0-alpha.32
 
 
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: FsHotWatch, 0.8.0-alpha.32"
 
 
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FsHotWatch@0.8.0-alpha.32
 
 
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FsHotWatch&version=0.8.0-alpha.32&prerelease
 
Install as a Cake Addin
#tool nuget:?package=FsHotWatch&version=0.8.0-alpha.32&prerelease
 
Install as a Cake Tool
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

FsHotWatch

Trying to speed up the F# development feedback loop.

FsHotWatch is a background daemon that watches your source files and aims to keep the F# compiler warm, so saving a file re-checks just what changed and hands the results to your tools (linters, analyzers, test runners) — instead of each tool restarting the compiler from scratch every time.

Status: early alpha, and a lot of it is AI-written. It runs the author's own daily F# work, but behavior and APIs shift between versions, rough edges are expected, and your mileage may vary. The goal is a faster F# loop — it's still finding its shape, so issues and PRs are very welcome.

The problem

F# tools are slow because each one starts its own compiler from zero. A 15-project solution can take ~2 minutes to analyze. Every save restarts your linter, your analyzer, and your test runner — all re-parsing and type-checking the same hundreds of files again.

How it works

FsHotWatch runs one compiler in the background and shares it with all your tools:

  1. You save a file — FsHotWatch notices.
  2. It re-checks just that file using the already-warm compiler — ideally milliseconds rather than minutes.
  3. Plugins get the results instantly — your linter, analyzer, and test runner see the new check results without re-parsing.
  4. You query the resultsfshw check runs everything and reports what each tool found.

Saves are debounced: if 10 files change at once (a formatter sweeping the repo, say), FsHotWatch waits for things to settle and processes them in one batch.

Quick start

# Install the CLI
dotnet tool install -g FsHotWatch.Cli

# Run all checks. This auto-starts the daemon the first time —
# no separate "start" step needed. Verbose by default.
fshw check

# Prefer one line per plugin?
fshw check --compact # or -q

fshw init writes a starter .fshw.json; see Configuration.

Commands

Command What it does
fshw check Run all configured checks and report findings. Auto-starts the daemon. --run-once runs without a daemon; -q/--compact for one line per plugin.
fshw status [plugin] Show the daemon's current status (optionally for one plugin).
fshw start Run the daemon in the foreground (Ctrl+C to stop). Optional — check/status start it for you.
fshw stop Stop the running daemon.
fshw format Format the code (Fantomas).
fshw test-rerun Rerun tests for an xUnit v3 --filter-class / --filter-trait slice.
fshw rerun <plugin> Force one plugin to re-run, clearing its cached state.
fshw init Generate a starter .fshw.json.
fshw config check Validate .fshw.json without starting the daemon.

Add -v for debug logging or -a for agent-friendly, parseable output. Run fshw --help for the full list.

Packages

FsHotWatch is split into small packages so you install only what you need:

Package What it does
Core library — the daemon, file watcher, plugin system, IPC
CLI tool — fshw check, start, stop, status, …
Plugin: figures out which tests to run when code changes
Plugin: runs F# analyzers (like G-Research or your own)
Plugin: runs FSharpLint using the warm compiler's results
Plugin: checks if your files are formatted with Fantomas
Plugin: runs dotnet build and emits BuildCompleted events
Plugin: runs custom commands when specific files change
Plugin: checks per-file line/branch coverage thresholds after each test run

Configuration

Run fshw init to scaffold a .fshw.json in your repo root, or write one by hand. Every field is optional — sensible defaults apply when omitted.

{
 "build": {
 "command": "dotnet",
 "args": "build"
 },
 "format": true,
 "lint": true,
 "cache": "file",
 "tests": {
 "beforeRun": "dotnet build",
 "dependsOn": ["src/MyApp/Database/Migrations/**"],
 "projects": [
 {
 "project": "MyProject.Tests",
 "command": "dotnet",
 "args": "run --project tests/MyProject.Tests --no-build --",
 "filterTemplate": "--filter-class {classes}",
 "classJoin": " ",
 "group": "unit"
 }
 ]
 },
 "analyzers": {
 "paths": ["analyzers/"]
 },
 "fileCommands": [
 {
 "pattern": "*.fsx",
 "command": "dotnet",
 "args": "fsi --typecheck-only"
 }
 ],
 "coverage": {
 "configPath": "coverage-ratchet.json",
 "searchDir": "coverage"
 }
}

Reference

Field Type Default Description
build object \| bool {"command": "dotnet", "args": "build"} Build command. false disables.
format bool true Enable Fantomas format-on-save preprocessor.
lint bool true Enable FSharpLint plugin. Uses fsharplint.json if found.
cache string \| bool "file" Cache strategy: "none", "memory", or "file". ("jj" is a legacy alias for "file".)
tests object Test runner config. See below.
coverage object Coverage threshold checking.
analyzers object F# Analyzers SDK integration.
fileCommands array [] Custom commands triggered by file patterns.

For memory/idle-exit, FSEvents latency, and per-task timeout keys, see .

build fields:

Field Type Default Description
command string "dotnet" Build command.
args string "build" Arguments to the build command.
buildTemplate string Template for incremental builds. {projects} is replaced with changed project paths.

tests fields:

Field Type Default Description
beforeRun string Command to run before each test run (e.g. "dotnet build").
dependsOn string[] [] Repo-root-relative globs (*, ?, **) naming external test inputs the symbol-diff can't see — DB migrations, generated files, schemas. Their content hash salts the test cache key, so editing a matched file forces a real test re-run even when no test source changed.
coverageDir string "coverage" Directory (repo-root-relative) for per-project Cobertura artifacts.
projects array [] List of test project configurations.

tests.projects[] fields:

Field Type Default Description
project string "unknown" Project name (used for filtering and display).
command string "dotnet" Test runner command.
args string "test --project <project>" Arguments to the test runner.
group string "default" Group name (for running subsets).
environment object {} Extra environment variables as "KEY": "VALUE" pairs.
filterTemplate string Template for class-based filtering. {classes} is replaced with affected test class names.
classJoin string " " Separator for joining class names in the filter.
reportVerificationFormat string "auto" How the pass/fail verdict's structured test report is obtained. The report (not the process exit code) decides green/red. auto injects --report-ctrf only for a runner detected as xUnit.v3 (else falls back to the dotnet heuristic); ctrf always injects it; off never injects it and the exit code stays authoritative.

analyzers fields:

Field Type Default Description
paths string[] Directories containing analyzer DLLs. Relative paths resolved from repo root.

fileCommands[] fields:

Field Type Default Description
pattern string "*.fsx" File extension pattern to match (e.g. "*.fsx", "*.sql").
command string "echo" Command to run when a matching file changes.
args string "" Arguments to the command.

coverage fields:

Field Type Default Description
configPath string "coverage-ratchet.json" Path to the coverage-ratchet thresholds file (relative to repo root or absolute).
searchDir string "." Directory tree to search for coverage.cobertura.xml files after each test run.

Cache directory

FsHotWatch keeps its check-result cache and the TestPrune database in .fshw/ at the repository root. Add it to your .gitignore:

.fshw/

What it does and doesn't cache. The on-disk cache stores FCS check results, keyed by file content — so a fresh daemon can replay unchanged files instead of re-checking them. It does not persist the compiler's in-memory warmth: FSharpChecker and its FCS caches are rebuilt from cold on every daemon start, so the first scan after a (re)start still pays that warm-up before the cached results start landing.

Writing plugins

Plugins are declarative update functions over a shared warm compiler: you define how your state reacts to events (file checked, build completed, tests finished), and the framework manages the agent, status, caching, and IPC. See .

Memory & tuning

The daemon keeps the F# compiler warm, which costs memory. FsHotWatch ships with conservative defaults (aggressive GC, optional idle-exit) so this stays in check — see if you want to adjust them.

Product Versions Compatible and additional computed target framework versions.
.NET net10.0 net10.0 is compatible.  net10.0-android net10.0-android was computed.  net10.0-browser net10.0-browser was computed.  net10.0-ios net10.0-ios was computed.  net10.0-maccatalyst net10.0-maccatalyst was computed.  net10.0-macos net10.0-macos was computed.  net10.0-tvos net10.0-tvos was computed.  net10.0-windows net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (7)

Showing the top 5 NuGet packages that depend on FsHotWatch:

Package Downloads
FsHotWatch.TestPrune

FsHotWatch plugin for TestPrune test impact analysis

FsHotWatch.Analyzers

FsHotWatch plugin for F# Analyzers SDK integration

FsHotWatch.Build

FsHotWatch plugin that runs dotnet build and emits BuildCompleted events

FsHotWatch.Coverage

FsHotWatch plugin that checks per-file coverage thresholds after test runs

FsHotWatch.Fantomas

FsHotWatch plugin for Fantomas format checking

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.8.0-alpha.32 0 6/18/2026
0.8.0-alpha.31 51 6/17/2026
0.8.0-alpha.30 57 6/16/2026
0.8.0-alpha.29 56 6/15/2026
0.8.0-alpha.28 60 6/12/2026
0.8.0-alpha.27 60 6/11/2026
0.8.0-alpha.26 56 6/10/2026
0.8.0-alpha.25 54 6/10/2026
0.8.0-alpha.24 86 6/8/2026
0.8.0-alpha.23 56 6/7/2026
0.8.0-alpha.22 60 6/7/2026
0.8.0-alpha.21 53 6/6/2026
0.8.0-alpha.20 54 6/5/2026
0.8.0-alpha.19 55 6/4/2026
0.8.0-alpha.18 51 6/4/2026
0.8.0-alpha.17 62 6/3/2026
0.8.0-alpha.16 60 6/2/2026
0.8.0-alpha.15 88 5/28/2026
0.8.0-alpha.14 60 5/26/2026
0.8.0-alpha.13 76 5/4/2026
Loading failed