skip to content

caffeinate — Keep macOS Awake on Demand

Prevent display, idle, system, or user-active sleep for the duration of a command, a fixed time, or a process — without permanently changing pmset.

14 min read 41 snippets deep dive

caffeinate — Keep macOS Awake on Demand#

What it is#

caffeinate is a small Apple-shipped command-line utility that posts a power assertion against the macOS power-management subsystem to prevent some or all forms of sleep for the duration of an invocation. It is the scripted equivalent of nudging the trackpad every minute: cleaner, faster, and tied to a process lifetime so it can never be left running after its parent dies. Reach for caffeinate whenever you need a one-off “don’t sleep right now” promise — a long backup, an overnight build, a recording session, a presentation — without modifying the persistent pmset settings that survive across reboots. If you need a permanent policy (always wake at 06:00, never sleep on AC), use pmset instead.

caffeinate lives in /usr/bin/caffeinate and is part of every macOS install from Mountain Lion (10.8) onward; no Homebrew package or third-party app is required.

Install#

caffeinate is preinstalled on macOS. Verify the binary path and version.

which caffeinate
caffeinate -h 2>&1 | head -5

Output:

/usr/bin/caffeinate
usage: caffeinate [-disu] [-t timeout] [-w pid] [command [arguments]]

There is no Linux or Windows port; the closest analogues are systemd-inhibit on Linux and powercfg /requestsoverride on Windows.

Syntax#

caffeinate accepts zero or more mode flags, an optional timeout, an optional PID to track, and an optional command to run. With no arguments and no command it runs until killed with Ctrl-C; with a command it inherits the command’s lifetime.

caffeinate [-disu] [-t SECONDS] [-w PID] [COMMAND [ARGS...]]

Output: (none — exits 0 on success)

Essential flags#

FlagMeaning
-dPrevent display sleep (screen stays on)
-iPrevent idle sleep (system stays awake even if idle)
-sPrevent system sleep while the machine is on AC power
-uDeclare user activity — wakes display for ~5 s, then exits
-mPrevent disk sleep
-t SECONDSRun the assertion for at most this many seconds, then exit
-w PIDHold the assertion until the given process exits
(no flag)Default behaviour ≈ -d — display assertion only

The mode flags are additivecaffeinate -dis posts three assertions at once.

The four assertion types#

macOS exposes a small set of named power assertions. caffeinate is a thin wrapper that maps each command-line flag to one of these assertions; they are the same assertions you see in pmset -g assertions.

FlagUnderlying assertionWhat it prevents
-dPreventUserIdleDisplaySleepDisplay dimming / sleeping
-iPreventUserIdleSystemSleepSystem sleep when idle (display may still sleep)
-sPreventSystemSleepSystem sleep on AC; ignored on battery
-uUserIsActiveBriefly wakes display (≈5 s) — does not hold awake

Inspect the current set of assertions on a running system.

pmset -g assertions

Output:

2026-05-25 09:14:02 -0700
Assertion status system-wide:
   BackgroundTask                 0
   ApplePushServiceTask           0
   UserIsActive                   0
   PreventUserIdleDisplaySleep    1
   PreventSystemSleep             0
   PreventUserIdleSystemSleep     1
   ExternalMedia                  0
   PreventDiskIdle                0

Listed by owning process:
   pid 41203(caffeinate): [0x0000000000018b41] 00:00:42 PreventUserIdleSystemSleep named: "caffeinate" 
   pid 41203(caffeinate): [0x0000000000018b42] 00:00:42 PreventUserIdleDisplaySleep named: "caffeinate"

The 64-bit hex blob is the assertion ID; the duration is HH:MM:SS; the named string shows the holder.

Running until Ctrl-C#

The simplest invocation: no command, no timeout. Posts the default display assertion and blocks until you press Ctrl-C.

caffeinate

Output: (none — blocks the terminal; the display will not sleep until you interrupt)

caffeinate -di       # also prevent idle system sleep
caffeinate -dim      # plus prevent disk idle

Output: (none — blocks until interrupted)

Use this when you’re stepping away from the machine for a moment but want to come back to a still-active screen, or when a foreground task in another tab needs the system kept up.

Running for a fixed time (-t)#

-t SECONDS is the cleanest pattern for “keep this machine awake for exactly N seconds, then let it sleep again”. The assertion is released the instant the timer fires — no Ctrl-C needed.

