A minimal Swift CLI to turn the MacBook built-in display on or off without closing the lid. Inspired by Lunar's BlackOut feature, with implementation patterns drawn from screen_tune.
- Apple Silicon Mac (M1 or later)
- macOS 13 Ventura or later
- At least one external monitor connected (when turning the built-in off)
- Swift toolchain (
swift build)
Intel Macs are not supported. The
SLSConfigureDisplayEnabledAPI behaves differently on Intel and does not perform a true display disconnect.
displaytoggle <command>
Commands:
on Turn the built-in display on
off Turn the built-in display off (requires ≥1 external monitor)
toggle Toggle the built-in display on/off
status Print current state (on/off)
Examples:
displaytoggle status # Built-in display: ON
displaytoggle off # Built-in display: OFF
displaytoggle on # Built-in display: ON
displaytoggle toggle # Built-in display: OFFExit codes: 0 success, 1 bad arguments, 2 runtime error.
# Build and install to PATH
bash build.shNo code signing is required. The binary runs unsigned.
macOS exposes no public API for disconnecting the built-in display while the lid is open. This tool uses two private functions from SkyLight.framework:
| Private API | Purpose |
|---|---|
SLSConfigureDisplayEnabled |
Enable or disable a display |
SLSGetDisplayList |
Enumerate all displays, including disabled ones |
SLSConfigureDisplayEnabled is called inside a Core Graphics display configuration transaction:
CGBeginDisplayConfiguration(&config)
SLSConfigureDisplayEnabled(config, displayID, enabled)
CGCompleteDisplayConfiguration(config, .permanently)The .permanently flag commits the change persistently. A side effect of this is that CGGetOnlineDisplayList no longer returns the disabled display — SLSGetDisplayList is used instead to locate the built-in display ID when turning it back on.
On Apple Silicon, a disabled display is fully disconnected at the hardware level (not just dimmed), identical to clamshell mode. It disappears from CGGetActiveDisplayList entirely.
displaytoggle off refuses to run if no external monitor is detected, preventing you from blacking out your only display:
Error: No external monitor detected. Refusing to black out built-in display.
displaytoggle/
├── Package.swift
├── build.sh
└── Sources/displaytoggle/
├── SkyLightBridge.h # Objective-C bridge declaring private SkyLight APIs
├── DisplayManager.swift # Display detection and toggle logic
└── main.swift # CLI argument parsing and entry point
- macOS updates may break this.
SLSConfigureDisplayEnabledandSLSGetDisplayListare private, undocumented APIs with no stability guarantees. - Sleep/wake may re-enable the built-in display. macOS can restore the display state after waking from sleep. Run
displaytoggle offagain if needed, or wrap it in alaunchdwake trigger. - M3 (non-Pro/Max) second external monitor. Disabling the built-in on entry-level M3 does not unlock a second external port — this is a macOS hardware limitation unrelated to this tool.
This tool was inspired by Alin Panaitiu's reverse-engineering work behind Lunar's BlackOut feature. His blog post — Turn off MacBook display in clamshell mode — identified SLSConfigureDisplayEnabled as the correct private API and explained why it works on Apple Silicon. That was the spark.
The actual implementation patterns, however, are drawn directly from screen_tune by Anton Orlov, an open-source menu bar app using the same private APIs:
- The
CGDisplayConfigRefsignature forSLSConfigureDisplayEnabled(vs. Lunar'sCGSConnectionIDvariant) - The
CGBeginDisplayConfiguration/CGCompleteDisplayConfiguration(.permanently)transaction pattern SLSGetDisplayListfor enumerating all displays including disabled ones — necessary becauseCGGetOnlineDisplayListomits displays that have been turned off viaSLSConfigureDisplayEnabled
Apple's open-source PowerManagement — PMDisplay.m — provided additional context on how macOS itself calls into SkyLight for clamshell mode.
Built with Claude.