caffeinate vs an app

caffeinate keeps your Mac awake until you close the lid.
Then it doesn't.

Every Mac ships with caffeinate, a Terminal command that keeps the machine awake. It's free, it's already installed, and for a one-off job it's fine. This page covers the flags, the gotchas, and the point where a menu bar app is the better tool.

The short version

caffeinate -i holds your Mac awake until you press Ctrl-C, but not through a closed lid or a closed terminal, and with nothing in the menu bar to show it's running. Midnight Oil uses the same power assertion and adds the parts caffeinate can't: closed-lid mode, a countdown, triggers, and battery safety.

How caffeinate works

/usr/bin/caffeinate has shipped with every Mac since 2012. It asks the power manager for an assertion, the same mechanism Xcode, Final Cut, and Midnight Oil use, and holds it until the command exits. The man page hasn't changed since it was written, which tells you how simple it is.

The flags

caffeinate            # prevent idle sleep until Ctrl-C
caffeinate -d         # also keep the display on
caffeinate -i         # prevent idle system sleep (the default)
caffeinate -s         # prevent system sleep; only works on AC power
caffeinate -u -t 5    # declare the user active for 5 seconds
caffeinate -t 3600    # for one hour
caffeinate -w 12345   # until process 12345 exits
caffeinate -i make    # for as long as this command runs
caffeinate -dimsu     # everything

Check what's holding the Mac awake with pmset -g assertions. Stop a stray one with killall caffeinate.

Where it falls down

A closed lid beats it

An assertion holds off idle sleep. Closing the lid isn't idle; it's an explicit request, and as one guide puts it, “no assertion overrides it.” The workaround is sudo pmset -a disablesleep 1, which needs an admin password, applies to the whole machine, and stays on until you remember to turn it off. A MacBook still running in a bag with sleep disabled has nowhere to put its heat.

It has no face

Nothing in the menu bar tells you caffeinate is running, or for how long. You find out it wasn't when the SSH session is gone in the morning.

It dies with the terminal

Close the window, quit Terminal, or have it crash, and the assertion goes with it. The community answer is to wrap it in tmux, which works, and is one more thing to remember at 11 PM.

Some flags silently do nothing

-s is a no-op on battery. -t is ignored when you wrap a command. -u expires after five seconds unless you say otherwise. Each of these has a Stack Exchange thread from someone who thought it worked.

No triggers, no schedule

It can't start when you dock, stop when the battery gets low, say “until 7 AM and then let it sleep,” or hold your Mac awake every weekday from 9 to 5. You'd script all of that yourself, cron included.

The overnight agent problem, specifically

People running Claude Code, Codex, and Cursor agents overnight have converged on the same recipe: tmux new-session -d -s agent 'caffeinate -i claude', sometimes wired into Claude Code's hooks so it starts automatically. It works, as long as the lid stays open and you never need to see whether it's still running. There are half a dozen wrapper projects on GitHub whose only job is to make caffeinate less annoying.

Midnight Oil is what that recipe wants to be. Start a session while Terminal is running and it ends when the agent's app quits. Or until 7 AM. Check Stay awake with lid closed and you can shut the laptop. The flame in the menu bar shows time remaining, and normal sleep comes back on its own when the session ends, when the app quits, or if anything crashes.

Midnight Oil vs caffeinate

Midnight Oilcaffeinate
PriceFreeFree, preinstalled
MechanismIOKit power assertionIOKit power assertion
Shows it's running and time leftMenu bar flame and countdownNothing; check pmset
Survives closing the terminalYesNo (unless wrapped in tmux)
Keep awake until a clock timeYesNo (seconds only, via -t)
While an app is runningYes, pick from a listYes, one process, via -w or wrapping
Closed-lid modeYes; sleep restored automaticallyNo; sudo pmset workaround, manual reset
TriggersYesNo
Weekly schedules, like work hoursYesNo (cron plus a script)
End on low battery or unplugYesNo
Works from a scriptYes: midnightoil run, start, and stopYes
InstallHomebrew cask or DMGNone needed

When caffeinate is the right tool

Scripts and CI. If you're already in a shell and the job is caffeinate -i ./build.sh, there's no reason to open an app. It's also the only option on a Mac where you can't install anything.

When an app is

Anything you'd want to see, extend, or forget about: an overnight run, a download, a render, a presentation, or a laptop you're about to close.

Replacing your caffeinate habit

  1. Install Midnight Oil. brew install --cask coreyhaines31/tap/midnightoil
  2. Start the agent in Terminal, Cursor, or wherever it lives.
  3. Click the flame › While App Is Running › Terminal. Or Keep Awake Until › 7:00 AM. Check “Stay awake with lid closed” if you're closing the laptop.
  4. Leave. When the app quits or the time arrives, your Mac goes back to its normal sleep schedule.

Like wrapping commands? Midnight Oil comes with a midnightoil command that works the same way, plus closed-lid mode, battery safety, and a countdown in the menu bar:

midnightoil run --lid-closed -- ./build.sh   # instead of caffeinate -i ./build.sh
midnightoil start --until 7am                # instead of caffeinate -t, minus the math

Keep caffeinate for CI and Macs where you can't install anything. Use Midnight Oil for everything you'd otherwise have to remember.

The same assertion, with a menu bar.

Free. No account, no subscription.

macOS 14 or later · Apple Silicon and Intel · brew install --cask coreyhaines31/tap/midnightoil