caffeinate -i -t 3600          # 1 hour of "no system sleep"
caffeinate -dis -t 1800        # 30 min: no display, no idle, no system sleep
caffeinate -di -t $((8*3600))  # 8 hours overnight

Output: (none — exits 0 once the timer elapses)

A common shell idiom for awake-for-N-hours.

hours=4
caffeinate -di -t $((hours*3600))
echo "Caffeinate window closed at $(date)"

Output:

Caffeinate window closed at Sun May 25 13:14:02 PDT 2026

Wrapping a command#

The most useful mode: pass a command after the flags and caffeinate will run that command, hold the assertion for exactly its lifetime, and exit with the command’s exit code. This is automatic, safe, and impossible to leak — when the wrapped command dies, the assertion releases.

caffeinate -i make build
caffeinate -dis ./long-test.sh
caffeinate -i rsync -aH /Users/alice/src/ /Volumes/Backup/src/
caffeinate -dis ffmpeg -i in.mov -c:v libx265 -crf 22 out.mp4

Output: (whatever the wrapped command emits — caffeinate adds nothing of its own)

Quote arguments carefully — everything after the first non-option token is passed to the inner command.

# Wrong — `2` is interpreted as an extra argument to `caffeinate`, not to `sleep`
caffeinate -i sleep 2

# Right — works because flag parsing stops at `sleep`
caffeinate -i sleep 2

# When in doubt, separate with --
caffeinate -i -- sleep 2

Output: (none — exits 0 after 2 seconds)

Both forms above happen to work, but the -- separator is safer if your inner command starts with a dash.

Attaching to an existing PID (-w)#

-w PID holds the assertion until the named process exits, then releases. This is the right pattern when the workload was started by something else — a GUI app, a launchd job, another shell session — and you don’t want to restart it under caffeinate.

# Find the PID of a running Final Cut export
pgrep -f "Final Cut Pro" | head -1

# Keep the system awake until that PID dies
caffeinate -dis -w 7821

Output: (none — blocks until PID 7821 exits, then exits 0)

A real-world combo: start the long task in the background, capture its PID, then attach.

./overnight-render.sh > render.log 2>&1 &
render_pid=$!
caffeinate -i -w "$render_pid"
echo "render PID $render_pid finished with status $?"

Output:

render PID 7821 finished with status 0

Multiple -w flags can be passed; caffeinate exits only when all of the tracked PIDs have exited.

caffeinate -i -w 7821 -w 7842 -w 7901

Output: (none — exits 0 when the last of those three PIDs ends)

Declaring user activity (-u)#

-u is not a long-hold flag; it tells the OS “the user just did something” which wakes the display for roughly five seconds and then exits. Use it to nudge the screen on from a script (status notification, alarm) without holding any persistent assertion.

caffeinate -u -t 5         # wake the display for 5 seconds, then exit

Output: (none — display turns on; caffeinate exits after 5s)

-u has no effect on a desktop without an attached display, and on a laptop with the lid closed the wake is suppressed.

Display sleep vs system sleep vs idle sleep#

The flags overlap in confusing ways. The mental model: macOS has three sleep states the user can hit, plus one tier above that for “is the user even here”.

FlagKeeps display on?Keeps CPU running?Keeps disk spinning?On AC only?
-dyesno — system can still idle-sleepnono
-ino (display can dim/sleep)yesnono
-snoyesnoyes
-mnonoyesno
-d -iyesyesnono
-d -i -myesyesyesno
-d -i -syesyesnoyes

Choose by use case:

  • Watching a long video / kiosk display-d
  • Headless build, server task, scp/rsync-i
  • Recording or live transcoding that must not pause-i -s
  • Backup writing many files to a slow USB drive-i -m

Laptop lid behavior#

Closing a MacBook lid on AC power normally triggers clamshell mode (sleep if no external display attached). caffeinate cannot fully override this — even with -dis, closing the lid with no external display will sleep the machine. Apple deliberately gated this in the kernel so a closed laptop in a bag does not overheat.

Workarounds, ordered from least to most invasive.

  1. Plug in an external display, keyboard, or mouse — clamshell with peripherals stays awake automatically.
  2. Use pmset -b -c -u sleep 0 and pmset -a disksleep 0 to disable sleep persistently (then caffeinate -i is unneeded — see pmset).
  3. Install a kernel-extension-free tool like Amphetamine (App Store) which works around the clamshell restriction via assertions on macOS where Apple still allows it.
  4. Reset via sudo pmset -a disablesleep 1 (System Integrity Protection must be off on older macOS).

The clean rule: caffeinate works fine until you close the lid; if you need lid-closed-awake, you need external peripherals or Amphetamine.

Battery vs AC behavior#

caffeinate -s is a no-op while the machine is on battery: by design, macOS will not honour PreventSystemSleep to protect battery life. The other three flags (-d, -i, -u) work on both AC and battery.

# On battery this is equivalent to caffeinate -di (the -s is silently ignored)
caffeinate -dis -t 3600

Output: (none — runs for an hour; on battery the -s half of the assertion never fires)

If you genuinely need “stay awake while unplugged”, caffeinate -di is the maximum you can ask of macOS without changing persistent settings via pmset -b sleep 0.

Logging and verifying assertions#

Combine with pmset -g assertions and the log stream to verify your invocation is doing what you expect.

caffeinate -dis -t 60 &
sleep 1
pmset -g assertions | head -20

Output:

[1] 71204
2026-05-25 09:30:18 -0700
Assertion status system-wide:
   BackgroundTask                 0
   ApplePushServiceTask           0
   UserIsActive                   0
   PreventUserIdleDisplaySleep    1
   PreventSystemSleep             1
   PreventUserIdleSystemSleep     1
   ExternalMedia                  0
   PreventDiskIdle                0

To see assertion lifecycle events live, tail the unified log.

log stream --predicate 'subsystem == "com.apple.iokit.power"' --info --debug \
    --style compact | grep -i assertion

Output:

2026-05-25 09:30:19 powerd: PMAssertion: pid=71204 caffeinate: created PreventUserIdleSystemSleep
2026-05-25 09:31:19 powerd: PMAssertion: pid=71204 caffeinate: released

Verbose-style alternative — pmset assertion CLI#

pmset -g assertionslog provides a one-shot, second-by-second log suitable for piping into a file when you need a forensic record of who held what.

sudo pmset -g assertionslog | head -30

Output:

2026-05-25 09:31:00 +/- PreventUserIdleSystemSleep   pid 71204 caffeinate
2026-05-25 09:32:01 +/- PreventUserIdleSystemSleep   pid 71204 caffeinate (released)

This is the right tool when investigating “why didn’t my Mac sleep last night?” — see the pmset cheatsheet for the full assertion / sleep-log walkthrough.

Common pitfalls#

  1. Default behaviour is display-only. caffeinate alone (no flags) keeps the display on but does not prevent system sleep on idle. Add -i if the task is CPU-bound and the screen can dim. The most common “it slept anyway” report is this missing flag.
  2. -s is silently ignored on battery. Don’t rely on caffeinate -s for an unplugged laptop; use -i instead and accept that AC-only system sleep cannot be deferred from userland.
  3. Closing the lid sleeps the machine regardless. No caffeinate flag prevents clamshell-without-peripherals sleep. Plug in external input or display, or change pmset policy permanently.
  4. Forgetting to wrap with -- for commands that start with a dash. caffeinate -i --some-tool interprets --some-tool as a flag to caffeinate. Use caffeinate -i -- --some-tool to disambiguate.
  5. Background caffeinate & without a wait. When wrapped in a script that exits, the backgrounded caffeinate is reparented to launchd and keeps running. Always wait for it, or use -t SECONDS, or use -w $$ to tie its lifetime to the parent script’s PID.
  6. Holding too many assertions for too long. Each minute of -i on battery costs real charge — caffeinate itself is free, but the workload it protects burns through battery. Pair with -t to bound the cost.
  7. Expecting -u to hold the screen on. -u simulates user activity for ~5 s then exits. It is not a “keep on” flag; use -d for that.
  8. Running inside tmux/screen and detaching. The assertion persists as long as the caffeinate process is alive, but if you kill the inner shell from another terminal the assertion is released. Verify with pmset -g assertions.
  9. macOS Power Nap can still wake the machine. Even with caffeinate -s running, Power Nap may schedule periodic wakes for Time Machine, Mail, and iCloud sync. Disable with pmset -a powernap 0 if a perfectly quiet machine is required.
  10. CPU thermal throttling overrides everything. If the chassis hits its thermal envelope during a long render, macOS will throttle and may doze briefly to recover. caffeinate cannot override hardware-level thermal management.

