A Second Horizon utility · free · notarized

Readout.

An instrument panel in the menu bar: network, disk, temperatures, fans, CPU, memory. It tells you which app is talking to the internet, which process is eating your memory, and it hands you the fans.

macOS 14+ · Apple Silicon (Intel partially supported) · v1.0.2

brew install --cask secondhorizonstudio/tap/readout

Or download Readout-1.0.2.zip directly. Signed, notarized, no account, no payment, nothing phoning home.

↑ 42 KB/s ↓ 1.8 MB/sCPU 18%MEM 62%CPU 48° FAN 2.5K
The combined item, rendered as the app renders it: one slot, hairline dividers, labels spelled out.

01·The bar

One menu bar item, however much it shows

Menu bar real estate is the scarcest pixel on a Mac, and most monitors are greedy with it. Readout renders every widget you enable into a single status item, separated by hairlines. macOS pads each item it’s given, so separate widgets both waste width and read as four different apps sitting in a row. Four combined widgets take less room than two separate ones.

Widgets draw as template images, the standard frosted treatment macOS applies to its own status icons, legible on any wallpaper in either appearance. Labels are spelled out (CPU 18%, CPU 48°) so a percentage never masquerades as a temperature. Prefer separate, individually ⌘-draggable items? One toggle.

Readout's Widgets settings, the full panel: a row per widget (Network, Disk, CPU + Memory, Temp + Fans), each with a bar style menu and an on/off switch; appearance switches for combining into one menu bar item and using accent colors; the popover's layout pickers; a drag-to-reorder list of popover sections; and the sampling controls.
Settings → Widgets, the whole tab inside a window-sized frame: scroll it. Each widget picks its own bar style; the switch below decides whether they share one slot or scatter.

02·The popover

Answers, not only numbers

Click the bar and the dashboard opens. The design rule inside: every number should answer a question you actually ask.

“What is talking to the internet so much?”
Per-app traffic with live rates and rolling five-minute totals. Anything that uploads more than 50 MB or downloads more than 500 MB inside that window gets flagged in orange. No baseline model, no cloud, just attribution you can read.
“What is eating my memory?”
The top five processes by physical footprint, the same figure Activity Monitor shows. When memory pressure climbs or swap is high, they’re labeled as the likely drivers. macOS doesn’t expose per-process swap; Readout says so instead of inventing it.
“How hot is it, really?”
Every sensor the machine exposes, 28 on an M1 Max, deduplicated and named in plain language, with CPU temperature as the headline, colored plain below 80 °C, amber to 95, red past it. Calibration references are excluded from “hottest” because they aren’t temperatures. And on Apple Silicon, where CPU and GPU share a die and there is no separate GPU probe, Readout tells you that rather than inventing a number.
“What are the fans doing?”
Live RPM per fan with its hardware travel range and, if you enable it, the controls below.
Readout's dashboard: a network section with upload and download rates, a traffic bar graph, session totals, and per-app rows; nested CPU rings for all cores, performance cores and efficiency cores with the top processes beside them; a memory ring with its top consumers, and a disk ring with a read/write graph; a CPU temperature dial on the thermal color ramp with die-zone cells and SSD, battery and power rings; a ring per fan with the mode choices stacked between them.
The 0.5 dashboard: rings instead of meters, and the whole popover fits a 14″ screen. Captured on an M1 Max, once in each appearance, minutes apart.

03·Fan control

The fans answer to you, and fail safe without you

Off by default. Enabling it installs a privileged helper, the only code that ever writes to the fan hardware, and macOS asks you to approve it once. Then: Auto (macOS drives, as before), Curve (a draggable temperature-to-speed curve following the hottest CPU sensor), Manual, and Max.

Software that commands fans owes you an answer to one question: what happens when it crashes? Readout’s answer, measured on hardware, not promised:

  • Every target is clamped to the fan’s hardware range, inside the helper. There is no speed you can ask for that the hardware didn’t already allow.
  • If the app crashes, fans revert to automatic in under a second. If it freezes with its connection still open, the nastier case, a dead-man timer reverts them within 15 seconds.
  • Any sensor reaching 95 °C forces automatic control, whatever your settings say.
  • The helper checks the code signature of anything that connects to it, and reverts to automatic if it launches and finds fans stranded in a forced mode, which covers power loss.

