Skip to content

E0min/ClamshellKeeper

Repository files navigation

ClamshellKeeper

English | 한국어

macOS menu bar app for people who want to start a long Codex or Claude Code task, close their MacBook, and let the work continue in clamshell mode. It keeps the Mac awake, defaults to a 3h session, and can turn itself off after Codex or Claude Code CLI work appears to finish. It does not run on Windows.

Close the lid. Keep the work alive.

Start a long Codex or Claude Code task, shut your MacBook, and walk away. ClamshellKeeper keeps the work running, then gets out of the way when the session ends.

Get started · See the safety model · 한국어

ClamshellKeeper app icon

Source-build-only preview. No public .app.zip is provided until the app is Developer ID signed, notarized, stapled, checksumed, and Gatekeeper-tested.

Why This Exists

Sometimes you hand a long task to Codex or Claude Code, step away, and want to close the laptop. If the MacBook sleeps, terminal work can stop. If you leave sleep disabled indefinitely, battery and heat become the next problem.

ClamshellKeeper puts clamshell keep-awake in the menu bar while keeping the default behavior bounded and reversible.

The 10-second demo

  1. Start a long-running Codex or Claude Code task.
  2. Turn ClamshellKeeper on.
  3. Close the MacBook lid.
  4. Come back to a finished task; the timer, AI detection, battery safety, and crash watchdog handle the cleanup.

What's New

  • Turning keep-awake on starts a 3h timer by default.
  • After a Codex or Claude Code CLI process has been seen, keep-awake turns off if those AI processes are gone for 5 minutes.
  • Battery safety turns keep-awake off at 20% while on battery power.
  • While keep-awake is on, the app asks macOS to sleep the display again after about 1 minute without keyboard, mouse, or trackpad input, so the screen can turn off while work continues.
  • The menu bar status shows the scheduled timer-based off time.
  • The app distinguishes sessions it turned on from an already-enabled external SleepDisabled state.
  • Every managed session is journaled before SleepDisabled changes. A separate unprivileged watchdog owns the guarded On transition and turns it Off if the app exits, hangs, or misses its deadline.
  • Limited Power Access allows only pmset -a disablesleep 1 and pmset -a disablesleep 0; managed sessions do not start unless the exact noninteractive rule is ready.
  • The recovery command can be copied from the menu.

What It Does

ClamshellKeeper toggles only these system power commands:

/usr/bin/pmset -a disablesleep 1
/usr/bin/pmset -a disablesleep 0

Admin rights are needed because pmset -a disablesleep changes system-wide macOS power settings. Limited Power Access grants only those two exact commands, not broad passwordless sudo. It is required so automatic safety paths never wait for an administrator prompt while you are away. ClamshellKeeper does not install a persistent privileged daemon.

Platform Support

  • macOS only.
  • Windows and Linux are not supported.
  • The app assumes a MacBook clamshell workflow and macOS pmset power settings.

Build From Source

Requirements:

  • macOS 13 or newer
  • Swift 5.9 or newer
  • Xcode Command Line Tools or Xcode
git clone https://github.com/E0min/ClamshellKeeper.git
cd ClamshellKeeper
swift test
./Scripts/build-app.sh

The app bundle is created at:

build/ClamshellKeeper.app

Install it locally:

ditto build/ClamshellKeeper.app "$HOME/Applications/ClamshellKeeper.app"
open "$HOME/Applications/ClamshellKeeper.app"

If an older copy is already running, quit it from the menu bar and open it again.

Enable Limited Power Access

The first managed session offers to install Limited Power Access. You can also choose Install Limited Power Access... from the app menu, or run:

sudo ./Scripts/install-sudoers.sh

Verify the complete rule and its NOPASSWD scope:

sudo -n -l

Check the current system state:

pmset -g | grep SleepDisabled

Undo Everything

Turn clamshell keep-awake off:

sudo /usr/bin/pmset -a disablesleep 0

Remove the limited sudoers rule:

sudo rm -f /private/etc/sudoers.d/clamshellkeeper

Remove the app:

rm -rf "$HOME/Applications/ClamshellKeeper.app"

After confirming SleepDisabled is 0, stale local recovery state can be removed with:

rm -f "$HOME/Library/Application Support/ClamshellKeeper/managed-session.json"

