This guide provides a workaround for macOS battery drain issues during sleep by automatically disabling Bluetooth and WiFi when the system sleeps and re-enabling them on wake.
macOS currently has issues with battery draining during sleep when Bluetooth and WiFi remain active.
Use sleepwatcher to run scripts that:
- Disable Bluetooth and WiFi when the system goes to sleep
- Re-enable Bluetooth and WiFi when the system wakes up
- Install Homebrew (if not already installed):
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"- Install sleepwatcher:
brew install sleepwatcher- Install blueutil (for Bluetooth control):
brew install blueutilCreate ~/.sleep file:
cat > ~/.sleep << 'EOF'
#!/bin/bash
exec >> ~/lid-events.log 2>&1
echo "Lid closed or system sleeping at $(date)"
# Print battery level
echo "Battery level $(pmset -g batt | grep -Eo '\d+%' | cut -d% -f1)%"
# Run commands in background with nohup to avoid blocking sleep
nohup sh -c '/opt/homebrew/bin/blueutil --power 0 2>/dev/null; networksetup -setairportpower en0 off 2>/dev/null' &>/dev/null &
# Exit immediately to let system sleep
exit 0
EOFCreate ~/.wakeup file:
cat > ~/.wakeup << 'EOF'
#!/bin/bash
exec >> ~/lid-events.log 2>&1
echo "Lid opened or system woke up at $(date)"
# Print battery level
echo "Battery level $(pmset -g batt | grep -Eo '\d+%' | cut -d% -f1)%"
/opt/homebrew/bin/blueutil --power 1; networksetup -setairportpower en0 on
EOFMake scripts executable:
chmod +x ~/.sleep ~/.wakeupStart and enable the service to run at login:
brew services start sleepwatcherCheck that sleepwatcher is active:
brew services list | grep sleepwatcherYou should see:
sleepwatcher started [username] ~/Library/LaunchAgents/homebrew.mxcl.sleepwatcher.plist
-
Terminal/iTerm Access: You may need to grant Terminal or your terminal app permission to control system settings
- Go to System Settings → Privacy & Security → Accessibility
- Add and enable your terminal application
-
Network Configuration Access: The
networksetupcommand may trigger a permission dialog- Click "Allow" when prompted
-
Automation Permissions: You might need to approve automation access
- Go to System Settings → Privacy & Security → Automation
- Enable necessary permissions for Terminal
Check the log file to verify it's working:
tail -f ~/lid-events.logYou should see entries like:
Lid closed or system sleeping at [timestamp]
Lid opened or system woke up at [timestamp]
After sleep/wake, verify the radios are being controlled:
# Check Bluetooth status
blueutil --power
# Check WiFi status
networksetup -getairportpower en0- Check sleepwatcher is running:
brew services list | grep sleepwatcher- Restart the service:
brew services restart sleepwatcher- Check for errors in system log:
log show --predicate 'process == "sleepwatcher"' --last 1hThis setup uses nohup and background execution to prevent immediate wake. If you still experience issues:
- Verify the
.sleepscript has the correct content with background execution - Ensure you're using the exact script format provided above
- Check that
blueutilis installed at/opt/homebrew/bin/blueutil
If you want to stop using this workaround:
brew services stop sleepwatcherTo completely uninstall:
brew services stop sleepwatcher
brew uninstall sleepwatcher
rm ~/.sleep ~/.wakeup- sleepwatcher: Monitors system sleep/wake events and triggers scripts
- Background execution: Using
nohupand&prevents the commands from blocking the sleep process - Immediate exit: The script exits quickly, allowing the system to complete the sleep transition
- Logging: All events are logged to
~/lid-events.logfor troubleshooting
This is a temporary workaround until Apple fixes the underlying battery drain issue in macOS. The solution has been tested and confirmed to work without causing immediate wake issues.