Keep a Mac awake for a long-running job — a shell-agnostic `caf` wrapper around `caffeinate` (on/off/status, human durations like "2 hour", optional `--lid` to survive closing the lid via `pmset disablesleep`, auto-reverted when the timer expires, and a screen blackout that darkens the built-in display while the lid is shut and restores the brightness on open). Use to start/stop/inspect the keep-awake state on this Mac from any shell, or to install the whole setup (script + one-time sudoers g...
Scanned 9/6/2026
Install to Claude Code
npx -y skills add savchenko-dev/caf --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of caf?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/savchenko-dev-caf)More formats (shields.io, HTML) on the badges page.
---
name: caf
description: Keep a Mac awake for a long-running job — a shell-agnostic `caf` wrapper around `caffeinate` (on/off/status, human durations like "2 hour", optional `--lid` to survive closing the lid via `pmset disablesleep`, auto-reverted when the timer expires, and a screen blackout that darkens the built-in display while the lid is shut and restores the brightness on open). Use to start/stop/inspect the keep-awake state on this Mac from any shell, or to install the whole setup (script + one-time sudoers grant) on a fresh Mac. Do NOT use for scheduling wakeups, `pmset` power profiles, or Linux/Windows sleep settings.
triggers:
- "keep the mac awake / don't let it sleep while X runs"
- "не давай маку засыпать, идёт выкатка / тесты"
- "caffeinate for 2 hours"
- "caf on / caf off / caf status"
- "keep it running with the lid closed"
- "add another hour / extend the keep-awake / продли caf"
- "is the mac still caffeinated? / turn sleep back on"
- "set up caf on this Mac / install my keep-awake script"
---
# caf — keep the Mac awake from any shell
`caf` is a small POSIX-`sh` script wrapping `caffeinate` with a pidfile, human-readable
durations, and an opt-in lid-close override. It is a plain executable, so it behaves
identically from `sh`, `bash`, `zsh`, `fish`, or a non-interactive agent shell.
Script: `~/.claude/skills/caf/caf` (run it by full path if it isn't on PATH).
## Commands
| Command | Effect |
| --- | --- |
| `caf on` | keep awake indefinitely (closing the lid still sleeps) |
| `caf on 2 hour` | keep awake for 2 hours; `15 min`, `30 sec`, `1.5 hour`, `hour` also work |
| `caf on --lid` | also disable lid-close sleep, indefinitely |
| `caf on --lid 2 hour` | also disable lid-close sleep; auto-restored when the timer expires |
| `caf on --lid --no-dim` | keep the lid override but leave the screen lit |
| `caf extend 1 hour` | add time to a running caf without dropping the lid override |
| `caf off` | kill the caffeinate process, restore lid-close sleep and brightness |
| `caf status` | caffeinate ON/OFF (with until-time + time left for a timed run) + lid-close and screen-blackout state |
| `caf build` | precompile the screen-blackout helper (`caf-dim`) |
| `caf install-sudoers` | one-time setup so `--lid` needs no password (prompts for sudo) |
Durations are parsed by `/usr/bin/units`, so they need a space: `2 hour`, not `2h`.
Unparseable input fails loudly instead of silently caffeinating forever.
## Behaviour worth knowing
- **Background process, not a shell job.** `caffeinate -d -i [-t <secs>]` is started with
`nohup`, so it survives the invoking shell and the terminal window closing. Its pid lives
in `/tmp/caf.pid`.
- **`on` is idempotent.** With caffeinate already running, `caf on …` refuses to change the
timer (`run 'caf off' first`) — except `caf on --lid`, which adds the lid override to the
already-running process without restarting it.
- **`extend` is how you change a running timer.** It starts the replacement `caffeinate`
before killing the old one and never calls `pmset`, so there is no window where a shut
lid could sleep the Mac — unlike the `caf off && caf on --lid …` it replaces. It *adds*
to the remaining time, so it can never shorten a run; on an indefinite run, which has no
deadline to add to, it sets one that far out instead.
- **A timed run leaves a stale pidfile** once `caffeinate -t` exits by itself; `status`/`off`
detect that via `kill -0` and report OFF.
- **Lid override is real system state.** `sudo pmset -a disablesleep 1` disables lid-close
sleep machine-wide, and it persists across reboots until set back to 0. Every path that
sets it also restores it: `caf off`, and for a timed run a detached watcher that fires at
expiry. The watcher only reverts if `/tmp/caf.lid` still holds *its own* pid, so a later
`caf off` or a new `caf on --lid` can't be clobbered by a stale watcher.
- **`caf on --lid` prints warnings** about airflow with the lid closed, and about running on
battery (with the current percentage) — a flat battery kills every process anyway.
- **`--lid` also blacks out the screen.** `caffeinate -d` keeps the display awake, so the panel
would otherwise stay lit behind a shut lid and drain the battery to light nothing. A watcher
(`caf-dim watch`, pid in `/tmp/caf.dim`) polls the lid twice a second, sets the built-in
display to 0 on close, and restores the last brightness seen *while the lid was open*. It
touches only the panel `CGDisplayIsBuiltin()` reports, so an external monitor in clamshell
mode is never dimmed; it re-asserts 0 if macOS brings the backlight back; and it logs every
transition to `/tmp/caf.dim.log`. `caf off` restores brightness even after a `kill -9`, from
the value parked in `/tmp/caf.dimmed`. `--no-dim` opts out.
- **The blackout needs `swiftc`.** Brightness has no supported CLI on Apple Silicon, so
`caf-dim.swift` calls `DisplayServicesGet/SetBrightness` from the private DisplayServices
framework. It compiles on demand into `~/.cache/caf/caf-dim` (rebuilt when the source is
newer; `caf build` does it up front). Without `swiftc` the blackout is skipped with a
warning and `--lid` still works.
- **Retrofitting a running session.** With caffeinate already up *and* lid-close already
disabled, `caf on --lid` no longer just says "already ON" — it arms the blackout on the
existing process without restarting it.
## Using it on this Mac
Just run it. `caf status` first if the user asks whether the Mac is caffeinated; prefer a
bounded duration (`caf on 2 hour`) over indefinite when the job has a known length.
Only reach for `--lid` when the user explicitly wants the lid closed — it changes global
power behaviour, and a Mac running with a closed lid must be on a desk, never in a bag.
Never run `caf install-sudoers` unprompted: it writes `/etc/sudoers.d/caf-pmset` and needs
an interactive password. Ask the user to run it themselves.
## Installing on a fresh Mac (any shell)
1. Copy the script somewhere on PATH and make it executable:
```sh
install -m 755 ~/.claude/skills/caf/caf /usr/local/bin/caf
```
Any PATH dir works (`~/.local/bin`, `~/bin`, `~/dotfiles/bin` + a PATH entry). Because it
is an executable with a `#!/bin/sh` shebang, no per-shell function/alias is needed — the
same file serves `zsh`, `bash`, and `fish` alike.
Copy `caf-dim.swift` alongside it to keep the screen blackout — the script looks next to
itself, then in `~/.claude/skills/caf/`, then at `$CAF_DIM_SRC`. Then `caf build` once.
2. Optional, only needed for `--lid`: the user runs `caf install-sudoers` once. It writes
```text
<user> ALL=(root) NOPASSWD: /usr/bin/pmset -a disablesleep 0, /usr/bin/pmset -a disablesleep 1
```
to `/etc/sudoers.d/caf-pmset` (mode 440, root:wheel). Exact-match commands, no wildcards:
the worst it grants is toggling lid-close sleep. Without it, `--lid` still works but
prompts for a password — and the auto-revert watcher will fail silently at expiry, because
the sudo timestamp is long gone by then, so lid-close sleep stays disabled until `caf off`.
3. `units` (`/usr/bin/units`) and `caffeinate` ship with macOS — nothing else to install.
## Shadowing by a shell function
A shell function or alias named `caf` wins over a PATH executable — notably a fish-native
`caf` in `~/dotfiles/fish/functions/caf.fish`, which this script was ported from. If both
exist, `caf` means different code in fish than in zsh/bash, so check with
`type caf` / `functions caf` before debugging odd behaviour. Either mirror edits into both
or delete the function and let the script serve every shell; the sudoers grant is shared.
## Troubleshooting
- **`caf: don't understand duration '2h'`** — add a space: `2 hour`. `units` won't parse glued
forms.
- **`caf: can't reach pmset without a password prompt`** — the sudoers grant is missing; run
`caf install-sudoers`.
- **Lid-close sleep stayed disabled** — check `pmset -g | grep SleepDisabled`; `caf off`
restores it, or `sudo pmset -a disablesleep 0` directly.
- **`caf status` says OFF but the Mac stays awake** — something else is holding an assertion;
check `pmset -g assertions` (other tools, incl. agent harnesses, run their own `caffeinate`).
- **`screen blackout unavailable`** — no `swiftc` (`xcode-select --install`) or `caf-dim.swift`
isn't next to the script; `caf build` reports which. `--lid` still works, screen stays lit.
- **Screen stayed dark after the lid opened** — `caf off` restores it from `/tmp/caf.dimmed`,
or set it by hand: `~/.cache/caf/caf-dim set 0.5`.
- **Did the blackout actually fire?** You can't watch it happen, so read `/tmp/caf.dim.log` —
it records every close/open transition with the restore value.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!