Lid Awake is a native macOS menu bar app for keeping a Mac awake during deliberate local work. It can hold standard idle sleep assertions and, when the user opts in, use an admin-approved helper to manage closed-lid sleep behavior.
Bundle identifier: com.thuongtin.LidAwake.
Website: lidawake.pages.dev.
Lid Awake is early release software. Public downloads are Developer ID signed, notarized by Apple, and distributed as DMG and zip archives with SHA-256 checksums. Release builds include Sparkle update metadata so users can check for signed updates from the app.
- Menu bar control for keeping the Mac awake.
- Battery and Low Power Mode guardrails.
- Optional launch at login.
- Optional closed-lid mode through a macOS-approved privileged helper.
- Display-on or display-off behavior for supported closed-lid workflows.
- Optional lock screen request when the lid closes.
- Sparkle-powered update checks from the menu bar and Settings.
- CI-safe checks separated from local runtime verification.
- Local release archive creation with SHA-256 checksum.
- macOS 14 or newer.
- Apple Silicon Mac. Current public builds are
arm64only and do not run on Intel Macs.
- Xcode command line tools.
- Swift toolchain compatible with SwiftPM
swift-tools-version: 5.10.
Install with Homebrew:
brew tap thuongtin/tap
brew install --cask lid-awakeThe Homebrew cask declares depends_on arch: :arm64, so Intel Macs are blocked at install time.
Download the latest LidAwake-<version>-macos.dmg and matching .sha256 file from GitHub Releases. The zip archive is also published for users who prefer scriptable downloads.
Verify the checksum:
cd ~/Downloads
shasum -a 256 -c LidAwake-<version>-macos.dmg.sha256Then open the DMG and drag LidAwake.app to Applications. If you choose the zip archive instead, verify the matching LidAwake-<version>-macos.zip.sha256 file before unzipping.
Release builds are notarized and stapled, including the DMG, so normal installs do not require xattr. If macOS still blocks the app, first confirm you downloaded the official release asset and that the checksum matches. Avoid xattr -cr for official releases unless you intentionally changed the archive or received it through a channel that added a quarantine problem outside the release package.
Closed-lid behavior is hardware and macOS policy dependent. Running a MacBook while closed can increase heat under CPU, GPU, or charging load. Keep the machine ventilated, watch thermal behavior, and turn closed-lid mode off when it is no longer needed.
Lid Awake does not use sudo from the app. Closed-lid mode is an explicit user choice and requires macOS approval for the privileged helper before the app can ask it to run pmset -a disablesleep 1 or pmset -a disablesleep 0.
The helper only accepts XPC clients identified by macOS code signing as com.thuongtin.LidAwake. See Power Model for the helper trust boundary and power-management details.
Run the CI-safe contributor check:
./scripts/check.shThis command runs swift test, swift build, stages dist/LidAwake.app, and lints the staged Info.plist. It is safe for CI because it does not launch the app.
Run only the test suite:
swift testBuild all SwiftPM targets:
swift buildStage the app bundle without launching:
./script/build_and_run.sh --stageBuild and launch the local app bundle:
./script/build_and_run.shLocal debug staging leaves Sparkle update checks unconfigured by default. This prevents local builds from showing update errors before a public appcast.xml exists. To test a custom appcast locally, pass SPARKLE_ENABLED=1 and SPARKLE_FEED_URL=<url> to script/stage_app.sh or script/build_and_run.sh; add SPARKLE_ALLOW_INSECURE_FEED=1 if the local feed is not https:// (for example http://localhost).
Optional local runtime verification lives in scripts/verify.sh. It may launch the app, delete LidAwake.settings defaults for verification, and check live pmset power assertions, so it is not used by CI and should run only on a developer Mac where runtime power-management QA is acceptable.
Create a local release archive:
./script/package_release.shArchives are written to dist/releases with a .sha256 checksum. Public release packaging requires Developer ID signing by default, so read Releasing before publishing a public build.
./script/package_release.sh is a public release gate by default and requires a Developer ID Application signing identity. For local archive testing only, run it with ALLOW_NON_DEVELOPER_ID_RELEASE=1.
After the app bundle is notarized and stapled, create a DMG installer:
./script/package_dmg.shAfter the notarized DMG is stapled, generate a Sparkle appcast:
./script/package_appcast.shThe appcast is written to dist/releases/appcast/appcast.xml. Sparkle uses the public key in scripts/sparkle_public_key.txt; the matching private key must stay in Keychain or a local secret and must never be committed.
- Agent Guide: verification commands, danger zones, and conventions for AI coding agents.
- Power Model: power-management behavior, helper trust boundary, and manual QA.
- Developer Permissions Guide: helper approval, Accessibility, signing, and local permission diagnostics.
- Releasing: packaging, signing, checksum, and notarization guidance.
- Troubleshooting: common helper, permission, and power assertion issues.
- Contributing: development workflow and pull request expectations.
- Security Policy: private reporting path for helper and power-management vulnerabilities.
- Support: where to ask questions and how to file useful issues.
- Code of Conduct: community participation expectations.
- Changelog: notable user-facing, packaging, and documentation changes.
Sources/LidAwake: menu bar app, settings UI, and app-side services.Sources/LidAwakeCore: shared policy, parsing, settings, power abstractions, and helper XPC contract.Sources/LidAwakeHelper: privileged helper entrypoint for closed-lid mode.Tests/LidAwakeCoreTests: deterministic unit tests for core behavior.Tests/LidAwakeTests: app lifecycle tests with fake services.script/stage_app.sh: pure app bundle staging without launching the app.script/build_and_run.sh: local stage, run, debug, logs, telemetry, and runtime verification entrypoint.script/package_release.sh: local release archive and checksum command.script/package_dmg.sh: DMG creation command for notarized and stapled app bundles.script/package_appcast.sh: Sparkle appcast generation command for notarized release archives.scripts/sparkle_public_key.txt: public Sparkle EdDSA key used by release builds.scripts/check.sh: CI-safe build, test, stage, and plist lint.scripts/verify.sh: optional local runtime smoke verification that may launch the app.plans/: implementation plans and reviewer status.
Keep local scratch output and reference repositories outside the public source tree. The repository ignores work/, outputs/, .codex/, dist/, and Swift build output so local study material and generated artifacts do not become project artifacts.
- Intel Macs are not supported by current public release artifacts.
- Closed-lid mode requires explicit helper approval in System Settings.
- The local staged app uses development signing suitable for local testing.
- Self-update requires the published
appcast.xmlrelease asset to match the current notarized DMG. - Closed-lid behavior may vary by Mac model, power source, lid state, and macOS policy.
Lid Awake is available under the MIT License. See LICENSE.