Skip to content

macOS menu bar app for live battery and power monitoring with charge limiting, sleep control, and advanced power management tools.

License

Notifications You must be signed in to change notification settings

peterneutron/powergrid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

77 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PowerGrid

Main View


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 project

PowerGrid 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.

Features

  • 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.

Getting Started: Building from Source

This project uses a Makefile to automate the build process.

1. Prerequisites

  • 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

2. One-Time Setup in Xcode

Before you can build from the command line, you need to configure code signing once in Xcode.

  1. Open PowerGrid.xcodeproj in Xcode.
  2. In the project navigator, select the "PowerGrid" project, then the "PowerGrid" target.
  3. Go to the "Signing & Capabilities" tab.
  4. From the "Team" dropdown, select your personal Apple ID. Xcode will automatically create a local development certificate for you.
  5. You can now close Xcode.

3. Pick a Build Lane

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 invoking make with no arguments; runs the protobuf generator, copies the Swift stubs, and produces build/PowerGrid.app with signing disabled.
  • make devsigned – development-signed build using automatic signing. Provide SIGNING_IDENTITY="Apple Development: Your Name (TEAMID)" when you know the exact identity; otherwise the Makefile launches scripts/select_signing_identity.sh to discover certificates via the security tool and prompt you to choose.
  • make archive – manual-signing archive for maintainers. Accepts/auto-discovers SIGNING_IDENTITY in the same way and creates build/PowerGrid.xcarchive.
  • make export – exports an .app from the latest archive using ExportOptions.plist.
  • make package – creates build/PowerGrid.zip from the unsigned app bundle.
  • make clean – removes ./build plus generated protobuf outputs.

Notes on version pairing and build artifacts:

  • During every build lane, the daemon is compiled with an ldflags-stamped BuildID and a sidecar file powergrid-daemon.buildid is produced and bundled into the app. This avoids coupling hashes to code signing.
  • The app compares its embedded BuildID to the daemon's GetVersion response 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.

Development Workflow

The Makefile provides several targets to streamline development:

  • make build: Default unsigned lane (same as running make). Regenerates protobuf stubs before compiling.
  • make devsigned: Development-signed build that auto-selects your certificate if SIGNING_IDENTITY is not supplied.
  • make archive: Manual-signing archive for release validation.
  • make export: Export from the latest archive; tweak ExportOptions.plist for different export styles.
  • make package: Zip the unsigned app bundle for quick sharing.
  • make proto: Regenerate gRPC code only (useful when iterating on proto/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).

Configuration

PowerGrid uses standard macOS preferences (CFPreferences / defaults) and a simple precedence: user > system > built‑in default.

  • System (daemon): /Library/Preferences/com.neutronstar.powergrid.daemon.plist

    • ChargeLimit (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.plist

    • ChargeLimit (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 -g and toggles it via pmset -a when requested.

Logging

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"'

Acknowledgments

  • 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 🙏

About

macOS menu bar app for live battery and power monitoring with charge limiting, sleep control, and advanced power management tools.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published