stayawake is a lightweight macOS menu-bar utility that automatically decides when your Mac should stay awake.
It is designed for long-running work: builds, downloads, renders, scripts, audio playback, fullscreen activity, and focused work apps. When there is no useful activity, it lets macOS sleep normally.
Project page · Latest release · Screenshots
The menu-bar character changes with the current decision. The sleeping character means macOS can sleep normally; the energized character means stayawake is actively keeping the Mac awake.
More screenshots: Screenshots.
- Automatic sleep control with no manual toggle required for normal use
- Menu-bar status icon with separate Awake and Sleep states
- Current decision, reason, and recent logs directly in the menu
- Manual keep-awake options for 30 minutes, 1 hour, or until turned off
- Configurable CPU, network, disk, idle, process, foreground-app, and blocklist rules
- Low-resource polling strategy for a small always-on menu-bar app
- English and Simplified Chinese localization
- No cloud service, account, telemetry, or content upload
The fastest way to install is through Homebrew:
brew install --cask amoswzw/tap/stayawakeYou can also download the latest DMG directly from the GitHub Releases page and drag stayawake.app into /Applications.
Runtime:
- macOS 13 or later
Development:
- Xcode 15 or Swift 5.9 or later
swift build -c release
./build-app.sh
open build/stayawake.appbuild-app.sh creates an ad-hoc signed .app bundle at build/stayawake.app.
Launch the app and click the menu-bar icon. stayawake does not show a Dock icon.
The menu shows:
- Current state: keeping awake, manual keep-awake, or sleep allowed
- Current reason and next check timing
- Recent logs: the latest 5 meaningful state changes
- Manual keep-awake actions
- Settings and full logs windows
- Quit
The menu-bar icon follows macOS light and dark appearances. The sleeping character means sleep is allowed; the energized character means stayawake is actively keeping the Mac awake.
Open Settings... from the menu to configure:
- Launch at login
- App language
- Idle threshold
- Sampling and release cooldown
- CPU, network, and disk thresholds
- Task process names
- Foreground work-app allowlist
- Foreground/fullscreen blocklist
Settings are stored locally in UserDefaults.
stayawake collects lightweight system signals and feeds them into a pure policy function.
| Signal | Source |
|---|---|
| Idle time | CGEventSourceSecondsSinceLastEventType |
| Foreground app | NSWorkspace.frontmostApplication |
| Task process names | sysctl(KERN_PROC_ALL) |
| Per-core CPU usage | host_processor_info with a 60s P75 window |
| Network rate | getifaddrs / if_data with a 60s P75 window |
| Disk rate | IOBlockStorageDriver statistics with a 60s P75 window |
| Audio activity | CoreAudio device running state |
| Fullscreen windows | CGWindowListCopyWindowInfo |
| Battery / AC power | IOPSGetProvidingPowerSourceType |
| Thermal state | ProcessInfo.thermalState |
Decision order:
- Manual override keeps the Mac awake.
- Serious or critical thermal state on battery allows sleep.
- Resource activity or audio keeps the Mac awake.
- Task process, foreground work app, or fullscreen activity keeps the Mac awake only when paired with recent user input.
- Probe failures keep the Mac awake to avoid interrupting work.
- User idle with no activity allows sleep.
- Otherwise, sleep is allowed.
stayawake favors low overhead over high-frequency monitoring.
- Automatic decisions are rechecked after the configured cooldown, defaulting to 120 seconds.
- Manual keep-awake until turned off uses a longer 300-second tick.
- Repeated identical automatic decisions are deduplicated in the log.
- CoreAudio device lists are cached for 5 minutes.
- Logs are kept in memory and capped.
This keeps the app small and quiet while preserving the main goal: avoid interrupting long-running work.
- No Accessibility permission is required.
- No user files, windows, text, browser content, or terminal output are read.
- No data is uploaded.
- The app only reads aggregate system signals such as CPU, network, disk counters, app bundle IDs, process names, idle time, audio activity, and power state.
Bundled languages:
- English
- Simplified Chinese
To add another language:
- Create
Sources/stayawake/Resources/<locale>.lproj/Localizable.strings. - Use
Sources/stayawake/Resources/en.lproj/Localizable.stringsas the template. - Add the locale to
CFBundleLocalizationsinbuild-app.sh.
.
├── Package.swift
├── build-app.sh
├── docs/_config.yml
├── docs/_layouts
├── docs/index.md
├── docs/SCREENSHOTS.md
├── docs/assets
├── docs/screenshots
├── Sources/stayawake
│ ├── App.swift
│ ├── AppCoordinator.swift
│ ├── MenuBarController.swift
│ ├── SettingsView.swift
│ ├── LogsView.swift
│ ├── Policy.swift
│ ├── *Probe.swift
│ └── Resources
│ ├── en.lproj
│ ├── zh-Hans.lproj
│ ├── status-awake-template.png
│ ├── status-sleep-template.png
│ └── stayawake.icns
└── Tests/stayawakeTests
├── PolicyTests.swift
└── EventLogTests.swift
build/, .build/, and Xcode user state are generated locally and should not be committed.
swift testThe test suite covers policy decisions, signal derivation, log deduplication, blocklist behavior, and sliding-window behavior.
MIT. See LICENSE.
