README.md
Mstat
A tiny native macOS menu-bar system monitor with a Zig sampling engine and a Swift/AppKit/SwiftUI interface. It shows CPU usage, reclaimable-memory-adjusted usage, memory pressure, swap, and CPU temperature.

Requirements
- macOS 13 or newer
- Zig 0.16.0
- Xcode command-line tools with the macOS SDK
Build and run
| 1 | zig build app |
| 2 | open zig-out/Mstat.app |
Or build and launch it in one step:
| 1 | zig build run |
For a one-shot metrics check without opening AppKit:
| 1 | zig build once |
| 2 | zig build once-json |
zig build is the only build entry point. It builds the Zig engine as a static
library, invokes swiftc, and assembles Mstat.app; no Makefile or Xcode project
is required.
The Zig engine samples on a std.Io concurrent task and keeps ten minutes of
timestamped one-second snapshots. Swift polls the latest completed snapshot, so
Mach, sysctl, and AppleSMC calls never run on the main thread. The collapsed
menu-bar item uses an adaptive 20-second refresh gate. While its popover is open,
headline metrics update every second and the downsampled chart refreshes every
five seconds.
The popover uses a restrained SwiftUI layout with a neutral CPU chart, SF
Symbols, numeric transitions, monospaced digits, and system Reduce Motion. Its
menu-bar display mode can be CPU, temperature, memory, a configurable pair of
metrics, or a configurable symbol. The selections persist in UserDefaults.
The thermometer is filled directly from 0–100% for a 0–100°C reading.
Temperature uses the undocumented AppleSMC IOKit user client. The current fallback sensor set is verified on an M3 Pro; unsupported machines display an em dash instead of inventing a value. No privileged helper is used.
Engine ABI
The UI talks to an opaque engine through the small C header in
src/mstat_engine.h: create/destroy, copy the current snapshot, and copy history.
No Swift or AppKit objects cross into Zig, and there are no callbacks across the
language boundary.