Skip to content

Repository files navigation

Puer — keeps your Mac awake with the lid closed, then lets it sleep on a delay you choose

MIT licence macOS 13 or later, Apple Silicon

You set Claude Code off on something long. A build, a download, an agent that will be a while yet. You close the lid, and macOS goes to sleep and takes the job with it.

Puer keeps the machine running with the lid shut, then sleeps after a delay you picked in advance — 30 minutes, 2 hours, 8 hours.

The timer is the point. This is a machine that ends up in a bag, so awake-forever is a choice you have to make deliberately, not the default.

One setting

Click the bowl in the menu bar. One flat list, one tick.

   Off — sleep as usual
   15 minutes
   30 minutes
   1 hour
 ✓ 2 hours
   3 hours
   4 hours
   8 hours
   12 hours
   Never sleep
   ─────────────────
   Open Puer Window…
   ─────────────────
   Quit Puer

Picking a delay turns Puer on. Picking Off turns it off. Nothing else — no status line, no caption, no separate switch to disagree with the list. There used to be a "Keep awake" tick box and a delay submenu: two controls over one lid, and they could contradict each other. That is gone.

The glyph carries the state: a solid, steaming tea bowl while Puer is holding the Mac awake, a bare outline while it is off.

Open Puer Window… gives you the same list in a window, plus a status line that appears only when it has something to tell you — the live countdown while the lid is shut (Lid closed — sleeping in 12m 30s), the never-sleep confirmation, or a note that the status could not be read. The rest of the time it says nothing.

Puer also keeps a Dock icon, on purpose. When the menu bar is full macOS has no slot for the status item, and a menu-bar-only app would be unreachable.

Install

macOS 13 or later on Apple Silicon. You will need an admin password, and the Xcode Command Line Tools for swiftc.

git clone https://github.com/startsevdev/puer.git
cd puer
sudo ./install.sh      # the background service
./build-menubar.sh     # compiles the app, renders the icon, sets launch-at-login

install.sh needs sudo: the service changes a system power setting, and macOS only lets root do that. Nothing is downloaded and nothing is pre-built — the app is compiled on your machine from the source in this repo.

If the bowl never appears, /tmp/puer.err is the first place to look. If the Mac sleeps anyway, run pmset -g | grep SleepDisabled — with Puer on it should read 1 within about 15 seconds.

Uninstall

cd puer
sudo ./uninstall.sh

Service, app, control files and log are removed, disablesleep is cleared, and the Mac goes straight back to stock behaviour.

Under the hood

What it does to your Mac. puer-daemon.sh runs as root under launchd (com.puer.daemon.plist) and polls the lid every 15 seconds with ioreg -r -k AppleClamshellState -d 1. Everything it does, it does by toggling one system flag, pmset -a disablesleep — the one mechanism that still holds off lid-close sleep on battery as well as on mains.

State What the daemon does
Puer on, lid open Holds the flag at 1. The Mac will not sleep at all, though the display still dims and locks on its own schedule.
Puer on, lid closed, under your delay Flag stays at 1, and the counter climbs by 15 s a poll.
Puer on, delay reached pmset -a disablesleep 0, then pmset sleepnow.
Puer off Re-asserts 0 whenever it finds the flag set, and nothing else.

Opening the lid resets the counter. Switching Puer off takes effect at the next poll, within 15 seconds — nothing here is instant.

Each poll reads the flag back from pmset -g rather than trusting what it last wrote. So if something else on the system sets disablesleep behind its back, a switched-off Puer puts it back to 0 instead of silently leaving your Mac unable to sleep.

The app. menubar/main.swift (Swift/AppKit) never touches power settings itself. Three files in /Users/Shared carry the whole conversation:

File Meaning
.puer-paused present means Puer is off
.puer-limit the chosen delay in seconds; absent or not a number falls back to 3600
.puer-status written every poll as state;closed;limit;mode, e.g. closed;180;3600;active — the window's countdown is this file, not a guess

The app reads PUER_SHARED from the environment when it is set, which is how the tests point it at a scratch directory.

"Never sleep" is not a separate mode: it is a delay so long it is never reached in a session, about ten years. It is the one choice that never stops on its own. Every other choice holds the Mac awake for exactly as long as you picked — which, at 8 or 12 hours, is still all afternoon in a bag.

Where the install puts things. install.sh copies puer-daemon.sh to /Library/Scripts as root:wheel, mode 755, bootstraps com.puer.daemon.plist into system, and clears any leftover disablesleep. build-menubar.sh compiles the app into ~/Applications/Puer.app, renders icon/AppIcon.icns via icon/make-icon.sh when the sources are newer, and registers ~/Library/LaunchAgents/com.puer.app.plist for launch at login. The three files in /Users/Shared are written at runtime, not by the installer.

Tests.

./tests/test-daemon.sh
./tests/test-menu.sh

Neither needs root and neither touches your real power settings. test-daemon.sh drives a rewritten copy of the daemon against stub pmset and ioreg in a temp directory, so the lid can be closed and time can pass without either actually happening — including the case where something else flips the flag mid-run. test-menu.sh compiles the app and runs it with --dump-menu against a scratch PUER_SHARED, then asserts the menu offers exactly one, correctly ticked choice. Both print PASS/FAIL per case and exit non-zero if anything failed.

Logs. /var/log/puer.log for the daemon, /tmp/puer.err for the app.

Repo layout

Path What it is
puer-daemon.sh, com.puer.daemon.plist the poll loop and its launchd job
menubar/main.swift the status item, the menu and the window
icon/PuerIcon.swift, icon/make-icon.sh, icon/tea*.png the bowl: cream on a Claude-orange squircle for the app icon, template glyphs for the menu bar
icon/PuerHero.swift, icon/make-hero.sh the banners on this page, drawn from the same bowl
install.sh, uninstall.sh, build-menubar.sh setup and removal
tests/test-daemon.sh, tests/test-menu.sh the two test scripts above

Licence

MIT. See LICENSE.

About

Close the lid, let it keep working — a macOS menu bar app that keeps your Mac (and your AI agents) awake with the lid shut, then sleeps on a delay you choose.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages