Awake macOS app icon — obsidian squircle with matte espresso cup and glowing amber steam waves
Click to toggle·
SleepDisabled: 1Wi-Fi & Agents: Active (Unrestricted)Screen: Locked (SACLockScreen)Guard: ≤10% Batt · ≥40°C Lid

Close the lid. Keep running.

Lid-closed keep-awake for Mac. Close your MacBook on battery, lock the screen automatically, and keep Claude Code, Codex, Cursor, and SSH running, with a 10% battery and 40°C backpack safety circuit breaker.

macOS
Scriptcurl -fsSL https://il.ly/awake/install.sh | sh
AI AgentInstall https://github.com/Illyism/awake on my Mac
Package
brew tap illyism/awake https://github.com/Illyism/awake && brew install --cask illyism/awake/awake
DownloadApple silicon · Control Center + Menu Bar + CLI (v1.0.0 DMG)

Using the DMG directly? Because the release build is open-source and ad-hoc signed without an Apple Developer ID, run xattr -dr com.apple.quarantine /Applications/Awake.app once before launching (the Script and Homebrew Cask installers handle this automatically).

Closed space-black MacBook Pro with a warm amber glow along the front seam beside a matte black espresso cup
Close the lid on battery and walk away. Wi-Fi stays in unrestricted performance mode while the screen locks immediately.caffeinate -dims + pmset disablesleep 1

The Clamshell Problem

Why bare caffeinate drops your agents when the lid closes

You start a long Claude Code, Codex, or Cursor run (or an SSH deploy) and close your MacBook lid to walk to a coffee shop or catch a flight. Seconds later, every request fails. That happens because macOS treats Idle Sleep and Clamshell Sleep as two completely separate state machines:

ApproachLid closed on batteryScreen lock on closeBackpack heat & battery guard
caffeinate -i / AmphetamineSleeps immediately, drops Wi-FiYes (via sleep)N/A (already asleep)
sudo pmset -a disablesleep 1Stays awakeLeft unlocked (no sleep event)Cooks in bag / drains to 0%
AwakeStays awake, Wi-Fi unrestrictedInstant SACLockScreenImmediatePauses ≤10% or ≥40°C, auto-resumes when calm
01 · UNRESTRICTED WI-FI

No hotel Wi-Fi power-save drops (-dims)

Running caffeinate -ims without -d lets powerd send kCGSDisplayWillSleep to WiFiAgent, dropping weak connections. Awake holds -dims + IOKit kPMSetClamshellSleepState(1).

02 · INSTANT CLAMSHELL LOCK

Locks loginwindow the moment the lid closes

Because disabling clamshell sleep suppresses macOS's normal sleep event, the screen would otherwise stay unlocked when closed. Awake.app listens to IOPMrootDomain (AppleClamshellState) and calls SACLockScreenImmediate() in-process.

03 · BACKPACK CIRCUIT BREAKER

Pauses at ≤10% battery or ≥40°C, resumes when calm

Every 30 seconds, the watcher checks battery %, AppleSmartBattery temperature, and macOS thermal pressure. If your closed MacBook warms up in a bag or hits 10%, Awake restores sleep and automatically resumes once plugged in or cooled down (+4% / −2°C hysteresis).

04 · ZERO-DRIFT CONTROL CENTER & MENU BAR

Event-driven kqueue + IORegistry state sync

The macOS 26 Control Center widget and Menu Bar item verify both a live caffeinate PID (sysctl) and kernel SleepDisabled = 1 in IORegistry, so a reboot or kill -9 never leaves the switch out of sync.

Terminal & GUI

One toggle in Control Center. Two words in your terminal.

Toggle from macOS Control Center, pick a countdown timer from the Menu Bar cup icon, or wrap any command in awake:

zsh · awake & asleep~/.local/bin/awake
# One-time setup: install /etc/sudoers.d/awake (or click Touch ID in the menu bar)
$ awake setup

# Keep awake indefinitely (close the lid, Wi-Fi stays up)
$ awake

# Keep awake for 45 minutes (s / m / h), then restore normal sleep
$ awake 45m

# Keep awake only while a long agent or build command runs
$ awake -- claude -p "Refactor the auth module and run the test suite"

# Inspect live state, countdown timer, battery °C, and last safety pause
$ awake status
awake  caffeinate pid 22253 (42m left)
lid    sleep disabled
temp   30C (lid limit 40C)
last   auto-stop: battery at 10%, Mon 21:08
power  Now drawing from 'AC Power'
power   -InternalBattery-0	87%; charging; 0:51 remaining

# Restore normal sleep immediately
$ asleep

# Uninstall anytime
$ curl -fsSL https://il.ly/awake/install.sh | sh -s -- uninstall

Security & Privacy

Auditable in 5 minutes. Zero network calls.

Because macOS requires root to toggle Clamshell Sleep (pmset -a disablesleep), Awake installs a dedicated, syntax-checked (visudo -cf) rule at /etc/sudoers.d/awake that permits only two exact commands with no wildcards or extra arguments:

%admin ALL=(root) NOPASSWD: /usr/bin/pmset -a disablesleep 0, /usr/bin/pmset -a disablesleep 1
  • 0 network requestsNeither the Zsh script, the menu bar app, nor the Control Center widget ever opens a socket.
  • Sandboxed WidgetExtensionAwakeControl.appex runs in the macOS App Sandbox with read-only access to ~/.cache/awake/ (0700).
  • Optional sleep hookDrop an executable script at ~/.config/awake/on-sleep to auto-unmount encrypted volumes when closing the lid.