Skip to content

Latest commit

 

History

29 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

keepawake

Keep a Mac awake - even on battery with the lid closed. ARM & Intel.

Install

brew tap ecc521/keepawake
brew install ecc521/keepawake/keepawake
sudo keepawake install

Or build from source with cd cli/keepawake && ./build.sh, then run sudo ./keepawake install.

The one-time install step adds a sudoers rule permitting exactly two commands (/usr/bin/pmset -a disablesleep 0/1). Remove both at any time with sudo keepawake uninstall.

Use

keepawake                    # run until Ctrl-C
keepawake -t 3600            # run for 1 hour, then stop automatically
keepawake -- ./backup.sh     # run a command, stop when it exits
keepawake --battery 20       # release the hold at 20% battery; default 10

Whenever keepawake stops, the hold is released and normal sleep resumes. The -d -i -m -s -u flags match caffeinate, so you can use keepawake in its place and still cover ordinary display and disk sleep. Full CLI reference: cli/keepawake/README.md.

The problem

Clamshell mode automatically sleeps, even with caffeinate, unless plugged into both an external display and charger.

The display requirement can be bypassed with a virtual display, but that does not satisfy the charging requirement.

The only available option (that I am aware of) here is pmset, to fully disable the sleep capability.

How it works

keepawake holds the system-wide SleepDisabled power-management setting, via pmset -a disablesleep 1, for as long as the session lasts.

Setting it requires root, which is what the one-time sudo keepawake install is for. It writes /etc/sudoers.d/keepawake:

%admin ALL=(root) NOPASSWD: /usr/bin/pmset -a disablesleep 1, /usr/bin/pmset -a disablesleep 0

SleepDisabled governs system sleep only. Display and disk sleep are independent timers. keepawake also runs /usr/bin/caffeinate internally (tied to its own lifetime via -w) to hold those assertions, so it can be used as a drop-in caffeinate replacement that guarantees full sleep prevention instead of sleep prevention only when plugged in and on AC power

Safety cutoffs

An unattended device (car, backpack, etc) that is left running could easily overheat or run itself out of battery. The cutoffs here are conservative defaults, however are intended to reduce the risk of unexpected surprises.

  • --battery <pct>|none (default 10): releases only on battery when battery drops below the specified percentage.
  • --thermal none|serious|critical (default critical): releases under thermal pressure. serious is reached by ordinary heavy CPU/GPU work, but is likely a better choice for devices in enclosed areas.

Both locks reacquire immediately after battery / thermal pressure have dropped.

Recovering a stuck hold

SleepDisabled is persisted to disk, so a run killed with kill -9 or lost to a panic can leave it set. Any of these clears it:

keepawake --release          # explicit
keepawake ...                # any later run takes the hold, then clears it on exit
sudo pmset -a disablesleep 0 # directly, no keepawake involved

pmset -g reports SleepDisabled on its first line, which is also the answer to "why won't this Mac sleep?".

Known limitations

  • The hold is system-wide. It is one global setting, not a per-process assertion. Concurrent sessions are fine: they share a flock(2), and the last one out releases the hold, but that also means the last session ending clears a hold you set by hand outside keepawake.

Testing

./tests/run_tests.sh

Tests that take a real hold need the sudoers rule installed and skip cleanly without it. A physical lid close still has to be tested by hand.

License

MIT. See LICENSE.

About

Keep a MacBook awake with the lid closed - no external display, no dummy plug, no kext.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages