Needle/Thinking out loud

The watchdog and the journal: an app that debugs itself

August 19, 2026 · 1 min read

A user wrote that Readout “froze for a second” and I had nothing. No reproduction, no timestamp, no stack. The standard industry fix for this is a crash reporter SDK that uploads diagnostics to someone’s cloud, which for an app whose whole privacy story is “nothing leaves your Mac” was not going to happen. So the question became: how does an app debug itself using only the machine it’s standing on?

The watchdog

Since 0.5.5 a main-thread watchdog runs alongside the UI, and any stall over 400 ms gets written to the diagnostic log with its duration. That’s the whole feature. But it converts “it froze for a second, I think, maybe Tuesday?” into a dated entry that either exists or doesn’t, and when it exists, into a pattern: always during a sweep, always after wake, never at all. A freeze you can date is a bug. A freeze you can’t is a mood.

Evidence instead of vibes, collected by the only machine that witnessed the crime.

The journal

The watchdog writes into the same deduplicated journal that collects every sampler failure, parse surprise, crash, and self-budget overrun, including the safety events: if fan control ever loses its temperature feed and hands the fans back to macOS, fan.blindlands there too. Settings → Health shows it live with one-click copy, so a bug report arrives carrying its own evidence. None of it is transmitted, ever. The journal is yours; I only see it if you paste it.

The trade against a telemetry pipeline is worth calling out. A crash reporter would show me every user’s failures, ranked by frequency, without asking anyone anything; the journal only shows me what someone chooses to send, so I learn about the bugs people bother to report. For a system monitor I think that’s the right side of the line. An app whose job is watching your machine has one extra duty the category rarely acknowledges: to watch itself with the same rigor, and to keep what it sees at home.

← All Needle notes