Important
Needs a MacBook whose hinge reports a continuous angle. Apple silicon Airs
(M2 and later) and the 14"/16" Pros have that sensor; the M1 Air, the 13" M1 Pro
and every desktop Mac do not. Build it and run --selftest and it will tell you
in one line.
FrostFold is a cosmetic effect and nothing else. It runs in the background with no dock icon and no menu bar item — no account, no licence key, and no network code of any kind.
It is a personal project by Riccardo Nevoso, written from a description of how such an effect ought to behave rather than from anyone else's source, assets or wording.
Stills are rendered from a synthetic desktop, so none of mine ends up in the repository.
Regenerate them from your own screenshot: Scripts/filmstrip.sh --input shot.png --out docs/readme
Finished and in daily use. The effect, the settings panel, the preview scrubber, start-at-login and the accessibility behaviour are all in place. What is not: notarisation, so a downloaded copy needs one right-click to open.
The pane is hinged at the foot of the display and folds away from you, carrying the picture with it — the way a lid closes, not the way a page lifts. The hinge stays pinned at full width while everything above it foreshortens and converges, so the picture collapses toward the hinge line instead of spreading. Three things follow, and together they are the whole effect.
The gap drives the frost. The glass still meets the display at the hinge and lifts further away toward its free edge, so there is no gap at all along the hinge and the most of it at the top. Frost follows the gap, so the foot of the screen stays legible while everything above it turns to milk. Hold frosted glass against text and you can read it; lift it away and you cannot.
What it lifts off has nothing left to show. The picture has gone with the glass, so the display behind the pane blacks out, and the black opens up from the top as the pane converges.
It dims as it leans. Less light reaches you the further the pane tips away, so the glass darkens along with the gap.
![]() |
![]() |
![]() |
| 100° above the engage angle — nothing renders, capture is off |
50° gathering — converging, the gap just opening at the free edge |
22° collapsed toward the hinge, blacked out above |
Look at the bottom edge of any window in the last two: it stays sharp while its own title bar has dissolved.
| OS | macOS 14 Sonoma or later |
| Hardware | A MacBook with a continuous lid-angle sensor. Apple silicon Airs (M2 and later) and 14"/16" Pros have one; the M1 Air, the 13" M1 Pro and every desktop Mac do not. |
| Toolchain | Xcode Command Line Tools (xcode-select --install). Full Xcode is not required — the Metal shaders are compiled at runtime. |
Not sure whether your Mac qualifies? Build it and run --selftest; it tells you
in one line.
Download the latest build from Releases, or build it yourself:
git clone <your-fork> && cd FrostFold
Scripts/signing-identity.sh # once — see the note below
Scripts/bundle.sh --universal # arm64 + x86_64
cp -R dist/FrostFold.app /Applications/
open -a FrostFoldScripts/bundle.sh compiles a release build, assembles the bundle, copies in
the icon and ad-hoc signs it. Drop --universal while you're iterating to build
only the native slice — it's roughly ten times quicker.
Important
Run Scripts/signing-identity.sh once. An ad-hoc signature has no identity
of its own, so the requirement macOS records for the Screen Recording grant is
the code hash itself:
designated => cdhash H"9ef21410…"
Every build with changed source gets a new hash, so macOS treats it as a different app and asks for the permission again — and every release you ship makes your users re-grant too.
The script creates a self-signed certificate, and the requirement becomes:
designated => identifier "io.github.frostfold" and certificate root = H"8aae…"
No hash in it, so no rebuild can invalidate it. bundle.sh picks the identity
up automatically and falls back to ad-hoc if it isn't there. Switching to it
changes the app's identity once, so expect one final prompt.
It lives in its own keychain, not your login keychain — the login keychain
gates key access behind an interactive dialog that a script can't answer.
Remove it any time with security delete-keychain frostfold-signing.keychain.
Important
This app has not been through Apple's notary service. A copy you did not compile yourself therefore needs right-click → Open once, or System Settings → Privacy & Security → Open Anyway. It opens normally thereafter.
FrostFold has no dock icon and no menu bar item — it starts, sits in the background and waits for the lid. Launching it again doesn't start a second copy; it opens the settings of the one already running.
open -a FrostFold # start it, or open settings
dist/FrostFold.app/Contents/MacOS/FrostFold --quit # stop it--settings, --preview, --quit and --selftest all work on the binary
inside the bundle. The settings window carries an Enabled switch, a Preview
button and Quit, so you never need the command line to get back out.
To start it with the Mac, use Start FrostFold at login in its settings. If macOS holds the registration pending approval, the panel says so and offers to open the Login Items pane.
FrostFold cannot work without Screen Recording. The glass is assembled from whatever the screen is showing, so denying it leaves nothing to draw.
macOS asks once, on first launch, with its own prompt. Allow it and FrostFold carries straight on — and with the signing identity above in place, it won't ask again on later builds.
If you dismissed that prompt, macOS won't ask a second time — FrostFold will say so and offer to open Privacy & Security → Screen Recording, where you can switch it on and start the app again.
The lid-angle sensor itself needs no permission at all.
Launch FrostFold again to open them (open -a FrostFold). Preview… opens a
window with a manual scrubber, so you can dial the effect in without opening and
closing the lid a hundred times.
Material
| Intensity | Low / Medium / High. How milky the top edge gets once the fold is fully in. |
| Perspective | How hard the pane converges as it folds away, and with it how fast the gap opens. Higher narrows the free edge further and concentrates the milk at the top. |
| Edge softness | Fall-off at the pane's free edges. The hinged edge stays pinned to the display and never fades. |
| Dimming | How far the glass darkens as the gap opens. |
| Corner radius | Rounding on the free corners, in points, so you can match your display's own rounding. The hinged edge runs straight. |
Motion
| Responsiveness | Low trails the lid; high tracks it immediately. |
| Hinge sensitivity | Where in the lid's travel the fold does its work. Low holds off until the lid is well down and then gathers; high rises the moment the lid moves. |
| Minimum movement | Deadband, in degrees. Below this the pane holds still, so a lid parked part-way open doesn't shimmer on sensor noise. |
| Engages at | The lid angle at which the fold starts, 85° by default — a little past perpendicular, so normal use never triggers it. Above this angle nothing renders and capture is off. |
| Maximum fold | How far back the pane tips once the fold is complete, which is what sets the gap and therefore the frost. |
| Stationary frame rate | 15 / 30 / 60 / 90 / 120 FPS. Only applies while the lid is still. |
The fold is normalised over the span from the engage angle down to roughly shut, so it always completes as the lid closes, whatever you set the engage angle to.
The sensor. MacBooks expose the hinge as an Apple HID sensor device (las,
usage page 0x20, usage 0x8A). Two feature reports carry the angle: report 7
is a little-endian UInt32 in hundredths of a degree, report 1 a UInt16 in
whole degrees. FrostFold prefers 7 and falls back to 1. It polls at 120 Hz while
the lid is moving and drops to the stationary rate once it settles.
The capture. A ScreenCaptureKit stream over the built-in display, with
FrostFold's own windows excluded from the content filter (and marked
sharingType = .none) so the pane cannot capture its own output and spiral.
Frames arrive as IOSurface-backed pixel buffers and become Metal textures
without a copy.
The render. The pane is a real quad in 3D, hinged along y = -1 and rotated
about that edge, away from the viewer. The vertex shader hands the rasteriser a
w of (D - z) / D and lets the hardware do the perspective divide, so the
picture stays correct across the whole pane rather than warping the way a 2D
fake does. Folding away rather than toward also keeps w > 1 everywhere, so the
near plane can never be crossed however hard the perspective is set. Everything
the pane no longer covers is filled black, because the picture left with the
glass.
The gap at any point on the pane is its distance from the hinge times the sine of the tilt — zero at the hinge by construction, which is why the bottom stays clear without that having to be tuned. Frost is read straight off it. Rather than crossfading one blurred copy against the sharp frame, the renderer builds a four-level blur pyramid (¼, ⅛ and ¹⁄₁₆ resolution, each softer than the last) and the fragment shader walks it continuously by the local frost. A crossfade reads as haze sitting on top of a still-sharp picture; walking a pyramid genuinely defocuses, which is what a diffuser does. Grain is keyed to pane-local coordinates, so it lives in the material and travels with it.
There is no specular term anywhere in the shader. Etching a surface makes it scatter what passes through it, not mirror what falls on it, so a highlight would be the wrong kind of light entirely.
Capture runs only while the pane has something to show. Above the resting angle the stream is torn down entirely and the overlay clears to fully transparent — what is left is a feature-report read at the stationary rate, which is a few dozen bytes over the HID transport.
FrostFold reads the display settings you've already set, and re-reads them when they change:
| Reduce Motion | The pane's travel is damped to a third. The effect is motion, so it's honoured by damping rather than by switching off — the frost still reads, the pane barely moves. |
| Reduce Transparency | Scatter is halved, so what's behind the glass stays legible. |
| Increase Contrast | Edge fall-off tightens to a defined edge instead of a fade. |
Captured frames go from ScreenCaptureKit to the GPU and nowhere else. Nothing is
written to disk, nothing is sent anywhere, there is no analytics and no network
code of any kind. Settings live in UserDefaults.
# Headless diagnostics: Metal, shader compilation, the sensor, the permission.
dist/FrostFold.app/Contents/MacOS/FrostFold --selftest
# Render the pane over a still image at a range of lid angles.
Scripts/filmstrip.sh --input shot.png --out docs/readme
# Redraw the app icon and repack Resources/FrostFold.icns.
Scripts/icon.sh
# Redraw docs/readme/banner.svg, with DM Sans embedded.
python3 Tools/banner/make.py
# Create the self-signed code-signing identity (once).
Scripts/signing-identity.shfilmstrip produces the images in this README, and it's the quickest way to
judge a shader change without touching the lid. icon.sh draws the app icon
from code — Resources/FrostFold.icns is committed, so you only need it if you
change the drawing.
Project layout
Sources/FrostFold/
LidAngleSensor.swift HID feature-report reader, adaptive polling
ScreenCapturer.swift ScreenCaptureKit stream → MTLTexture
Shaders.swift Metal source, compiled at runtime
MetalRenderer.swift reduce → blur → hinged pane
GlassView.swift CAMetalLayer view and the click-through overlay window
EffectController.swift ties it together, decides when anything runs
Settings.swift UserDefaults-backed preferences
SettingsWindow.swift SwiftUI settings panel
PreviewWindow.swift preview with a manual scrubber
AppDelegate.swift background lifecycle, second-launch signals
SelfTest.swift --selftest
Tools/filmstrip/ still-image renderer
Tools/icon/ draws the app icon
Tools/banner/ draws the README banner
Tests/FrostFoldTests/ the fold's arithmetic, and regressions for two
bugs that a still image could not have caught
Scripts/ bundle.sh, filmstrip.sh, icon.sh, signing-identity.sh
.claude/skills/apple-design/ the macOS design language this UI follows
This is an independent, clean-room implementation of an idea — a lid-angle-driven frosted fold — written from a description of the behaviour, not from anyone else's source, assets or branding. It is not affiliated with or derived from any other application. The name deliberately avoids Apple trademarks; "MacBook" and "Mac" appear here only as hardware compatibility statements.
MIT. See LICENSE.



