README.md
Amped ⚊
A tiny, completely native macOS menu bar app that keeps your Mac awake — an
Amphetamine-style alternative whose party trick is keeping the Mac awake with
the lid closed, using pmset disablesleep rather than caffeinate alone.
No window, no settings sheet, no Dock icon. Just a pill in your menu bar and a handful of switches.
Install
| 1 | brew install --cask gustaferiksson/tap/amped |
Or grab the notarized Amped.app from the latest release
and drop it in /Applications. macOS 26 (Tahoe) or newer.
The menu
Click the pill in the menu bar:
| Toggle | What it does |
|---|---|
| Keep Awake | Prevents idle sleep while the lid is open. Uses an IOKit power assertion (same mechanism as caffeinate). No password needed. |
| Allow Lid Closed | Also stays awake with the lid closed (clamshell). Runs pmset -a disablesleep 1, the only thing that overrides clamshell sleep. An independent switch — it keeps the Mac awake on its own (it holds the idle-sleep assertion internally) without flipping the Keep Awake toggle. |
| Lock Screen on Lid Close | Security guard for lid-closed mode: the instant the lid shuts, Amped locks the screen so the Mac keeps running but stays behind your password. Without it, suppressing sleep also suppresses the usual lock-on-sleep, leaving a closed lid awake and unlocked. On by default; remembered between launches. |
| Auto-off at 20% Battery | Safety net: when on battery and the charge drops to 20% or below, Amped releases everything so the Mac can sleep normally. Remembered between launches. |
| Launch at Login | Registers Amped as a login item (via SMAppService) so the pill is there every time you log in. |
The menu bar pill reflects the state at a glance:
pill— sleep allowed (off)pill.fill— awake (lid open)pills.fill— awake with the lid closed
A status line shows the current state and battery level. ⌘Q quits.
On launch Amped starts with everything off (so it never surprises you by blocking sleep or prompting). Only the Auto-off and Lock Screen on Lid Close preferences are remembered. When it quits it always restores normal sleep behaviour.
How lid-closed mode stays passwordless
Keeping a Mac awake with the lid shut requires flipping the system
disablesleep flag, which only root can do. Amped does this through a small
privileged helper — a root LaunchDaemon embedded in the app bundle that
the app talks to over XPC. The XPC channel is locked to Amped's own
Developer-ID Team ID (setCodeSigningRequirement), so nothing but Amped's
signed app can reach the helper, and the helper does exactly one thing:
pmset disablesleep on/off.
The first time you enable Allow Lid Closed, Amped offers to set the helper up. Approve "Amped" once under System Settings → General → Login Items & Extensions, and from then on the lid toggle is silent — which also lets Auto-off at 20% drop clamshell mode while the lid is shut and you're away. Prefer not to? Just This Time keeps the Mac awake now with a single password prompt and installs nothing. Remove the helper anytime from that same System Settings pane (it's visible there, unlike a hidden sudoers rule); the setup offer reappears the next time you enable lid-closed mode.
The helper only runs in a properly signed build. In an unsigned local build it can't be approved, so lid mode falls back to a password prompt on every toggle. Build signed (below) to exercise the real path.
Build & run
Requires Xcode, plus two Homebrew tools:
| 1 | brew install xcodegen librsvg |
| 2 | ./build.sh # ad-hoc local build → ./dist (helper inactive; password fallback) |
| 3 | open dist/Amped.app # the pill appears in your menu bar |
Signed build (helper works)
Signing config lives in .env (git-ignored; copy from .env.example):
| 1 | DEVELOPMENT_TEAM=82K3YC8HVF |
| 2 | CODE_SIGN_IDENTITY="Developer ID Application" |
Then ./build.sh produces a build that meets Apple's notarization requirements:
Developer ID signing, Hardened Runtime on both the app and the helper, a
secure timestamp, and no get-task-allow entitlement. Install and try it:
| 1 | cp -R dist/Amped.app /Applications/ # run from a stable location |
| 2 | open /Applications/Amped.app |
Then: enable Allow Lid Closed → Set Up Helper… → approve Amped in System Settings → toggle Allow Lid Closed again — it's now silent. (No Team ID is hard-coded: the app reads its own at runtime to pin the XPC channel to the same team.)
Notarize & ship
One-time: create a notarytool keychain profile (the password is an
app-specific password from appleid.apple.com, not your Apple ID password):
| 1 | xcrun notarytool store-credentials "Amped" \ |
| 2 | --apple-id "you@example.com" --team-id 82K3YC8HVF --password "xxxx-xxxx-xxxx-xxxx" |
Set NOTARY_PROFILE=Amped in .env, then after a signed ./build.sh:
| 1 | ./notarize.sh # ditto-zips, notarytool submit --wait, stapler staple, verifies |
Distribute the stapled dist/Amped.app (zip or DMG). altool is dead since
Nov 2023 — this uses notarytool.
For automated releases — push a v* tag and CI produces the notarized
GitHub Release and bumps the Homebrew cask — see docs/RELEASING.md.
To work on it in Xcode:
| 1 | ./icon/generate-icons.sh && xcodegen generate && open Amped.xcodeproj |
(The .xcodeproj is generated from project.yml and is git-ignored.)
The icon
- Menu bar: an SF Symbol (
pillfamily) — Apple permits SF Symbols in your own UI, and they adapt to light/dark and the focus state automatically. - App icon:
icon/amped.svg(a two-tone capsule).icon/generate-icons.shrenders it into the asset catalog at all macOS sizes. To make a proper Liquid Glass icon, openamped.svgin Icon Composer, refine the layers, and export an.iconto drop into the project.
A note on the App Store
The lid-closed feature relies on pmset disablesleep / a privileged helper,
which a sandboxed App Store build cannot do. Ship it as a notarized
Developer ID app. An App Store version would have to drop the clamshell
feature.
Project layout
| 1 | Sources/ (the app) |
| 2 | AmpedApp.swift @main App + MenuBarExtra |
| 3 | MenuContent.swift the dropdown (toggles + status + quit) |
| 4 | MenuBarLabel.swift the pill SF Symbol that reflects state |
| 5 | SleepController.swift state, battery polling, auto-off safety net |
| 6 | PowerAssertion.swift IOKit power assertion wrapper (idle sleep) |
| 7 | Privileged.swift routes pmset to the helper, else an admin prompt |
| 8 | HelperClient.swift registers/calls the helper (SMAppService + XPC) |
| 9 | Battery.swift battery % + on-battery via IOKit power sources |
| 10 | LoginItem.swift launch-at-login via SMAppService |
| 11 | Prompts.swift first-use helper-setup dialogs |
| 12 | AppDelegate.swift restores normal sleep on quit |
| 13 | Helper/ (the privileged root daemon) |
| 14 | main.swift XPC listener entry point |
| 15 | HelperService.swift runs pmset as root; pins the client by Team ID |
| 16 | dev.gustaf.Amped.Helper.plist LaunchDaemon definition |
| 17 | Shared/ (compiled into both targets) |
| 18 | HelperProtocol.swift the XPC contract |
| 19 | HelperConstants.swift identifiers / service names |
| 20 | CodeSigning.swift Team-ID requirement helpers |
| 21 | icon/ amped.svg + render script |
| 22 | project.yml XcodeGen project (app + helper targets) |
| 23 | build.sh one-shot local / signed build |
| 24 | notarize.sh notarytool submit + stapler staple |
| 25 | .env.example signing / notary config template |