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.

Mstat menu bar popover

Requirements

  • macOS 13 or newer
  • Zig 0.16.0
  • Xcode command-line tools with the macOS SDK

Build and run

sh
1zig build app
2open zig-out/Mstat.app

Or build and launch it in one step:

sh
1zig build run

For a one-shot metrics check without opening AppKit:

sh
1zig build once
2zig 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.

License

MIT