Safety Defaults

  • Turning keep-awake on starts with a 3h timer by default.
  • Timers are available for 1h, 2h, 3h, 4h, or Until Off.
  • AI Auto-Off is on by default. After ClamshellKeeper sees a Codex or Claude Code CLI process, it turns keep-awake off if those AI processes are gone for 5 minutes.
  • AI Auto-Off scans only the current user's process list and excludes desktop-app internals. It is still process-based: if Codex or Claude Code stays open at an interactive prompt, ClamshellKeeper treats it as running.
  • Sleep Display While On is on by default. While keep-awake is on, the app asks macOS to sleep the display after about 1 minute without keyboard, mouse, or trackpad input. A failed request is ignored; the app never forces display brightness to zero.
  • Battery safety is on by default.
  • If the Mac is on battery and reaches 20%, ClamshellKeeper turns keep-awake off.
  • Unknown power status ends a session when Battery Safety is enabled; serious thermal pressure always ends it.
  • Timer, battery safety, and AI Auto-Off preferences are saved between launches.
  • A private 0600 lease records session ownership, process-start identities, guarded command-group identity, and phase transitions before activation and, for bounded timers, the absolute deadline. The watchdog performs On only after confirming the baseline is Off and journaling a suspended process group, then enforces parent exit, heartbeat expiry, activation/release timeouts, and any configured deadline.
  • Normal Quit waits for confirmed Off and refuses to silently abandon an app-owned session.
  • Recovery command if anything looks wrong:
sudo /usr/bin/pmset -a disablesleep 0

Transparency

Relevant implementation paths:

Limits

  • The app does not directly control Wi-Fi or network policy.
  • It does not run on Windows.
  • Sleep Display While On is a display-sleep request. Keyboard, mouse, or trackpad input can wake the display again, and the app requests display sleep again on the next idle cycle.
  • AI Auto-Off is process-based. If an AI CLI remains open at a prompt, the app cannot know that the actual task is finished.
  • If another app or a manual command enabled SleepDisabled, ClamshellKeeper shows it as an external session and does not apply automatic policies.
  • The user-space watchdog protects app crashes, hangs, and missed deadlines while the login session is alive. It cannot survive logout or reboot; a stale lease is recovered the next time ClamshellKeeper launches. Launch at Login shortens that recovery window.

How It Compares

This table is intentionally narrow. It covers clamshell keep-awake transparency only.

Why ClamshellKeeper instead of caffeinate?

caffeinate is excellent for a quick, one-off sleep-prevention command. ClamshellKeeper is for a different job: managing a long-running MacBook clamshell session around Codex or Claude Code.

ClamshellKeeper adds the session layer that a raw CLI assertion does not provide:

  • A bounded default timer instead of an easy-to-forget background command
  • AI-process auto-off after work appears to finish
  • Battery and thermal safety
  • A menu bar state, scheduled off time, and recovery command
  • A durable lease and watchdog that can recover after app hangs or crashes
  • Direct disablesleep control for the closed-lid workflow, with an exact two-command sudoers scope

The tradeoff is intentional: ClamshellKeeper needs macOS, a one-time Limited Power Access setup, and a source-build-only workflow for now. Use caffeinate when you only need a temporary assertion; use ClamshellKeeper when the session needs to manage itself after you close the lid.

Option Focus Shows exact system change Reversible docs Notes
ClamshellKeeper Clamshell keep-awake menu bar toggle Yes, pmset -a disablesleep 1/0 Yes Source-build-only until signed release is ready
Amphetamine General macOS awake sessions Not the project focus App-specific Mature app, broader feature set
KeepingYouAwake caffeinate style awake sessions Partly App-specific Good for idle sleep, not the same as disablesleep
Lungo Simple menu bar awake utility Not the project focus App-specific Clean general-purpose awake utility
caffeinate CLI idle sleep assertions Yes Manual Does not directly configure disablesleep
Manual pmset Raw system command Yes Manual Powerful, but easy to forget to undo

Release Posture

v0.1.0 and the current v0.2.0 development line are source-build-only previews. Public binary downloads are blocked until:

  • Developer ID signing is configured.
  • The app is notarized and stapled.
  • Gatekeeper validation passes on a clean Mac.
  • Release artifacts are produced by protected CI.
  • SHA256 checksums are published.

Contributing

Forks and small fixes are welcome. Start with:

swift test
swift build -c release
./Scripts/build-app.sh

See CONTRIBUTING.md and SECURITY.md.

About

Cute macOS menu bar app that keeps your MacBook awake in clamshell mode.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors