macOS App

ChargeBeep

A 150 KB Mac menu bar app that plays a sound when your battery reaches the charge level you pick. Plain Swift, no Electron, no network code.

  • Swift
  • AppKit
  • IOKit
  • IOPowerSources
ChargeBeep app icon — a battery with a sound wave

Why it exists

My MacBook used to sit at 100% charge all day, which is the worst thing you can do to a lithium battery. ChargeBeep is a tiny menu bar app that fixes this: you pick a charge level, plug in, and walk away — the moment the battery hits your target, it plays a sound. It also shows the exact battery percentage in the menu bar, which macOS hides by default.

The whole app is a single ~730-line Swift file, no storyboards, no package manager, no dependencies. It compiles with one swiftc -O invocation into a ~150 KB binary.

Event-driven, not polled

The first version polled the battery every 30 seconds. It worked, but it was the wrong design — too slow for an instant alert, and wasteful at shorter intervals. The system already knows when power changes, so the final version subscribes to IOPSNotificationCreateRunLoopSource and adds it to the main run loop. That callback fires the instant you plug in, unplug, or the percentage ticks — reaction is immediate and the app is idle the rest of the time. A one-minute Timer stays as a belt-and-suspenders fallback, plus a didWakeNotification observer to re-check immediately after the Mac wakes from sleep.

Battery values come from IOPSCopyPowerSourcesInfo / IOPSGetPowerSourceDescription rather than shelling out to pmset and parsing text — I read kIOPSCurrentCapacityKey and kIOPSMaxCapacityKey off the internal-battery power source and compute the percentage directly. No string parsing, no subprocess per tick.

Keeping the Mac awake without breaking sleep

Keeping the Mac awake while charging was the tricky part. The obvious approach — sudo pmset disablesleep 1 — needs a password and, worse, leaves system sleep permanently disabled if the app ever crashes before it can undo it. That’s a terrible thing to ship.

The right tool is an IOKit power assertion: IOPMAssertionCreateWithName with kIOPMAssertionTypePreventUserIdleSystemSleep. It needs no privileges, works with the lid open, and — critically — the kernel releases it automatically when the process dies. Sleep can never get stuck. The assertion is created only while actively charging below the threshold and released the moment the target is hit, so the Mac goes back to normal power behavior as soon as its job is done.

There’s an optional “powerful mode” for keeping the Mac awake with the lid closed, which genuinely does require pmset disablesleep. Instead of asking for a password every time, ChargeBeep installs a single narrowly-scoped sudoers.d rule — NOPASSWD for exactly /usr/bin/pmset disablesleep * and nothing else — via one admin prompt, and removes that file cleanly when the mode is turned off or the app is uninstalled.

The one-shot “armed” pattern

Playing the sound exactly once per charge cycle is deceptively fiddly: the power callback can fire many times around the threshold. I use a small armed boolean — it’s set true while plugged in and below target, and the beep only fires on the below→reached transition, then disarms. Unplugging re-arms it. It’s a tiny state machine, but it’s the difference between one polite chime and your laptop beeping at you every few seconds.

Built small on purpose

  • Plain Swift and AppKit — no Electron, no SwiftPM, no third-party code
  • ~150 KB binary from a single main.swift
  • No network code at all: nothing is tracked, nothing phones home
  • Autostart via a LaunchAgent plist written on first run (works on macOS 11+, no deprecated login-item APIs)
  • Ships as a drag-to-Applications .dmg built by a ~60-line bash script
  • Sound picker auto-discovers bundled, system, and user-provided audio files