A menu-bar app that stops your Mac from falling asleep, and holds it there — after you quit, after a reboot, and against anything else that changes it.
Download the latest .dmg from
Releases, open it and
drag the app to Applications.
The build is signed and notarized, so there is no "unidentified developer" warning. Drag it in Finder rather than copying it from a terminal — a terminal copy triggers App Translocation, which breaks the helper.
Requires macOS 14 or later. Universal (Apple Silicon and Intel).
| Switch | What it does | System setting |
|---|---|---|
| Keep Awake | The Mac never sleeps on its own. The screen may still turn off. | pmset -a sleep 0 |
| Keep display on | The screen stays on too. | pmset -a displaysleep 0 |
| Stay awake with lid closed | Closing the lid does not put it to sleep. | pmset -a disablesleep 1 |
They are independent switches. For "close the lid and keep working" you want the first and the third: with the lid shut the Mac can still fall asleep for being idle.
Flip a switch and the setting is written into the system. Then it is held there:
- Quit the app: nothing changes
- The app crashes: nothing changes
- Reboot: your settings are still there
- Another app or script changes them: they are put back
- Only switching it off puts your machine back the way it was
The app does not need to be running. A small privileged helper does the holding, and it keeps running whether the menu is open or not.
While a switch is on, that setting wins. What is not touched is anything you did not switch on — if "Keep display on" is off, your display timeout is yours, and nothing here will fight you over it.
The menu reads the current state from the system rather than remembering what it last wrote, so it stays honest. When it cannot reach the helper it says so instead of showing everything as off.
Changing these settings needs root, and no entitlement lets a normal app do it. Keep Mac Awake ships a small privileged helper for exactly this. The first time you change a setting it is registered with macOS — usually silently, with just a notification that the app added a background item. If macOS does ask, you will find it under System Settings › General › Login Items & Extensions. Either way it happens once; after that the switches work instantly, with no password prompts.
Before changing anything the helper records your machine's own values, and puts them back when you switch everything off.
The helper is also what holds your settings, so it keeps running whether the menu is open or not. If macOS ever ends up with a registration it cannot start — which an in-place update used to cause — the app notices at launch and repairs it without asking. Settings shows the helper's real state, checked by asking the helper itself rather than trusting macOS's record of it.
Settings also has a Launch at login switch — that only puts the menu back after a restart. Your power settings are already in effect either way.
Those apps hold an IOPMAssertion, which is tied to the process holding it.
That is a good design for what they are: the moment you quit, the Mac goes back
to normal, and nothing on your system has been altered.
Keep Mac Awake writes the setting instead. Different trade-off:
| Assertion-based apps | Keep Mac Awake | |
|---|---|---|
| The app must keep running | Yes | No |
| Survives quit / crash / reboot | No | Yes |
| Changes system settings | No | Yes — restored when you switch off |
| Wins against another app changing them | n/a | Yes, while switched on |
| Needs an admin approval | No | Once, for the helper |
| Lid closed without an external display | Not possible | Yes |
Pick this one if you want to set it and forget it, or need the lid-closed case. Pick one of those if you want something that never touches your system state.
Power settings are not the only thing that stops a Mac sleeping. Any app can hold an assertion — video calls, media players, other keep-awake utilities — and that overrides the settings for as long as it lasts. Your Mac then stays awake with every switch here turned off, and nothing in the settings explains why.
Settings lists whatever is doing it, by name. It only reports; an assertion belongs to the app holding it.
Settings has Restore Defaults: every power setting goes back to its macOS default and this app releases its records.
You need it in one specific case. This app remembers your machine's values the first time you flip a switch, so it can put them back later. If something had already set your display to never sleep before you ever used this app, then that is what gets remembered as normal — and switching everything off restores it faithfully. Restore Defaults is the way out.
It also resets power settings you changed yourself outside this app.
Choosing Sleep from the Apple menu still puts the Mac to sleep. These settings prevent idle sleep, not a deliberate command. That is how macOS works.
brew install xcodegen
xcodegen generate
xcodebuild -project KeepMacAwake.xcodeproj -scheme KeepMacAwake -destination 'platform=macOS' buildKeepMacAwake.xcodeproj is generated from project.yml and is not in git.
# pure logic, safe anywhere
xcodebuild -project KeepMacAwake.xcodeproj -scheme KeepMacAwakeTests -destination 'platform=macOS' test
# plus tests that read the real machine
xcodebuild -project KeepMacAwake.xcodeproj -scheme KeepMacAwakeDeviceTests -destination 'platform=macOS' testDevice tests live behind a separate scheme rather than an environment variable:
xcodebuild does not forward shell environment into a host-less macOS test
bundle.
Needs an Apple Developer account — a Developer ID Application certificate and notarytool credentials saved once:
xcrun notarytool store-credentials keep-mac-awake \
--apple-id <id> --team-id <TEAMID> --password <app-specific-password>
./scripts/release.sh 1.2.1The script bumps the version and build number, archives universal, exports with
Developer ID, notarizes and staples the app, then wraps it in a DMG and
notarizes and staples that too. Both stapling passes matter: without the first
one the copy dragged to /Applications carries no ticket of its own.
Override with KMA_SIGN_IDENTITY, KMA_TEAM_ID, KMA_NOTARY_PROFILE if the
defaults do not match your setup.
Change bundleIdPrefix, the three PRODUCT_BUNDLE_IDENTIFIER values and
DEVELOPMENT_TEAM in project.yml, and rename
Helper/ai.pakslab.keep-mac-awake.helper.plist to match your helper's bundle
identifier — SMAppService requires the plist filename to equal the daemon's
Label.
See docs/architecture.md — the design decision behind "settings outlive the app", and the macOS traps this code works around.
App/ menu bar UI, settings window, app lifecycle
Core/ helper client, registration retry, login item, preferences
Helper/ privileged daemon: pmset control, the two stores, enforcement, XPC
Shared/ config type, XPC protocol and logging shared by both targets
Tests/ XCTest — pure logic plus device-gated checks
MIT — see LICENSE.
