# DiskWatch counts an undebounced file event stream, and its own manifest explains why

> A read-only Rust TUI for disk diagnostics with eight tabs, three layouts and an unusually explicit limits section, where Hot Files ranks raw notify events, SMART depth depends on smartmontools rather than on Cargo, and latency percentiles are sampled averages rather than per-IO timings.

**matthart1983/diskwatch** — Single-host, read-only disk diagnostics TUI. Sibling to netwatch and syswatch.

- Repository: https://github.com/matthart1983/diskwatch
- Stars: 477 · Forks: 27
- Language: Rust
- License: MIT
- Published: 2026-09-20 · Updated: 2026-09-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/matthart1983-diskwatch

## Hot Files ranks a raw event stream, not a debounced one

The manifest says it outright. The file watcher is `notify` 7, FSEvents-backed on macOS where `kFSEventStreamCreateFlagFileEvents` is on by default from version 6, and inotify on Linux, and the comment ends with the decision: the raw event stream is used, not the debounced API. Tab 7 then ranks paths by event rate and attributes them to a process. Those two choices are related, and both push the same way. A raw stream delivers every event the platform emits, so a program that writes a file two hundred times in a burst produces two hundred events, and the rate reflects bursts rather than sustained pressure. Debouncing would have smoothed that, and it was turned off on purpose. Measured this way, a tab that ranks a path by event rate is closer to a change-rate monitor than to an I/O meter, which is why the tab is called Hot Files and not Top Writers. The same caveat applies to the Linux side, where the watch roots and their inotify limits are a documentation section of their own, so a large watched tree is a configuration decision rather than a free choice. Meanwhile `Cargo.lock` is committed, which matters more here than in a library: the exact `sysinfo` and `ratatui` builds are what decide whether the numbers on your screen match the numbers the capability matrix describes.

## SMART depth depends on a binary Cargo.toml never mentions

Tab 6 shows drive health and whatever NVMe or ATA attributes are available, and how much is available is decided outside the Rust build. Install `smartmontools` and you get full SMART attribute tables; without it, SMART reporting is limited to the basic health flag where available. Nothing in the dependency list asks for it, no build script checks for it, and there is no runtime warning quoted about the missing table, just narrower output. This is a reasonable choice for a read-only tool that would rather shell out to the platform's own utility than vendor a drive protocol, but it means two identical machines can show different SMART panels with the same binary. Measurements the platform cannot supply at all are rendered as `--` rather than as a zero, which is the honest choice and the one that makes a screenshot ambiguous without a footnote.

## A CJK filename used to shear every column to its right

One manifest comment records a bug class worth more than a changelog entry. Column clamping in the Lite view has to be display-width aware, not byte-aware or char-aware, because a CJK filename shears every column to its right. The fix is the `unicode-width` dependency at 0.2. Lite is the 80x24 layout meant for an SSH session or a tmux split, which is exactly where columns are narrow, filenames are long, and a CJK path is plausible, so the bug and the layout were in the same place. The rest of the dependency list reads like a small, deliberate set: `ratatui` 0.29 and `crossterm` 0.28 for the terminal, `sysinfo` 0.32 for the system facts, `clap` 4 with derive for the command line, `anyhow` 1 for errors, `chrono` 0.4 and `serde` with `serde_json` for output, and `libc` 0.2 for the platform calls. Nothing pulls in a storage protocol library, which is the same decision that puts `smartmontools` outside the build.

## Five install routes, and the repository ships its own Nix files

The install block names five paths in five lines:

```bash
brew install diskwatch                # macOS / Linux
nix-shell -p diskwatch                # NixOS / Nix
paru -S diskwatch                     # Arch (AUR)
cargo install diskwatch               # build from source with Rust
x eget use matthart1983/diskwatch     # prebuilt release binary
```

Prebuilt binaries cover macOS and Linux on x86_64 and aarch64, including static Linux builds, plus Linux armv5te and Windows x86_64. Each route pins differently, which matters for a tool that reports version-sensitive measurements. `cargo install` follows the published crate, currently 0.5.8, and the manifest excludes the four demo assets from that package, so a source install gets no demo material at all. `nix-shell -p` resolves from a nixpkgs channel and can trail the newest tag, which is what the Repology page the project links to is for. Meanwhile the repository root carries both `flake.nix` and `package.nix` while the credits go to community packagers for the Nix and Arch packages, and the build-from-source route is documented in a separate reference page rather than in the install block itself.

## Three releases in two days, then a week of work past the last tag

The release history is dense at the front. v0.5.6 shipped on 14 September 2026 at 09:01, v0.5.7 followed the same day at 10:22, and v0.5.8 landed on 15 September, titled for live Windows I/O metrics. The manifest says 0.5.8, so the tag and the crate version agree. The last commit on the default branch main is dated 22 September 2026, a week after that release, which means the source tree is ahead of what any of the five install routes will give you. For most tools that is a footnote. Here the title of the newest release is a platform capability, and the capability matrix is a documentation page rather than a compiled-in list, so a new measurement can exist on main and be absent from the binary your package manager hands you.

## macOS has no busy-time counter, so utilisation is a Linux number

The clearest statement in the project is a negative one: macOS does not expose the device busy-time counter that Linux utilisation is computed from. The consequence is that the same IO panel is measuring different things on the two systems, and on macOS the utilisation figure has no direct equivalent. Two neighbouring numbers are approximations on every platform. Latency percentiles and histograms are built from sampled interval averages, not from individual IO timings, so a percentile describes the shape of a sample rather than the tail of the real distribution. Hot Files attributes a path to the process holding it open, and unprivileged attribution is limited to your own user, so a system-wide ranking degrades to a per-user one unless the tool is run with more privilege than most people want to hand a diagnostics screen.

## One documented flag exits without a TUI, and nothing documents the output

Five run forms are named:

```bash
diskwatch                       # eight tabs
diskwatch --lite                # one 80×24 screen
diskwatch --dense               # six panels on one screen
diskwatch --watch ~/src         # watch a specific tree instead of the defaults
diskwatch --diag                # print collected state and exit
```

That last one is the only form a script can use without driving a terminal interface, and the other four need a human pressing `1` through `8` to switch tabs, `V` to cycle views, `,` for settings, `?` for help and `q` to quit, with `/` filtering files in Lite and Dense and `s` cycling file sorting in Dense. The manifest depends on `serde` and `serde_json`, so something is serialised, yet no option for machine-readable output appears in the run list, and the format of `--diag` is not stated anywhere in the project.

## Every doc is an anchor in one reference file, and no test directory is listed

Documentation is centralised rather than spread. The docs table points at `docs/REFERENCE.md` five times, for views and controls and installation and options, for configuration covering themes, columns, refresh settings and config precedence, for watch roots and defaults and Linux inotify limits, for how Hot Files associates paths with processes, and for the capability matrix of what is real and what is deferred. The top-level entries are `.github/`, `.gitignore`, `Cargo.lock`, `Cargo.toml`, `LICENSE`, `README.md`, the four demo assets, `docs/`, `flake.nix`, `package.nix` and `src/`. No test directory and no benchmark directory appear among them. For a project whose selling point is that it tells you the difference between a measurement and a guess, the honesty is all in prose and in the source, and the release profile is tuned for the binary instead: thin LTO, one codegen unit, symbols stripped.

## Conclusion

Use DiskWatch when you want to see which device, mount or path is busy without changing anything, and read its limits section before you quote a number from it. Three of them matter. Hot Files infers the process holding a path open rather than the writer of each event, latency percentiles come from sampled interval averages rather than individual IO timings, and macOS does not expose the busy-time counter that Linux utilisation depends on, so a panel can legitimately show `--` on one host and a figure on another. The install is read-only and needs no configuration, but SMART depth needs smartmontools present, and most package managers will hand you v0.5.8 from 15 September 2026 while the branch carries a week of unpushed work past that tag.

## FAQ

### What does DiskWatch need to show full SMART data?

smartmontools installed on the host. Without it, SMART reporting is limited to the basic health flag where available, and measurements a platform cannot supply at all are displayed as -- rather than as a value.

### How does DiskWatch decide which process is writing a hot file?

It infers the busiest process holding the path open rather than identifying the writer of each event. Sampling can miss short-lived writers entirely, and unprivileged attribution is limited to your own user, so a system-wide ranking degrades to a per-user one.

### Can DiskWatch be run from a script?

diskwatch --diag prints the collected state and exits. The other four documented forms are interactive: eight tabs by default, --lite for a single 80x24 screen, --dense for six panels, and --watch to point at one tree instead of the defaults.

### How do I install DiskWatch and what platforms are covered?

Five routes are named: brew for macOS and Linux, nix-shell -p, paru -S from the AUR, cargo install for a source build with Rust, and eget for a prebuilt release binary. Prebuilt binaries cover macOS and Linux on x86_64 and aarch64, static Linux builds, Linux armv5te and Windows x86_64.

## Sources

- [Issues](https://github.com/matthart1983/diskwatch/issues)
- [License: MIT](https://github.com/matthart1983/diskwatch/blob/main/LICENSE)
- [matthart1983/diskwatch on GitHub](https://github.com/matthart1983/diskwatch)
- [README](https://github.com/matthart1983/diskwatch/blob/main/README.md)
- [Releases](https://github.com/matthart1983/diskwatch/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/matthart1983-diskwatch