All of it verified on hardware: manual mode moved both fans from 2,319/2,495 to 2,807/2,958 RPM in four seconds; a simulated crash reverted in under a second; a frozen client reverted at the dead-man timer. The test harness ships in the app: Readout --fantest runs the whole round trip on your machine.

Readout's Fans settings: a fan control switch with a green “Helper connected” status, a note explaining the privileged helper and its safety limits, and a draggable temperature-to-speed curve.
Settings → Fans, with the helper installed and connected. The curve follows the hottest CPU sensor; drag a point, and the helper clamps whatever you ask for to the fan's own range.

04·Cost

The monitor must never be the thing worth monitoring

A system monitor that costs meaningful CPU is a parasite with a dashboard. Readout holds itself to budgets, measures them with 60-second CPU-time soaks (not the decaying averages ps shows), and, the unusual part, watches itself in production: if it ever exceeds ~3% CPU averaged over a minute while idle, it logs the overrun to its own failure journal and backs its tick rate off.

The expensive work, spawning the per-app attribution sweep, is skipped entirely when less than 500 KB has moved, and stands down when the machine reports serious thermal pressure. Opening the popover forces a fresh sample, so the data is never stale when you actually look. Sensors are read at the cadence the visible numbers need, and while your displays sleep Readout stops sampling altogether. A monitor nobody can see should cost nothing. Two memory numbers rather than one, because the SwiftUI dashboard keeps its view and GPU machinery warm once you have opened it.

Readout's sampling settings, at the foot of the Widgets tab: a refresh interval menu set to 2 seconds, a three-notch Monitoring detail slider sitting on Balanced between Efficiency and Detail, and a switch for reducing detail on battery.
Settings → Widgets, scrolled to its Sampling section. Three notches of effort, and a step-down that takes the next one down the moment you unplug. Sensor choice stays automatic; the headline temperature has to cover the whole CPU/GPU group or it can quietly miss the hottest one.
StateBudgetMeasured, M1 Max
Popover closed, network busy≤ 2% CPU1.3%
Popover open≤ 5% CPU2.6%
Display asleepno sampling~0%
Idle wakeups at rest≤ 10/s3.2/s
Memory, dashboard unopened≤ 25 MB18 MB
Memory, after using the dashboard≤ 80 MB50–70 MB
Fan control disabledno helper processconfirmed absent

05·Hardware

Read from the machine, honest about the gaps

Everything Readout shows is read from the Mac it’s running on: SMC keys, IOKit registries, kernel counters, HID sensor services. Nothing is looked up from a model database or fetched over the network, so a Mac released tomorrow works without an update. What varies by model is which probes exist, and every subsystem degrades to “unavailable” rather than guessing.

Verified on hardware: Apple Silicon MacBook Pro, end to end, fan control included. Implemented but not yet verified: M3/M4 fan control (a different write path, chosen automatically), Intel Macs, fanless Airs, desktops. Those paths fail safe and say so. Readout --compat prints your machine’s own support report. If you run unverified hardware, sixty seconds of paste turns “should work” into “does work” for everyone after you.

06·Trust

It logs its own failures, and they stay yours

Every sampler failure, parse surprise, crash, and self-budget overrun lands in a deduplicated journal on your disk. Settings → Health shows it live with one-click copy, so a bug report carries evidence instead of vibes. None of it is transmitted, ever. There is no telemetry.

The one network request Readout makes: once a day it asks GitHub whether a newer release exists, an anonymous request that sends nothing about you or your Mac, with an off switch in Settings. A new version posts one notification, ever, and nothing is downloaded until you choose to update; an app with a privileged fan helper has no business replacing itself unattended. Homebrew installs are pointed at brew upgrade; direct installs can have Readout download the release, verify it is signed by the same developer identity, and swap itself, or just open the release page. Updating is always your move.

07·Needle

Notes on what the numbers mean

Field guides and thinking-out-loud pieces from building the app: fans, sensors, and finding out which app is talking to the internet. Honest even where it costs a sale.

All Needle notes →