Skip to content

Latest commit

 

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MacBook 24×7 AI Agents — never sleep, lid closed, display off

Keep a MacBook running AI agents (Claude Code, Codex, etc.) around the clock — with the lid closed and the screen off — and how to undo it all.

software engineers before vs after agents — laptop carried fully closed vs slightly ajar so it doesn't sleep
"software engineers before vs after agents" — via @cormachayden_ on X. This repo is the fix for the laptop on the right.

The problem

  • macOS System Settings' "never sleep" / "Prevent automatic sleeping" option only prevents idle sleep while the lid is open.
  • Closing the lid always forces sleep, killing every running agent, SSH session, and background job. There is no setting in the UI to change this.
  • If you block lid-close sleep the hard way (below), macOS then leaves the screen on inside the closed lid — wasted power and heat — because the display normally only turns off as part of full sleep.

This repo fixes all three, and everything is reversible.

Quick install

./install.sh

That's it. It asks for sudo once, then: close the lid → Mac keeps running, screen turns off within ~2 seconds. Reopen the lid (tap a key) to wake the display.

If keyboard or mouse input wakes an external display while the lid remains closed, enable the optional keep-displays-off mode:

./install.sh --keep-displays-off

This checks for recent keyboard and mouse activity every ~2 seconds while the lid is closed, and re-blanks all connected displays only after input occurs. Re-run ./install.sh without the flag to return to the default close-transition-only behavior.

To also silence app and notification audio while the lid is closed, preserving and restoring your previous mute state when it opens:

./install.sh --keep-displays-off --mute-when-closed

Both options use the same lightweight lid watcher; no extra background process is installed. Omit either flag when re-running the installer to disable that option.

To revert everything back to normal macOS behavior:

./uninstall.sh

What it does (manual steps, if you'd rather run them yourself)

1. Never idle-sleep

sudo pmset -a sleep 0        # never sleep on AC power or battery
# or, safer if the Mac is sometimes unplugged:
sudo pmset -c sleep 0        # never sleep on charger only

2. Don't sleep when the lid closes

sudo pmset -a disablesleep 1

This is the key one — it's what the Settings app can't do. After this, closing the lid does nothing to the system.

3. Turn the display off when the lid closes

With disablesleep 1, macOS no longer blanks the screen on lid close, so a tiny watcher does it instead: lid-display-off.sh polls the lid sensor (ioreg … AppleClamshellState) every 2 seconds and runs pmset displaysleepnow the moment the lid closes. Only the display sleeps — agents keep running. A LaunchAgent (template) keeps the watcher alive and starts it at login.

By default, display blanking happens only when the lid changes from open to closed. In --keep-displays-off mode, it also checks macOS's keyboard/mouse idle timer while the lid is closed and runs pmset displaysleepnow only after recent input. This prevents keyboard or mouse activity from leaving an external display awake without repeatedly issuing display-sleep commands when nobody is interacting with the Mac.

With --mute-when-closed, the same watcher remembers the current macOS output mute state once, then reasserts mute every ~2 seconds while the lid is closed. This also retries failed mute commands and re-mutes the current output if an app, volume control, or audio-route change unmutes it. Audio enforcement works in both display modes; --keep-displays-off is not required for repeated muting. When the lid opens, the watcher restores the remembered mute state, retrying if restoration fails. The original state survives mute failures and watcher restarts.

Verify it's working

pmset -g custom                                   # sleep should be 0
pmset -g | grep SleepDisabled                     # should be 1
ioreg -r -k AppleClamshellState -d 4 | grep Clam  # Yes = lid closed
launchctl list | grep lidwatch                    # watcher running

Best proof: close the lid and SSH in from your phone.

Caveats

  • Keep it plugged in. With sleep 0 on battery the Mac runs until the battery hits 0% and dies anyway.
  • Heat. Lid-closed running blocks some venting; avoid heavy sustained loads on a pillow/blanket, give it airflow.
  • Manual sleep stops working. While disablesleep 1 is set, Apple menu → Sleep does nothing. Undo first if you actually want to sleep it.
  • Keep-displays-off mode is strict. Keyboard and mouse activity may briefly wake a display, but the watcher blanks it again within ~2 seconds. Open the lid or reinstall without the flag when you need to use an attached display normally.
  • Mute-when-closed affects output audio. Alarms or other software that bypasses the normal macOS output-mute control may behave differently.
  • Muting is polled, not instantaneous. A sound can briefly get through before the next ~2-second check after closing the lid or an external unmute. Muting also depends on macOS accepting the audio command; failures are retried.
  • Instant screen-off shortcut: Ctrl + Shift + Power (Touch ID key) blanks the display immediately at any time without sleeping anything.

Undo (manual)

sudo pmset -a disablesleep 0
sudo pmset -a sleep 1
launchctl bootout gui/$(id -u)/com.$(whoami).lidwatch
rm ~/Library/LaunchAgents/com.$(whoami).lidwatch.plist ~/bin/lid-display-off.sh

Files

File Purpose
install.sh One-shot setup: pmset changes + installs & starts the watcher
uninstall.sh Reverts everything to macOS defaults
lid-display-off.sh Watcher: manages display blanking and optional lid-closed muting
lidwatch.plist.template LaunchAgent that runs the watcher at login
tests/test-lid-display-off.sh Verifies display and mute modes with mocked macOS commands

About

Run AI agents 24x7 on a MacBook: never sleep, lid closed, display off. Fully reversible.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages