Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

caf

Keep your Mac awake for as long as a job takes — a small POSIX-sh wrapper around caffeinate with human-readable durations, a pidfile, and an opt-in lid-close override that restores itself when the timer expires.

It's a plain executable with a #!/bin/sh shebang, so the same file behaves identically in sh, bash, zsh, fish, or a non-interactive agent shell — no per-shell function, alias, or plugin.

$ caf on 2 hour
caf: ON (pid 41207) for 2 hour (≈ 7200s) — until 23:31

$ caf status
caf: ON (pid 41207) — until 23:31 (1h58m left)
caf: lid-close normal — closing the lid sleeps the Mac

$ caf off
caf: OFF

Install

Installing with an AI agent? Follow SKILL.md — it carries the canonical, ordered steps. The one detail the snippet below encodes and agents keep missing: caf-dim.swift must land in the same directory as caf, or caf build and --lid screen-dimming can't work.

DIR=/usr/local/bin   # any dir on PATH works: ~/.local/bin, ~/bin, …
curl -fsSL https://raw.githubusercontent.com/savchenko-dev/caf/main/caf           -o "$DIR/caf"
curl -fsSL https://raw.githubusercontent.com/savchenko-dev/caf/main/caf-dim.swift -o "$DIR/caf-dim.swift"
chmod +x "$DIR/caf"

macOS ships everything else it needs — caffeinate, pmset, and /usr/bin/units are all part of the system. (swiftc, from xcode-select --install, is only needed for --lid screen dimming; without it --lid still works, just lit.)

Usage

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 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 install-sudoers one-time setup so --lid needs no password

Durations are parsed by /usr/bin/units, so they need a space — 2 hour, not 2h. Anything unparseable fails loudly instead of silently caffeinating forever:

$ caf on 2h
caf: don't understand duration '2h'
     try:  caf on 2 hour | 15 min | 30 sec | 1.5 hour | hour
     note: glued forms like 2h / 15m aren't supported — add a space

Lid-close mode

caffeinate cannot stop a laptop from sleeping when the lid closes — that takes sudo pmset -a disablesleep 1, which is real machine-wide state that persists across reboots. --lid opts into it, and every exit path puts it back:

  • caf off restores it;
  • a timed caf on --lid 2 hour spawns a detached watcher that restores it 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.

Because the watcher fires long after the sudo timestamp has expired, --lid wants a passwordless grant for exactly those two commands:

caf install-sudoers

writes /etc/sudoers.d/caf-pmset (mode 440, root:wheel):

<you> ALL=(root) NOPASSWD: /usr/bin/pmset -a disablesleep 0, /usr/bin/pmset -a disablesleep 1

Exact-match commands, no wildcards — the worst it grants is turning lid-close sleep on or off. Without the grant --lid still works, but prompts for a password and the auto-revert at expiry fails silently, leaving lid-close sleep disabled until the next caf off.

caf on --lid also warns you about the two ways this bites: a closed lid means no airflow (desk only, never a bag), and running on battery means a flat battery kills every process it was protecting.

Screen blackout

caffeinate -d keeps the display awake, so with disablesleep 1 the panel stays lit behind a closed lid — burning battery to light nothing. --lid therefore also arms a watcher that blacks the screen out while the lid is shut and puts the brightness back when it opens:

$ caf on --lid
caf: ON (pid 41207) + lid-close disabled — no time limit, run 'caf off' to stop
     ✓ screen goes dark while the lid is shut, restored on open

$ caf status
caf: ON (pid 41207) — no time limit
caf: lid-close DISABLED — closing the lid keeps the Mac running
caf: screen blackout armed (pid 41219) — dark while the lid is shut, now 44%
  • The restore target is the last brightness seen while the lid was open, so a fade at close time can't be mistaken for your setting.
  • It only ever drives the panel CGDisplayIsBuiltin() reports, and does nothing when that panel is offline — an external monitor in clamshell mode is never touched.
  • macOS brings the backlight back on some wake events; the watcher holds it down and logs every transition to /tmp/caf.dim.log, which is how you check what happened with the lid shut.
  • caf off restores brightness even if the watcher was killed with -9, using the value parked in /tmp/caf.dimmed.
  • --no-dim opts out and keeps the old lit-screen behaviour.

Brightness has no supported CLI on Apple Silicon, so this rides DisplayServicesGetBrightness / SetBrightness from the private DisplayServices framework via a small Swift helper (caf-dim.swift). It is compiled on demand into ~/.cache/caf/caf-dim and rebuilt whenever the source is newer — caf build does it up front. Without swiftc the blackout is skipped with a warning and --lid still works.

How it works

  • caffeinate -d -i [-t <secs>] is started under nohup, so it survives the invoking shell and the terminal window closing. Its pid goes to /tmp/caf.pid.
  • caf on is idempotent: with caffeinate already running it refuses to change the timer — except caf on --lid, which adds the lid override to the running process without restarting it.
  • A timed run leaves a stale pidfile behind once caffeinate -t exits on its own; status and off detect that with kill -0 and report OFF.

Use as a Claude Code skill

This repo doubles as a Claude Code skill — clone it straight into your skills directory and Claude can drive caf for you ("keep the Mac awake while the deploy runs") or install it on a new machine:

git clone https://github.com/savchenko-dev/caf ~/.claude/skills/caf

SKILL.md carries the model-facing instructions; the script sits next to it.

Troubleshooting

Symptom Fix
caf: can't reach pmset without a password prompt run caf install-sudoers
lid-close sleep stayed disabled caf off, or sudo pmset -a disablesleep 0
caf status says OFF but the Mac stays awake something else holds an assertion — see pmset -g assertions
caf behaves differently in one shell a shell function/alias shadows the executable — check type caf

About

Keep your Mac awake: a shell-agnostic caffeinate wrapper with human durations and an auto-reverting lid-close override. Doubles as a Claude Code skill.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages