cheat sheet

caffeinate

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

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.

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

Output:

text
/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.

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

bash
pmset -g assertions

Output:

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

bash
caffeinate

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

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

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

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

Output:

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

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

bash
# 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.

bash
# 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.

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

Output:

text
render PID 7821 finished with status 0

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

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

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

bash
# 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.

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

Output:

text
[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.

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

Output:

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

bash
sudo pmset -g assertionslog | head -30

Output:

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

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

Output:

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

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

Output:

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

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

Output:

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

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

bash
# 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.

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

Output:

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

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

Output:

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

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

Output:

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

Sanity-check from another terminal

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

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

Output:

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

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

  • Apple Developer — caffeinate(1) man page — Authoritative flag list used while writing the options reference.
  • SS64 — caffeinate — Cross-version notes.
  • 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.