Skip to content
cookabcPublic

About

Menu bar system monitor for macOS 26+ — CPU, memory, network, disk, battery and processes on a pixel dashboard

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

28 Commits

Folders and files

Repository files navigation

Vitals — Menu Bar System Monitor

Vitals is a macOS system monitor that lives only in the menu bar. The menu bar icon shows a live CPU mini-curve and usage percentage; clicking it opens a dark pixel dashboard with CPU, memory, network, disk, battery and process details. No Dock icon, no main window.

Vitals overview: CPU, GPU, memory, network, disk and system on a pixel dashboard

Requires macOS 26.0 or later. Developed with Xcode 27 / macOS 27 SDK.

Features

  • The app icon uses a pixel V-shaped pulse, while the menu bar keeps a crisp monochrome V mark; the menu bar icon is a single-color vector that adapts to light and dark appearances
  • Four menu bar display modes: graph, number, graph + number, and icon; the curve color tracks load (green / orange / red) and a pause symbol overlays it when sampling is paused
  • CPU: total usage, a per-core bar chart, and a dot-matrix history of the last 120 samples; the overview shows segmented per-core bars plus performance / efficiency core counts; the DETAILS entry offers history, load average and a per-core breakdown
  • GPU: the overview shows driver-reported usage, history, and memory in use / allocated; details add renderer and tiler usage, with missing fields shown as N/A
  • Memory: used / total, a wired-apps-compressed-available segment bar, system memory pressure and swap; expand for file cache, free pages and swap total
  • Network: upload and download rates with history, pixel curves distinguishing upload from download, and peak statistics on the details page
  • Disk: startup volume capacity bar; the details page lists every readable block device (including disk images) with read / write rates, operation counts and history, and read/write sampling can be turned off in Settings
  • System: 1 / 5 / 15 minute load average, logical core count, thermal state, uptime and low power mode
  • Battery: the SYSTEM area shows level, hover reveals charging state and estimated time remaining (IOPowerSources); a low power mode marker
  • Processes: the details page lists the top 5 processes by CPU with usage and resident memory (sysctl + libproc delta sampling)
  • Thermal state: the SYSTEM area reports NORMAL / WARM / HOT / CRITICAL
  • Alerts: system notifications for sustained high CPU (30 consecutive seconds at or above 90% by default), disk usage, and thermal state escalation, with a 5 minute cooldown per alert
  • Language: follow the system, Simplified Chinese or English, switching the overview, details, settings, tips and notifications together; necessary product names, process names and technical abbreviations stay as-is
  • Settings window: menu bar mode, sampling interval (0.5 / 1 / 2 s), CPU / GPU / memory / network / disk / sensor / battery / process toggles, alert thresholds, and launch at login

System features used

Category API
Visual Canvas pixel glyphs, an isometric host illustration, segmented bars, dot-matrix curves, square-cornered borders and a fixed dark palette
Visual Overview, details and settings share one set of PixelSection / PixelSegments / PixelTrace / pixel toggles and option buttons
Visual Canvas dot-matrix polylines and segmented per-core bars, with SF Symbols for action icons
Logic @Observable (Observation framework) drives all UI; Swift 6 language mode with strict concurrency
Logic MenuBarExtra(.window) with a custom label and popover content; openSettings plus settings window activation
Logic Sampling: mach host_processor_info / host_statistics64, getifaddrs, sysctl (vm.swapusage, KERN_PROC_ALL), proc_pid_rusage, getloadavg, IOKit block device statistics, IOPowerSources, ProcessInfo.thermalState
Logic SMAppService login item, AppIntents (the "Pause or resume Vitals monitoring" shortcut), UserNotifications alerts
Logic Structured-concurrency sampling loop (Task + Task.sleep), Swift Testing unit tests

Build and install

xcodegen generate
xcodebuild -project Vitals.xcodeproj -scheme Vitals -configuration Release \
  -destination 'platform=macOS,arch=arm64' -derivedDataPath .build/DerivedData build
cp -R .build/DerivedData/Build/Products/Release/Vitals.app /Applications/
open /Applications/Vitals.app

Tests:

xcodebuild test -project Vitals.xcodeproj -scheme Vitals -destination 'platform=macOS,arch=arm64' \
  -derivedDataPath .build/DerivedData

The app icon is generated by Tools/make_icon.swift (drawn with CoreGraphics, written to the asset catalog and then scaled to the full set of sizes with sips):

swift Tools/make_icon.swift Sources/Vitals/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png

Architecture

