Keeping your Mac awake
A Guaranate session holds a macOS power assertion for as long as it runs, and releases it when it ends. Everything else — the duration syntax, the assertion mode, the live frame — is about deciding how long and how much sleep to inhibit.
Timed sessions
Section titled “Timed sessions”Pass a duration and Guaranate stays awake for exactly that long, then exits 0:
guaranate 30mguaranate 2hguaranate 1h30mguaranate 90sguaranate 1d2hguaranate 3600 # a bare integer is a number of secondsDuration syntax
Section titled “Duration syntax”| Unit | Meaning | Example |
|---|---|---|
s |
seconds | 90s |
m |
minutes | 30m |
h |
hours | 2h |
d |
days | 1d |
Components combine in descending order — 1h30m, 1d2h — and a bare integer is
read as seconds, for caffeinate-style muscle memory.
Two forms are rejected rather than guessed at:
- A trailing number with no unit (
1h30) is ambiguous, and is an error instead of silently meaning1h30mor1h30s. - A zero or negative duration (
0,0m) is an error — an assertion that expires immediately is never what you meant.
Invalid input fails before any assertion is acquired, so a typo can never leave your Mac awake:
$ guaranate 1h30Error: Invalid duration: '1h30'. Use forms like 30m, 2h, 1h30m, 90s, or a plain number of seconds.Indefinite sessions
Section titled “Indefinite sessions”Omit the duration to stay awake until you stop it:
guaranateThe live frame swaps the progress bar for a spinner (⠋ Awake — until interrupted). Press q or Ctrl+C to end it.
Ending a session
Section titled “Ending a session”| How it ends | Exit code |
|---|---|
| The duration elapses | 0 |
q on a TTY |
130 |
Ctrl+C (SIGINT) |
130 |
SIGTERM (e.g. kill) |
130 |
Every one of those paths releases the assertion first. Nothing is left behind for you to clean up, which is the guarantee the project’s end-to-end smoke test exists to defend.
Assertion modes
Section titled “Assertion modes”The default prevents user-idle system sleep while still letting the display sleep — the right mode for builds, downloads, and unattended compute.
guaranate 2h # prevent idle system sleep (display may sleep)guaranate 2h --display # also keep the display awakeguaranate 2h --system # prevent all system sleep| Flag | IOKit assertion | Display |
|---|---|---|
| (default) | PreventUserIdleSystemSleep |
may sleep |
-d, --display |
PreventUserIdleDisplaySleep |
kept awake |
-s, --system |
PreventSystemSleep |
may sleep |
--display and --system are mutually exclusive; asking for both is a
validation error rather than a silent precedence rule.
Labelling a session
Section titled “Labelling a session”--reason sets the text macOS records on the assertion, which is what you (or a
teammate) will see in pmset -g assertions:
guaranate 3h --reason "nightly dataset export"The default is Guaranate timed session. Give long sessions a real reason — it
is the only thing that explains why a machine is awake an hour later.
The live frame
Section titled “The live frame”On a color terminal, a running session renders a gradient progress bar, a dot-leader metrics table, and a centered header, all sized to the terminal width:
🌿 Guaranate ▏██████████████████▎░░░░░░░░░▕ 65% Elapsed · · · · · · · 01:18:00 Remaining · · · · · · · 00:42:00 Ends · · · · · · · 23:12:07 Assertion · · · · · System sleep Display · · · · · · May sleep Press Ctrl+C or q to stop
The bar fills green and warms towards berry red as the deadline approaches, the
assertion rows are color-coded (amber when --display keeps the screen on), and
the cursor stays hidden until the frame is gone. When the session completes, the
frame is replaced by a summary card:
🌿 Guaranate ▏████████████████████████████▕ ✓ Stayed awake · · · · · · · · · 2h Assertion · · · · · System sleep Sleep-prevention assertion released
Both frames are captures of the real binary — text, not screenshots — written
by npm run gen:frames. Only the clock values are dressed: the capture runs
for seconds, and the figures above are rewritten to a two-hour session so the
bar, the elapsed time, and the remaining time tell one story.
Terminals that can’t do that
Section titled “Terminals that can’t do that”Color and Unicode degrade independently, so the frame stays readable everywhere:
NO_COLORdrops color but keeps the Unicode bar.- A non-UTF-8 locale falls back to a plain ASCII bar (
[####----]) and keeps color;TERM=dumb(or noTERM) drops color as well.
Cursor hiding and frame redraws are the one thing tied to the terminal rather than to color: those escape sequences are written whenever stdout is a TTY.
Scripts, pipes, and CI
Section titled “Scripts, pipes, and CI”When stdout is not a TTY, the frame collapses to one start line and a two-line completion summary — no per-second redraw churn in your log file:
guaranate 2h --reason "release build" >> keepawake.log 2>&1 &Keyboard controls are inactive without a TTY; signals still work, so kill on
the process ends the session cleanly.
