IdleScreen
IdleScreen docs

Building from source

Requirements, repository gates, safe checks and the release path.

This page follows docs/BUILDING.md in the repository.

Requirements

  • macOS 26 Tahoe or later
  • Xcode 26
  • XcodeGen 2.46.0
  • Python 3 for the deterministic fixture tests
  • Lefthook 2.1.12, Qlty 0.618.0, actionlint 1.7.12 and zizmor 1.29.0 for the repository gates

Install the Homebrew tools and Qlty's signed release CLI. Download the Qlty installer and read it before running it, rather than piping it into a shell:

brew install xcodegen lefthook actionlint zizmor
curl -fsSL https://qlty.sh -o /tmp/qlty-install.sh
less /tmp/qlty-install.sh
sh /tmp/qlty-install.sh

Homebrew installs whatever is current, which isn't necessarily the version the gate expects. Check what you got:

./scripts/check-tool-versions.sh

CI asserts xcodegen --version exactly and installs Qlty from a pinned commit, so a local mismatch shows up as a disagreement with CI rather than a silent pass.

Generate and open the project

xcodegen generate
git diff --exit-code -- IdleScreen.xcodeproj

Open IdleScreen.xcodeproj and run the IdleScreenApp scheme for normal local development. A development build can't use the camera or agent hooks. See Troubleshooting.

Gates

lefthook install
./scripts/check-swift-format.sh changed
./scripts/qlty-check-gate.sh all
./scripts/verify-workflows.sh
./scripts/test-modern-schemes.sh

scripts/verify-workflows.sh runs actionlint and zizmor when present and reports a skip when either is unavailable, because CI is the authoritative workflow-security gate.

Safe deterministic checks

These don't install the app, register a helper or screen saver, request camera access, open System Settings or change power state:

./scripts/test-repository-layout.sh
./scripts/test-project-contracts.sh
python3 ./scripts/test_xccov_to_lcov.py
./scripts/test-companion-compile-gate.sh
python3 ./scripts/test_performance_r1_report.py
./scripts/test-run-performance-r1.sh
./scripts/test-camera-gate-c8-soak-planner.py
./scripts/test-controlled-physical-soak.py
./scripts/test-idlescreenctl-runtime.sh
./scripts/test-camera-agent-product-fixtures.sh
./scripts/test-synthetic-gate-product-fixtures.sh
./scripts/test-release-archive-provenance-fixtures.sh
./scripts/test-r1-release-candidate-fixtures.sh
./scripts/test-public-release-contract.sh

CI also runs the modern Xcode unit and integration schemes with Swift warnings as errors, CodeQL, workflow security, Qlty and Codecov coverage.

Physical checks

Scripts that install products, register services, open a camera, start the screen saver, lock the session, change displays or alter system state are separately consent-gated, and refuse by default. Read the script's refusal message, confirm the exact candidate and scope, and authorize only the action being performed. Never copy an opt-in from a fixture or another session.

Release candidates

scripts/build-r1-release-candidate.sh is the Developer ID distribution authority. A real run needs a clean committed source tree, a nonexistent absolute output directory outside the repository, the Developer ID Application identity SHA-1, separate distribution profiles for the app, extension and camera helper, an existing notarytool Keychain profile, and IDLESCREEN_ALLOW_REAL_DISTRIBUTION=YES.

The builder archives the app, embeds release identity, signs nested code from the inside out, creates a DMG, notarizes and staples it, and has Gatekeeper assess the DMG and the mounted app. It never creates or stores credentials and never signs after notarization.

Replay a finished candidate with scripts/verify-r1-release-candidate.sh, generate the Homebrew cask with scripts/generate-homebrew-cask.sh, and generate the SPDX 2.3 SBOM with scripts/generate-release-sbom.sh. Attach the SBOM to the GitHub release under exactly idlescreen-<version>-build<build>.spdx.json; the published download URL is derived from that name.

Ordinary changes target the protected dev/v0.1 branch. main advances only through a reviewed promotion pull request and gets the GA tag immediately.

Repository hygiene

Local roadmaps, raw test evidence, design exports and audit reports belong in the ignored .planning/ directory. Public documentation belongs under docs/.

Edit on GitHub