PowerGrid is a macOS power management tool composed of:
- A root daemon that monitors battery/adapter state and applies charge-limiting logic.
- A SwiftUI menu bar app that installs the daemon and provides controls and status.
⚠️ Experimental projectPowerGrid is a testbed, not a polished product. Interfaces and behaviors may change. If you need a production-ready tool, consider established alternatives. Some noteworthy ones are listed below.
- Menu bar status with icons for charge, charging state, and limiter active.
- Control Center-Inspired Toggles: A grid of beautiful, macOS-style buttons provides immediate, one-click access to essential power management functions like Force Discharge and Prevent Display Sleep.
- Live status: current charge, adapter description, health (%), cycle count.
- Time estimates: Time to Full (while charging) or Time to Empty (while discharging), formatted hh:mm. Time to Full automatically scales to your active charge limit when <100% and hides when full/at limit/paused.
- Power metrics: system, adapter, and battery wattage; adapter input voltage and amperage.
- Charge limit slider from 60–100%.
- Power Assertions: Prevent Display/System Sleep.
- Force Discharge: Discharges even when an adapter is present; only selectable if an adapter is present.
- Force Discharge Automatic: Discharges to your limit, then auto-disables; only selectable above limit.
- Native Notifications: Alerts for key events (e.g., cutoff), single permission prompt.
- Low Power Notifications: Alerts at 20% and 10% while discharging; includes an action button to enable macOS Low Power Mode when off.
- Advanced Battery Details: When enabled in Advanced Options, shows additional battery information below the power metrics.
- Serial Number, Design/Maximum/Nominal Capacity (mAh)
- Battery Voltage (V), Battery Current (A), Temperature (°C)
- Individual Cell Voltages (V) and a Drift indicator: Normal (green), Slight (yellow), High (red)
- Disable Charging Before Sleep: Configurable in Advanced Options and persisted per user by the daemon. When enabled, the daemon proactively disables charging on system sleep.
- MagSafe LED Control: When enabled in Advanced Options (and supported by hardware), the daemon reflects charging modes on the MagSafe LED.
- Charging (limit off or below limit): Amber
- Fully charged or at/above user limit: Green
- Force Discharge: Off
- Low battery (≤10%): Amber blinking
- Safe default: when disabled or on startup, LED is returned to System control
- Developer submenu: In dirty builds, Advanced Options shows a "Developer" submenu with short forms of both BuildIDs and tooltips with full hashes.
This project uses a Makefile to automate the build process.
- macOS with Xcode (26+ recommended) installed.
- Go toolchain.
- Homebrew for installing protobuf dependencies:
brew install protobuf swift-protobuf protoc-gen-grpc-swift
- Clone the repository:
git clone https://github.com/peterneutron/powergrid.git
Before you can build from the command line, you need to configure code signing once in Xcode.
- Open
PowerGrid.xcodeprojin Xcode. - In the project navigator, select the "PowerGrid" project, then the "PowerGrid" target.
- Go to the "Signing & Capabilities" tab.
- From the "Team" dropdown, select your personal Apple ID. Xcode will automatically create a local development certificate for you.
- You can now close Xcode.
Every lane writes artifacts into ./build and runs make proto as needed to keep generated sources in sync.
make build– unsigned local build. Equivalent to invokingmakewith no arguments; runs the protobuf generator, copies the Swift stubs, and producesbuild/PowerGrid.appwith signing disabled.make devsigned– development-signed build using automatic signing. ProvideSIGNING_IDENTITY="Apple Development: Your Name (TEAMID)"when you know the exact identity; otherwise the Makefile launchesscripts/select_signing_identity.shto discover certificates via thesecuritytool and prompt you to choose.make archive– manual-signing archive for maintainers. Accepts/auto-discoversSIGNING_IDENTITYin the same way and createsbuild/PowerGrid.xcarchive.make export– exports an.appfrom the latest archive usingExportOptions.plist.make package– createsbuild/PowerGrid.zipfrom the unsigned app bundle.make clean– removes./buildplus generated protobuf outputs.
Notes on version pairing and build artifacts:
- During every build lane, the daemon is compiled with an ldflags-stamped
BuildIDand a sidecar filepowergrid-daemon.buildidis produced and bundled into the app. This avoids coupling hashes to code signing. - The app compares its embedded
BuildIDto the daemon'sGetVersionresponse on first connection to decide if an upgrade prompt is needed.
The signing helper script requires the Xcode command line tools and at least one Apple Development certificate in your login keychain.
The Makefile provides several targets to streamline development:
make build: Default unsigned lane (same as runningmake). Regenerates protobuf stubs before compiling.make devsigned: Development-signed build that auto-selects your certificate ifSIGNING_IDENTITYis not supplied.make archive: Manual-signing archive for release validation.make export: Export from the latest archive; tweakExportOptions.plistfor different export styles.make package: Zip the unsigned app bundle for quick sharing.make proto: Regenerate gRPC code only (useful when iterating onproto/powergrid.proto).make clean: Remove build artifacts and generated code to start fresh.sudo -E go run ./cmd/powergrid-daemon: Run the daemon directly for debugging (requires root).
PowerGrid uses standard macOS preferences (CFPreferences / defaults) and a simple precedence: user > system > built‑in default.
-
System (daemon):
/Library/Preferences/com.neutronstar.powergrid.daemon.plistChargeLimit(int, 60–100): System charge limit used when no user is active or user has no override.
-
Per‑user (daemon/app):
~/Library/Preferences/com.neutronstar.powergrid.plistChargeLimit(int, 60–100): User override for effective charge limit.ControlMagsafeLED(bool): When true (and supported), daemon controls MagSafe LED state.DisableChargingBeforeSleep(bool, default true): When true, daemon proactively disables charging on system sleep.
-
App UI (UserDefaults in the app domain):
menuBarDisplayStyle,preferredChargeLimit,lowPowerNotificationsEnabled,showBatteryDetails.- These are UI-only and do not affect the daemon directly (except via RPC calls when you change settings in the app).
Notes:
- Low Power Mode (macOS) is not persisted by PowerGrid; the daemon reads the current state via
pmset -gand toggles it viapmset -awhen requested.
All daemon activity is logged to the macOS Unified Logging system. You can view logs using Console.app or the command line:
log stream --predicate 'subsystem == "com.neutronstar.powergrid.daemon"'- Built on PowerKit-Go for IOKit/SMC access and event streaming.
- Google Gemini and OpenAI GPT families of models and all the labs involved making these possible 🙏