Real-world recipes#

Overnight rsync to an external drive#

A common use case: nightly mirror of ~/Code to an attached USB-C drive. You want the machine awake, disks spinning, but the screen can sleep.

caffeinate -i -m -t $((10*3600)) \
    rsync -aH --info=progress2 \
    /Users/alice/Code/ /Volumes/Backup/Code/

Output:

        148,234,591,002  84%   76.32MB/s    0:08:11 (xfr#9412, ir-chk=183/124003)

If the rsync finishes early the timer is irrelevant — caffeinate exits with rsync’s status the moment rsync returns.

Long ffmpeg encode with the screen off#

Save battery and prevent screen burn-in while a multi-hour h.265 encode runs.

caffeinate -i ffmpeg -hwaccel videotoolbox -i in.mov \
    -c:v hevc_videotoolbox -b:v 8M out.mp4

Output:

frame=  4612 fps= 38 q=-0.0 size=   14336kB time=00:01:17.12 bitrate=1523.4kbits/s

Attach to a Time Machine backup PID#

Find the running backupd and prevent system sleep until it finishes.

pid=$(pgrep -x backupd)
[ -n "$pid" ] && caffeinate -i -w "$pid" && echo "Time Machine backup complete."

Output:

Time Machine backup complete.

See the tmutil cheatsheet for the full backup-orchestration story.

Wake-on-status-change script#

Wake the display to flash a notification when a build fails.

make build || { caffeinate -u -t 5; \
                osascript -e 'display notification "Build failed!" with title "make"'; }

Output: (display lights up for ~5s and a notification banner appears)

Run-until-this-shell-exits guard#

If you want every command in an interactive shell session to keep the machine awake, drop this into ~/.zprofile.

# Keep system awake while this login shell exists
caffeinate -i -w $$ &
disown

Output: (none — every new login shell gets paired with a caffeinate -i that dies when the shell ends)

Presentation mode#

For demos and presentations: no sleep, no display dim, no Power Nap, for two hours.

caffeinate -dis -t $((2*3600)) &
echo "Presentation mode active for 2 hours (caffeinate PID $!)."

Output:

Presentation mode active for 2 hours (caffeinate PID 71455).

To cancel early, kill 71455.

Race against the system sleep timer#

Useful in pmset/caffeinate troubleshooting — schedule a wake, then caffeinate to deliberately not sleep before that wake to confirm the wake fires.

sudo pmset schedule wake "$(date -v+10M '+%m/%d/%y %H:%M:%S')"
caffeinate -di -t 600
pmset -g sched

Output:

Repeating power events:
  wake at 05/25/2026 14:14:00

Scheduled power events:
  [0]  wake at 05/25/2026 14:14:00 by 'com.apple.alarm.user'

Bound a Docker build#

docker build of a large image set can run 30+ minutes; bound the system-awake window to twice that.

caffeinate -i -t 3600 -- docker compose build --pull

Output:

[+] Building 1432.7s (78/78) FINISHED

Sanity-check from another terminal#

Confirm a long-running caffeinate is actually still posting its assertions.

ps -o pid,command -p "$(pgrep -x caffeinate | head -1)"
pmset -g assertions | grep caffeinate

Output:

  PID COMMAND
71204 caffeinate -dis -t 7200
   pid 71204(caffeinate): [0x0000000000018b41] 00:42:11 PreventUserIdleSystemSleep named: "caffeinate"

Conditional caffeinate based on power source#

Only post the assertion when on AC — let battery sessions sleep normally.

if pmset -g batt | grep -q "AC Power"; then
    caffeinate -i -t 3600 ./long-task.sh
else
    ./long-task.sh
fi

Output: (depends on power state — runs the task either way; assertion held only on AC)

Sources#

References consulted while writing this article. Links open in a new tab.

  • pmset — persistent power policy (sleep timers, schedules, hibernate mode). Use when you need the setting to outlive the current invocation.
  • tmutil — Time Machine backup orchestration; commonly wrapped in caffeinate -i -w $(pgrep -x backupd).
  • macos-cli — broader macOS terminal reference; contains the original short note on caffeinate that this article expands.
  • pmset -g assertions — read the live assertion table to see whether (and which) caffeinate calls are currently active.