Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cocaffeinate

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.

Where this came from

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.

What it does

There are two macOS levers, and then there's what cocaffeinate decides to do with them.

The levers:

  1. caffeinate can block idle, disk, display, and system sleep. No admin. But it does not survive a physical lid close.
  2. pmset disablesleep sets the kernel flag that does survive a closed lid on battery with no external display. Needs sudo. This is the part --lid turns on.

What cocaffeinate decides on top of them:

  • System awake, screen asleep — it pulls caffeinate so 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-display overrides.
  • Agent-gated — with --while-agent it 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.

Install (macOS)

git clone https://github.com/ericporres/cocaffeinate
cd cocaffeinate
./install.sh            # installs to ~/.local/bin, no sudo

Optional short alias:

alias cca='cocaffeinate'

Usage

The command you actually want to commit...to your cranium:

cocaffeinate --lid --while-agent

That 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.

Best pattern for a long Codex run

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 session

Other 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).

Usage (Windows)

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

How it works

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

Why detecting "is the agent running" is not pgrep

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.

Safety and limits

  • --lid needs sudo to set disablesleep. The script always restores it on exit, including on Ctrl-C.
  • If the script is hard-killed (SIGKILL, crash, forced reboot), the disablesleep flag can be left set. cocaffeinate --off clears it; --status shows 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 therm only 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 / -KeepDisplay only 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.

The idea

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.

License

MIT. See LICENSE.

About

Keep your Mac (or PC) awake while Claude or Codex works, lid closed, without cooking it.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages