Keep your Mac battery healthy, the secure way
A security-hardened fork of BatteryOptimizer_for_Mac, rewritten in Swift.
The best way to preserve your Mac's battery health.
brew install MoonBoi9001/tap/apple-juice
sudo apple-juice visudo
apple-juice maintain longevityThree commands. Set it and forget it. Configure macOS settings for notifications.
| What it does | Why it matters |
|---|---|
| Maintains charge between 60-65% | Sweet spot for lithium-ion longevity |
| Runs on wall power when plugged in | Battery sits idle at low voltage, minimal degradation |
| Cell imbalance monitoring | Shows per-cell voltages and imbalance in status |
| BMS balancing | Charges to 100% and holds for equalization when cells drift |
Lithium-ion cells degrade faster at higher voltages. At 100% charge each cell sits at ~4.2V, accelerating chemical wear. At 60-65% the resting voltage drops to ~3.95V/cell, significantly reducing stress. Once the battery reaches 65%, charging is disabled. The laptop then runs entirely from wall power — no current flows through the battery at all. Charging re-enables if the battery drops below 60%.
Homebrew (Apple Silicon only):
brew install MoonBoi9001/tap/apple-juice
sudo apple-juice visudoThen run:
apple-juice maintain longevity # recommendedOr pick your own level:
apple-juice maintain 80 # maintain 75-80%
apple-juice maintain 80 50 # maintain 50-80%🔋 Battery Management
| Command | Description |
|---|---|
apple-juice maintain longevity |
Recommended. Maintain 60-65% for max lifespan |
apple-juice maintain 80 |
Maintain 75-80% |
apple-juice maintain 80 50 |
Maintain 50-80% |
apple-juice maintain suspend |
Temporarily charge to 100% |
apple-juice maintain recover |
Resume after suspend |
apple-juice maintain stop |
Disable completely |
apple-juice charge 90 |
Charge to specific level |
apple-juice discharge 50 |
Discharge to specific level |
🔄 Calibration
| Command | Description |
|---|---|
apple-juice calibrate |
Full calibration cycle |
apple-juice calibrate stop |
Stop calibration |
apple-juice balance |
Charges to 100%, holds 90 min for BMS equalization, then resumes previous mode |
apple-juice schedule |
Configure scheduled calibration |
apple-juice schedule disable |
Disable scheduled calibration |
📊 Monitoring
| Command | Description |
|---|---|
apple-juice status |
Health, temp, cycle count |
apple-juice status --csv |
Machine-readable CSV output |
apple-juice dailylog |
View daily battery log |
apple-juice calibratelog |
View calibration history |
apple-juice logs |
View CLI logs |
apple-juice ssd |
SSD health status |
apple-juice ssdlog |
SSD daily log |
⚙️ System
| Command | Description |
|---|---|
brew upgrade moonboi9001/tap/apple-juice |
Upgrade via Homebrew |
apple-juice update |
Update to latest version |
apple-juice version |
Show current version |
apple-juice changelog |
View latest changelog |
apple-juice reinstall |
Reinstall from scratch |
apple-juice uninstall |
Remove completely |
The v2.0 rewrite eliminates entire classes of vulnerabilities present in the original bash implementation:
- No shell interpolation — native Swift binary, no bash/sed/awk attack surface
- Atomic file writes for all config and PID files
- Signal handler serialization via GCD (no re-entrancy)
- Input validation on all user-facing commands
- Process verification on PID files (confirms apple-juice owns the process)
SMC access is granted through visudo with specific command allowlists — only the exact smc key/value pairs needed for charging control are permitted.
apple-juice runs as a background daemon managed by macOS launchd. It reads battery state through IOKit and controls charging via SMC keys using the bundled smc binary.
When the battery reaches the upper limit (65% in longevity mode), charging is disabled via SMC. The laptop continues to run entirely from wall power — the battery sits idle at its resting voltage with no current flowing. Charging only re-enables when the battery drops below the lower limit (60%), which only happens if you unplug.
The daemon is configured as a LaunchAgent with KeepAlive, so macOS automatically restarts it if the process dies unexpectedly. On clean shutdown (maintain stop), it re-enables charging and stays stopped. A startup recovery check runs before every command: if charging is found disabled but the daemon is not running, charging is re-enabled automatically. This ensures a Mac is never left in a non-charging state.
Architecture:
- Native Swift binary (no bash, no Python, no runtime dependencies)
- IOKit for direct battery reads (no
ioregsubprocess overhead) - IOKit power notifications for sleep/wake handling (no sleepwatcher dependency)
IOPMAssertionCreateWithNamefor sleep prevention (no caffeinate)- File-per-key config storage with atomic writes
- Serial dispatch queue for thread-safe SMC access
Always use apple-juice uninstall rather than brew uninstall directly. The uninstall command re-enables charging, stops the LaunchAgent, and cleans up all configuration files.
apple-juice uninstall
brew uninstall apple-juice # optional, removes the binaryRunning brew uninstall alone will remove the binary but leave the LaunchAgent plist and configuration in place.
Three quick settings to configure:
|
System Settings → Battery → Battery Health Turn off |
|
System Settings → Notifications Turn on |
|
System Settings → Notifications → Script Editor Select |
╔═══════════════════════════════════════════════════════════════╗
║ ║
║ DISCLAIMER ║
║ ║
║ This software is provided as-is, without warranty of any ║
║ kind. Use at your own risk. Battery management involves ║
║ low-level system operations. The authors are not liable ║
║ for any damage to your device. Back up before use. ║
║ ║
╚═══════════════════════════════════════════════════════════════╝
Made with 🧃 by the community