Pakkit.net
← Back to blog

Engineering Practice

`caffeinate` Is a Small Tool With a Clear Lifecycle

Use macOS's caffeinate in time-bounded or process-bounded modes to keep a laptop awake for a task and ensure it always stops when that task finishes.

  • macOS
  • Command Line
  • Operational Safety
  • Runbooks

The best tiny command-line tools do one thing, are easy to scope to another process, and stop automatically instead of becoming permanent configuration. caffeinate on macOS follows that pattern: it prevents sleep for a bounded intent (a duration or a target PID) and hands you a small, auditable blast radius instead of a global policy change.

caffeinate Is a Small Tool With a Clear LifecycleDiagram for caffeinate Is a Small Tool With a Clear Lifecycle, mapping three design pressures to three review checkpointsFIELD MAPcaffeinate Is a Small Tool With a Clear LifecycleDESIGN PRESSURESREVIEW CHECKPOINTS• time-bounded and process-bounded modes• why not to disable sleep globally• examples for downloads, presentations…• Prefer bounded assertions to global p…• Two explicit modes: time-bounded and…• Examples for common casesTURN ASSUMPTIONS INTO EVIDENCE
A compact map of the article’s design pressures and review checkpoints

Prefer bounded assertions to global policy

Disabling sleep at the OS or power-profile level is a hairball: it changes global defaults, requires privileges, and often outlives the task that needed it. That increases the blast radius (battery drain, thermal stress, lost automatic sleep on shared desks). A tiny tool should invert that risk by scoping intent and reverting automatically. Use caffeinate instead of editing pmset or energy preferences unless you mean to change behavior for all time and all users.

Two explicit modes: time-bounded and process-bounded

  • Time-bounded: caffeinate -t <seconds> asserts wakefulness for a fixed interval. Use this for predictable tasks: a known-length download, a scheduled long run, or a timed presentation rehearsal. Example: caffeinate -t 3600 keeps the machine awake for one hour.
  • Process-bounded: caffeinate -w <pid> waits while a given process ID runs and holds the assertion until it exits. This is the safer default for long, variable work: your task controls lifecycle, not an external timer. Example: start your job in one shell and wrap it: caffeinate -w $(pgrep -f my-download) or start under a shell that reports its own PID.

Tradeoffs: time-bounded is simple and auditable but can overrun or under-protect (if task runs longer than the timer). Process-bounded is precise but requires that the process you point at is the right owner of the task and that PID is stable.

Examples for common cases

  • Downloads: Start the download process, then caffeinate -w <pid> so sleep stops automatically when the downloader exits. If your downloader spawns child processes, target the parent process that controls completion.

  • Presentations: Use caffeinate -t <seconds> with a margin: caffeinate -t $((90 * 60)) for a 90-minute slot. Prefer a short margin and an escape route (kill the assertion) over a huge global timeout.

  • Long tasks (compiles, builds, syncs): Start the job under your monitoring shell or a small wrapper that writes a PID file; then point caffeinate at that PID. For batch tooling run by automation systems, prefer the automation process’s PID or a supervisor so the assertion dies with the job.

Failure modes and costs: incorrect PID selection leaves the machine awake indefinitely; long timeouts waste battery and can throttle thermal headroom. If the task forks and detaches, -w can lose track—wrap the task or use a supervisor that doesn’t double-fork.

How to confirm and how to stop it

Confirmation steps:

  • Check the process table: pgrep -a caffeinate or ps aux | grep caffeinate.
  • Inspect system assertions: pmset -g assertions shows who is preventing sleep and why; caffeinate appears as an assertion with your user and reason.
  • Verify expected behavior: close the lid or trigger a short sleep dry-run in a controlled environment (presentation room) to ensure the assertion blocks sleep as intended.

Stopping caffeinate:

  • If caffeinate runs foreground in a shell, stop it with Ctrl-C.
  • If it runs backgrounded, pkill caffeinate or kill <pid> removes the assertion.
  • For process-bounded mode, stopping the target process causes caffeinate to exit and the system to resume normal sleep policy.

Acceptance criteria for a successful run:

  • The device remains awake for the task window and returns to normal sleep behavior afterward.
  • No global power-settings changed; only transient assertions were added.
  • Battery and thermal metrics stayed within acceptable bounds during the run (if on battery, prefer short windows or an AC connection).

Checklist: run caffeinate safely

  • Decide: Is this a time-bounded or process-bounded need? (Prefer process-bounded.)
  • Prepare: Identify the PID or the expected duration; reserve a small margin.
  • Start: Use caffeinate -w <pid> or caffeinate -t <seconds>.
  • Verify: pmset -g assertions and pgrep -a caffeinate show the assertion.
  • Observe: monitor battery and temperature if on battery or in sensitive environments.
  • End: Let the process exit or kill caffeinate; confirm assertions cleared with pmset -g assertions.

Use this sequence as a preflight in a runbook when scheduling presentations or long unattended runs.

Design notes, tradeoffs, and where this advice is wrong

  • Least privilege: caffeinate does not require privileged changes; it runs as the invoking user and its assertion is scoped. That matches the principle of smallest necessary change.
  • Observability: Put the assertion intent in logs or a small note file (write a one-line record when you start caffeinate). That makes audits and postmortems straightforward: who requested extended wakefulness and why.
  • Failure modes: the common slip is pointing caffeinate at the wrong PID (a short-lived wrapper), which causes early termination of the assertion. Another is leaving a long -t value on a laptop on battery overnight.
  • When this advice is wrong: if an organization needs uniform power policy across a fleet or wants to disable sleep to support system-level services, modify the global policy via configuration management and treat it as a controlled change with rollback, not a local caffeinate invocation.

Takeaway

Tiny tools earn their keep by limiting scope and duration. Use caffeinate in process-bounded mode whenever possible, fall back to a short time-bounded mode with monitoring when needed, and always verify assertions with pmset -g assertions. Keep a short log entry alongside the command so you can answer who asked the machine to stay awake and why. If you need behavior that must outlive a user session or apply fleet-wide, treat it as a policy change, not a caffeinate invocation. /contact