Keep your Mac awake while your coding agent is working — even with the lid closed — without cooking it.
caffeinate keeps a Mac from dozing, but the moment you close the lid it sleeps anyway, and your long-running agent task dies with it. cocaffeinate holds the machine open through a closed lid for exactly as long as Claude or Codex is actually running, then hands sleep back to the OS the instant the agent quits. It watches the battery and the temperature while it does, so a laptop left running in a bag puts itself to sleep instead of overheating.
The name is the joke: co- as in Codex and Claude Code, and as in collaborator — the machine stays awake for the agent you're working with, not forever.
A friend texted me a LinkedIn post: Huel has a "laptops closed" mandate so people stay present in meetings. The one exception that keeps coming up is their Finance Director, who told the room "I can't close my laptop — I've got Claude running a big task for me." The post's punchline was a photo of a 3D-printed plastic hand you wedge under the lid to prop it open, and a joke about buying everyone one.
A plastic hand is a hardware patch for a software problem. It props the lid open with zero awareness — it will happily let your MacBook bake in a backpack on battery. So: a script instead. One that knows why it's keeping the lid open, and stops the moment the reason goes away.
There are two macOS levers, and then there's what cocaffeinate decides to do with them.
The levers:
caffeinatecan block idle, disk, display, and system sleep. No admin. But it does not survive a physical lid close.pmset disablesleepsets the kernel flag that does survive a closed lid on battery with no external display. Needssudo. This is the part--lidturns on.
What cocaffeinate decides on top of them:
- System awake, screen asleep — it pulls
caffeinateso the system stays up while the display is free to sleep (no reason to light a panel nobody's watching, and it sidesteps burn-in).--keep-displayoverrides. - Agent-gated — with
--while-agentit only holds the levers while Claude or Codex is running, and releases the instant the last one quits. - Battery floor — on battery, it restores normal sleep at a charge floor (default 20%) so it can't fully drain.
- Thermal failsafe — if the SoC hard-throttles (the classic no-airflow-in-a-bag symptom) or crosses a temperature ceiling, it doesn't just release — it forces the Mac to sleep so it cools down.
git clone https://github.com/ericporres/cocaffeinate
cd cocaffeinate
./install.sh # installs to ~/.local/bin, no sudoOptional short alias:
alias cca='cocaffeinate'The command you actually want to commit...to your cranium:
cocaffeinate --lid --while-agentThat arms lid-closed mode, confirms Claude or Codex is up, and parks until both quit (or the battery floor / thermal failsafe trips). Close the lid and walk into the meeting. When the agent finishes and you quit it, the Mac goes back to sleeping normally on its own.
Codex's headless mode (codex exec) and Goal mode can run for hours or days. Wrap the run and the keep-awake lasts exactly as long as the task, then releases:
cocaffeinate --lid -- codex exec "refactor the payments module and open a PR"Or gate on the app/agent staying alive (good for Codex's background computer-use agents and the desktop app):
cocaffeinate --lid --while-codex # awake while Codex runs
cocaffeinate --lid --while-claude # awake while Claude (Desktop or Claude Code) runs
cocaffeinate --lid -- claude # awake exactly for one Claude Code sessionOther shapes:
cocaffeinate # awake until Ctrl-C (lid open / docked)
cocaffeinate --lid # survive a closed lid until Ctrl-C
cocaffeinate --while "Docker" # gate on any process name (pgrep -f)
cocaffeinate --status # current sleep / battery / agent state
cocaffeinate --off # clear a stuck disablesleep flag (recovery)Options: --floor N (battery %), --timeout 90m|2h|5400, --max-temp 92, --keep-display (keep the screen on too).
cocaffeinate.ps1 mirrors the interface with the Windows equivalents — SetThreadExecutionState for the keep-awake layer and the power-plan lid-close action for the lid layer. Run elevated for -Lid:
.\cocaffeinate.ps1 -Lid -WhileAgent
.\cocaffeinate.ps1 -Lid -- codex exec "..."
.\cocaffeinate.ps1 -Status| Job | macOS | Windows |
|---|---|---|
| Keep the system awake (no admin) | caffeinate -ims (display may sleep) |
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED) |
| Survive a closed lid (admin) | pmset -a disablesleep 1 |
power-plan lid-close action → "Do nothing" |
| Detect Claude / Codex | System Events process name + pgrep -x |
Get-Process Claude,Codex |
| Battery (guardrail) | pmset -g batt |
Win32_Battery |
| Thermal (guardrail) | pmset -g therm throttle + powermetrics |
MSAcpi_ThermalZoneTemperature (best-effort) |
| Force sleep on overheat | pmset sleepnow |
Application.SetSuspendState |
| Teardown | trap restores disablesleep 0 |
try/finally restores the saved lid action |
The obvious move is pgrep -f Claude.app/Contents/MacOS/Claude. On real hardware (M1 Max, macOS 26) that returns nothing while the app is plainly running — macOS doesn't expose a GUI app's full argv to pgrep the way Linux does. Both Claude and Codex ship as GUI apps, so both hit this. The reliable check asks System Events for a process by name (Claude, Codex), which matches the desktop apps exactly, and falls back to pgrep -x for the CLI cases (Claude Code's claude, Codex's embedded codex). This was caught by running the script on actual silicon; a sandbox would have shipped it broken.
--lidneedssudoto setdisablesleep. The script always restores it on exit, including on Ctrl-C.- If the script is hard-killed (SIGKILL, crash, forced reboot), the
disablesleepflag can be left set.cocaffeinate --offclears it;--statusshows whether it's set. - The precise temperature reading uses
powermetrics, which needs root and whose output varies by chip and macOS version. The no-sudo throttle signal is the dependable trip; the absolute-temperature layer is best-effort. On Apple Silicon,pmset -g thermonly reports a throttle figure under actual thermal load — which is the only time it matters. - Gating on a desktop app (
--while-claude/--while-codex) keeps the Mac awake while the app is open, not only while it's actively working. For exact-duration precision on a CLI run, wrap the command instead:cocaffeinate --lid -- codex exec "...". - By default cocaffeinate keeps the system awake and lets the display sleep — it saves power and sidesteps panel burn-in (the reason Amphetamine and Apple Silicon both sleep the display on a folded lid). Pass
--keep-display/-KeepDisplayonly if you're watching on an external monitor. - Windows often doesn't expose CPU temperature to user space; where it doesn't, the Windows thermal failsafe can't fire.
Sleep-on-lid-close is a power model built on the assumption that the human is the only thread: when you stop looking, the machine stops working. Agentic work breaks that assumption. The fix isn't a plastic hand holding the lid open — it's the machine staying awake for the agent, only while the agent is working, and pulling its own plug if it starts to overheat.
MIT. See LICENSE.