Sources/Vitals/
  VitalsApp.swift            App entry: MenuBarExtra(.window) + Settings scene
  Core/
    SensorHub.swift          @MainActor @Observable state machine; sampling loop and alert scheduling
    Samplers.swift           mach / getifaddrs / sysctl / IOKit low-level sampling
    ProcessSampler.swift     sysctl(KERN_PROC_ALL) + proc_pid_rusage process sampling
    GPUSampler.swift         IOAccelerator driver statistics and missing-value validation
    BatteryKit.swift         IOPowerSources battery reads
    AlertEngine.swift        Pure-logic alert engine (threshold + duration + cooldown)
    Models.swift             CPUTicks / CPUMath / DiskMath and other models and pure functions
    LaunchAtLogin.swift      SMAppService wrapper
    Localization.swift       Language selection, resource lookup and formatting
    Units.swift, Ring.swift
  UI/
    PopoverView.swift        Popover entry
    PixelDashboardView.swift Pixel dashboard, overview / details navigation
    PixelArt.swift           Hand-drawn pixel glyphs and the isometric host illustration
    PixelDetailsView.swift   Full details in the same pixel style
    PixelControls.swift      Pixel controls shared by settings and details
    LocalizedContent.swift   Cross-window language and locale environment
    MenuBarLabelView.swift   Menu bar label (four modes)
    SparklineRenderer.swift  CoreGraphics mini curve and V-shaped vector mark
    SettingsView.swift       Pixel settings page
    SettingsPresenter.swift  Settings window activation, first show and bring-existing-to-front
    Theme.swift
  Intents/
    ToggleMonitoringIntent.swift

Sampling cadence: CPU / GPU / memory / network / system load / disk I/O refresh every sampling interval; battery refreshes every 5 cycles, disk capacity every 30 cycles, and processes every 5 seconds, to keep resident cost down.

Known limitations

  • Process names come from kinfo_proc.kp_proc.p_comm and are capped at 16 characters; longer names are truncated
  • Process CPU usage relies on proc_pid_rusage, which may return no data for processes owned by other users, so they are skipped
  • GPU data depends on the IOKit PerformanceStatistics a driver provides — not a stable cross-machine interface; unavailable fields are N/A, never 0
  • GPU memory in use / allocated are driver counters that may overlap system memory categories; they cannot be summed or used to derive dedicated VRAM
  • Temperature, fan speed, clock frequency and power draw have no reliable source and show N/A; thermal state is not converted to degrees Celsius
  • Memory usage is an estimate from kernel page counts and is not guaranteed to match Activity Monitor exactly; memory pressure reads that fail show "unavailable"
  • Disk throughput is the sum across readable devices, including disk images, and does not represent a single startup volume; a baseline is established on new attach, counter reset and resumed sampling to avoid false spikes
  • The pixel host is a decorative illustration and does not depict the current Mac's enclosure; its indicator pixels track real CPU usage
  • The pixel overview and details use no continuous animation and update only with real samples

Visual review

Debug builds accept --debug-panel to show the popover content in an ordinary window; add --debug-dark to check the dark appearance. These entry points are not part of Release builds.

The popover is 680 × 500 and uses a fixed dark pixel dashboard. The top holds the host illustration, per-core bars and GPU history; the middle is the memory segment bar; the bottom is network, disk and system. The process ranking lives on the details page. DETAILS opens a scrollable details page and MONITOR returns to the overview; pause and settings are always reachable.

Style reference: pixel system monitor panel. All graphics are drawn with native SwiftUI / Canvas; copy comes from Resources/en.lproj and Resources/zh-Hans.lproj. Short English titles use pixel glyphs, while Chinese or missing-glyph text falls back to a crisp system font. GPU figures are real readings reported by the local driver; the power, frequency and temperature figures in the reference are neither copied nor simulated.

Data semantics

  • vm.swapusage is read through the xsw_usage binary structure, with fields in bytes.
  • Process CPU time is first converted to nanoseconds via mach_timebase_info, then converted through a time delta; one fully used logical core is 100%, and multithreaded processes can exceed 100%. See Apple XNU task.c for the conversion.
  • The memory pressure sysctl returns dispatch flags (1 / 2 / 4), which differ from the kernel-internal enumeration. See Apple XNU kern_memorystatus_notify.c.
  • Disk throughput is based on deltas of the devices' cumulative counters, matched by stable device ID and then summed. Apple's description of the bytes-read counter.

Module toggles control both the overview and details. Turning off GPU / disk I/O also stops the corresponding sampling; CPU / memory keep supplying the menu bar and alerts. With multiple GPUs the overview shows the busiest device, and switching devices rebuilds GPU history while details list every device. Performance / efficiency core counts only show the totals the system reports and do not infer per-core numbering.

License

Vitals is released under the MIT License.

Local packaging

Run bash scripts/package-app.sh to generate the Xcode project, build the Apple silicon app and place a locally signed copy at dist/Vitals.app. Quit Vitals before replacing an installed copy.

The app uses an ad-hoc signature for local builds and is not notarized. GitHub Actions runs the tests and packages a local build on macOS 26; it does not publish releases.

About

Menu bar system monitor for macOS 26+ — CPU, memory, network, disk, battery and processes on a pixel dashboard

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages