The Task Manager macOS Never Gave You
I grew up on Windows. Ctrl+Alt+Del was muscle memory.
When I switched to Mac, the first thing I missed was a real Task Manager.
Activity Monitor felt like reading a spreadsheet when your house is on fire.
So I built MacPulse - the system monitor I always wanted on macOS.
How It Works • Features • Install • Extended Telemetry • Releases • Build • Architecture • Contributing
MacPulse is a native Swift/SwiftUI application. No Electron, no web views, no Python wrappers. It reads system telemetry directly from macOS kernel interfaces and publishes one atomic UI frame per refresh cycle.
CPU counters come from the Mach host_processor_info kernel trap, which returns per-logical-processor tick counts (user, system, idle, nice) for every core. MacPulse diffs consecutive samples to compute real-time utilization per logical processor - no top, no ps, no shell spawning. Memory stats use host_statistics64 with HOST_VM_INFO64 for wired, active, inactive, compressed, and free page counts.
MacPulse works out of the box with zero dependencies. For extended telemetry (CPU frequency, package power in watts, die temperature), install these optional providers:
| Provider | What it unlocks | Install |
|---|---|---|
| Intel Power Gadget | CPU frequency (GHz), package power (W), die temperature (C) | Download .dmg from Intel. MacPulse looks for PowerLog in /Applications/Intel Power Gadget/, /Library/Intel/Power Gadget/, and /usr/local/bin/. |
| smartmontools | Full NVMe/SATA SMART attributes: available spare, percentage used, life remaining, power-on hours, media errors, data written | brew install smartmontools - MacPulse uses smartctl when available. |
| NVIDIA drivers | GPU utilization, VRAM, clocks, temperature, power draw, fan speed | MacPulse reads nvidia-smi from /usr/local/bin/, /opt/homebrew/bin/, or /usr/bin/ when present. |
All three are strictly optional. If a provider is not installed, MacPulse skips it silently and shows only what the native macOS APIs expose.
Storage throughput is sampled from IOKit IOBlockStorageDriver counters attached to whole-disk IOMedia registry objects. Each physical device resolves to one parent statistics table, avoiding double-counting from APFS container synthesis. diskutil inventories physical devices; the device list refreshes only on plug/unplug events, not every sample cycle.
SMART diagnostics are on-demand only - no background polling. When you click "SMART health report," MacPulse reads the macOS-provided SMARTStatus from IOKit first. If smartctl is installed (see table above), it additionally parses NVMe/SATA health attributes: overall status, available spare, percentage used, life remaining, temperature, power-on hours, media errors, and data read/written totals.
MacPulse never invents a SMART percentage. If the drive or its USB/Thunderbolt bridge doesn't expose a metric, that field is absent - not zero, not "Healthy," not estimated.
Network throughput uses getifaddrs per-interface byte counters - no netstat, no shell commands. GPU utilization reads IOKit IOAccelerator / AGXAccelerator performance dictionaries when the driver exposes them (Apple Silicon and most AMD GPUs report natively without additional tools).
Every process is classified as Apple system, third-party background, or installed application using a multi-signal pipeline:
- Name catalog - a curated list of ~200 known Apple executables for processes where protected metadata is unavailable
- Code signature - verified Apple or third-party signing identity
- Bundle identity -
CFBundleIdentifierresolved from the owning.appbundle - Team ID - Apple Developer Team identifier from the code signature
- Executable path - filesystem location (
/System/,/Library/,/Applications/, user space) - Application ownership - helper executables resolved to the outermost
.appbundle (Chrome renderers → Google Chrome, Docker helpers → Docker Desktop)
Each classification carries a confidence percentage and lists the evidence that produced it. A name-catalog match alone scores lower than a name + signature + bundle match. This pipeline powers the view filters (see below).
Startup apps are scanned from ~/Library/LaunchAgents, /Library/LaunchAgents, /Library/LaunchDaemons, and (optionally) /System/Library/Launch*. Each plist is parsed for its label, program, and RunAtLoad state. The owning application is resolved from bundle containment, executable path matching, or bundle-identifier family evidence.
Enable/disable uses launchctl disable/enable gui/<uid>/<label> (or system/<label> for daemons). If the direct call fails, MacPulse falls back to osascript with administrator privileges. After every change, the actual launchctl print-disabled output is re-read to verify the operation succeeded - if the state didn't change, the error is surfaced instead of silently swallowed.
Windows-style process groups: Apps, Background processes, macOS processes. CPU is normalized to total machine capacity (0-100%), not the confusing per-core percentage macOS uses (where 800% means 8 cores busy). Expand any app to see its child processes.
- Column sorting - click any column header to sort ascending/descending by: CPU, Memory, GPU, Disk, Disk Read, Disk Write, Name, PID, Threads, Priority, Start Time, Status, User, Architecture, Publisher
- View filters - filter processes by origin classification:
- All processes
- Installed software (excludes Apple system components)
- Third-party background only (helpers, agents, menu-bar utilities, launch items)
- My Processes (current user only)
- Apple Only (Apple-signed apps and OS components)
- Unknown (processes with no determinable origin)
- Configurable columns - right-click any column header to show/hide: CPU, Memory, Disk, Disk read/write, GPU, PID, Priority, Architecture, Start time, Publisher, Threads
- Process actions - End task, Force terminate, Suspend, Resume
- Search - filter by name, publisher, or PID
Double-click any process to open a six-tab inspector:
| Tab | What It Shows |
|---|---|
| Overview | CPU, memory, threads, open file count |
| Process Tree | Actual parent-child PID relationships and probable related components |
| Identity | Software origin, classification confidence, bundle ID, executable path, code signature evidence |
| Open Files | Every file descriptor held by the process |
| Control | Suspend / Resume / Terminate / Force Terminate, priority adjustment (Background → Very High), process tree termination |
Cumulative CPU time, disk read, disk write, and memory per application since session start. Helper processes are grouped under their parent app. Click any column header to sort ascending/descending.
| Tab | Description |
|---|---|
| Users | Every user account with process count, aggregate CPU, memory, threads |
| Details | Flat process list with every available column (matches Windows Details tab) |
| Services | All running launchd services - Apple system and third-party - with PID |
Persistent menu-bar icon with live CPU percentage. Click for a popover with CPU/memory graphs and the top 5 processes. Can be disabled from Settings.
Chart types (area/line), CPU graph mode (overall/logical processors), visible history length (up to 600 samples), grid/axis toggles, refresh interval (0.5-5s), and telemetry provider diagnostics.
- Go to Releases
- Download
MacPulse-8.0.3-macOS-universal.dmg - Open the DMG, drag MacPulse to Applications
- Launch from Applications
First launch: macOS may show "can't be opened because Apple cannot check it for malicious software." Right-click the app → Open → Open. This only happens once with ad-hoc signed builds.
Requirements: macOS 12 Monterey or later. Universal binary (Apple Silicon + Intel).
For CPU wattage, frequency, and temperature readings on Intel Macs, install Intel Power Gadget. For full SMART disk health attributes (life remaining, power-on hours, media errors), install smartmontools: brew install smartmontools. Both are detected automatically on next launch.
| Asset | Description |
|---|---|
MacPulse-8.0.3-macOS-universal.dmg |
Drag-to-Applications disk image, universal binary (arm64 + x86_64), ad-hoc signed |
MacPulse-8.0.3-macOS-universal.zip |
Compressed .app bundle for manual placement or CI integration |
git clone https://github.com/vluncasu/MacPulse-Task-Manager.git
cd MacPulse-Task-Manager
make release # universal binary (arm64 + x86_64) -> dist/MacPulse.app
make dmg # drag-to-Applications installer -> dist/MacPulse-8.0.3-macOS-universal.dmg
make test # run XCTest suiteRequirements: macOS 12+, Xcode 13.4.1+ (full installation, not just Command Line Tools).
Or double-click: BUILD_MACOS.command / BUILD_DMG.command / OPEN_IN_XCODE.command.
| Language | Swift 5.6+ / SwiftUI / AppKit |
| Target | macOS 12 Monterey+ |
| Binary | Universal (arm64 + x86_64) |
| Dependencies | Zero external - only Apple system frameworks |
| CPU sampling | Mach host_processor_info per-logical-processor tick diffs |
| Memory | Mach host_statistics64 with HOST_VM_INFO64 |
| Disk I/O | IOKit IOBlockStorageDriver counters on whole-disk IOMedia objects |
| Network | getifaddrs per-interface byte counters |
| GPU | IOKit IOAccelerator / AGXAccelerator performance dictionaries |
| Disk inventory | diskutil physical device enumeration (refreshed on plug/unplug only) |
| SMART | IOKit SMARTStatus + optional smartctl enrichment for NVMe/SATA |
| Process identity | Code signature + bundle ID + Team ID + name catalog + path heuristics |
| Optional providers | Intel Power Gadget (CPU freq/power/temp), nvidia-smi (NVIDIA GPU) |
Single-process SwiftUI application. No kernel extensions, no helper daemons, no background services beyond the optional menu-bar companion.
Project structure
MacPulse/
App/ Application entry point, AppDelegate, window lifecycle
Models/ Data models - ProcessRecord, SystemSnapshot, PowerSnapshot, AppSettings
Services/ Telemetry engine - SystemSampler, SystemMonitor, HardwareInspector, StartupMonitor
Views/ SwiftUI views - ProcessesView, PerformanceView, ProcessInspectorView, SettingsView
Views/Components/ Reusable UI - ChartView, ProcessIconView, SectionCard, sidebar components
Resources/ Asset catalogs, entitlements, Info.plist
scripts/ Build automation - build-release.sh, create-dmg.sh, github-push.sh
screenshots/ Application screenshots for documentation
Distribution/Public/ Community edition configuration and App Store entitlements
Contributions are welcome. Whether it's a bug fix, a new feature, or a documentation improvement - every pull request gets reviewed.
Found a bug? Open an issue with your macOS version and steps to reproduce. Crash logs from ~/Library/Logs/DiagnosticReports/ are always helpful.
Want to contribute code? Fork the repo, create a feature branch, and submit a PR. The codebase builds with a single make release - no package managers, no dependency setup.
Have an idea? Start a discussion or open a feature request issue. We track everything in GitHub Issues.
If MacPulse is useful to you, consider giving the project a ⭐ - it helps others discover it.
Available under the MIT License. Use it, fork it, build on it.
Built with Swift and SwiftUI by TerabitLab
Star this project • Report a bug • Fork it



















