A native macOS screensaver (.saver bundle) that displays the Skynet logo on a simulated CRT monitor: scanlines, chromatic aberration, noise, a rolling bar, flicker, and periodic heavy glitches.
The screensaver renders a self-contained HTML file inside a WKWebView, hosted by a minimal ScreenSaverView subclass in Swift. An external Swift timer drives the frame loop, because WebKit would otherwise throttle the page when macOS treats the view as hidden.
- Open
build/in Finder and double-clickSkynet.saver. - macOS asks for this user or for all users – pick one; System Settings opens with Skynet preselected.
- Hit Set as Screen Saver.
If Gatekeeper complains on first launch:
xattr -dr com.apple.quarantine ~/Library/Screen\ Savers/Skynet.saverNo
build/Skynet.saveryet? Run./build.sh --no-installonce, then double-click.
The sections below cover the same steps in detail, plus alternatives, rebuilding, and troubleshooting.
- macOS 11 (Big Sur) or newer
- Xcode Command Line Tools – install them if missing:
Verify with
xcode-select --install
swiftc --version(it must print a version). - No other dependencies. No Xcode project, no Homebrew – just Swift and a shell script.
skynet-screensaver/
├── build.sh # Compiles, signs, installs
├── skynet.html # Self-contained HTML with SVG logo + CRT effects
├── src/
│ ├── SkynetView.swift # ScreenSaverView subclass, loads HTML in WKWebView
│ └── Info.plist # Bundle metadata
├── build/
│ └── Skynet.saver/ # Compiled bundle (produced by build.sh)
├── README.md
└── LICENSE
git clone <repo-url> skynet-screensaver
cd skynet-screensaverOr just copy the folder if you're not using Git.
./build.sh --no-installThe script, in one go:
- Wipes
build/Skynet.saver - Copies
Info.plistandskynet.htmlinto the bundle - Compiles
src/SkynetView.swiftagainst theScreenSaver,WebKitandCocoaframeworks - Ad-hoc signs the bundle (
codesign --sign -) so Gatekeeper stops complaining
The finished bundle ends up at build/Skynet.saver.
Option A – double-click in Finder (simplest):
- Open
build/in Finder - Double-click
Skynet.saver - macOS asks whether to install it for this user or for all users – pick one
- System Settings opens with Skynet preselected
Option B – let the build script install it:
./build.shSame as --no-install, but additionally copies the bundle to
~/Library/Screen Savers/Skynet.saver. Handy during development when you
rebuild often.
Option C – open from the Terminal:
open build/Skynet.saverTriggers the same install dialog as double-clicking in Finder.
- macOS 14 Sonoma and newer: System Settings → Screen Saver → scroll to the Other group → pick Skynet.
- macOS 13 Ventura and older: System Preferences → Desktop & Screen Saver → Screen Saver → pick Skynet.
Click the preview image to start a fullscreen preview.
Tip: if Skynet doesn't show up, close System Settings completely and open it again.
On first launch you may see a warning like "Skynet.saver can't be opened because Apple cannot check it for malicious software."
Option A – via the UI: System Settings → Privacy & Security → at the bottom you'll see "Skynet was blocked…" → Open Anyway.
Option B – via Terminal (faster):
xattr -dr com.apple.quarantine ~/Library/Screen\ Savers/Skynet.saverIf you change the HTML, the logo, or the Swift code:
./build.shThen, in System Settings, switch to a different screensaver and back to Skynet – otherwise macOS serves the cached version.
If the new build still isn't picked up:
# Kill the screen saver engine; macOS will relaunch it on demand
killall ScreenSaverEngine legacyScreenSaver 2>/dev/null || trueTo iterate on the visuals without rebuilding the bundle:
open -a Safari skynet.htmlSame file that ships inside the bundle – useful for fast CSS/JS tweaks.
rm -rf ~/Library/Screen\ Savers/Skynet.saverThen pick a different screensaver in System Settings.
All visual parameters live in skynet.html:
| Effect | Where | Parameter |
|---|---|---|
| Scanline strength | CSS .scanlines |
alpha value 0.38 |
| Noise intensity | CSS #noise |
opacity: 0.12 |
| Small glitches | JS scheduleGlitch() |
interval 2500 + rand*9000 ms |
| Heavy glitch | JS scheduleHeavyGlitch() |
first fires 40–90 s in, then every 2–5 min |
| Roll-bar speed | CSS animation: roll |
8.5s (smaller = faster) |
| Colors | CSS vars / fills | #c20000 (red), #d8d8d8 (text), #8a0000 |
"Skynet" doesn't appear in the list Check that the bundle is actually installed:
ls -la ~/Library/Screen\ Savers/Skynet.saver/Contents/MacOS/SkynetThe binary must exist and be executable. If not, run ./build.sh again.
Black screen instead of the logo
Usually skynet.html is missing from the bundle. Verify:
ls ~/Library/Screen\ Savers/Skynet.saver/Contents/Resources/The screensaver stops animating after a few seconds
macOS throttles WKWebView in the background. The external Swift timer in SkynetView.swift already works around that – if it stops working, check whether forcePageVisible() still hits the private selector. (Apple occasionally changes the signature between major versions.)
Build script fails with "swiftc: command not found"
Command Line Tools are missing: xcode-select --install.
codesign fails
Ad-hoc signing (--sign -) needs no certificate. If it still errors out, this usually helps:
sudo xcode-select -rSkynetViewis aScreenSaverViewsubclass that hosts aWKWebViewas its only subview.skynet.htmlis loaded into that WebView from the bundle resources.- A
WKUserScriptinjected atdocumentStartoverridesdocument.hidden/visibilityState, sorequestAnimationFrameand CSS animations don't get throttled. - In addition, a Swift
Timerruns at 30 Hz and callswindow.__sk.update(performance.now())viaevaluateJavaScripton every tick. That's the external frame driver WebKit can't throttle. forcePageVisible()uses a private API (_setVisibilityState:isInitialState:or_setVisibilityState:) to pin the WebView as visible, so the compositor keeps drawing even when the screensaver host flags the view as hidden.
MIT – see LICENSE.