Fully disables the MacBook built-in display while keeping the lid open — not a backlight dim, but a real disconnect from WindowServer compositing. The GPU stops rendering to it entirely.
Uses private SkyLight.framework APIs resolved at runtime via dlsym. No SIP disable required.
- macOS 13 (Ventura) or later — Apple Silicon or Intel
- At least one external display connected (safety guard)
- Xcode Command Line Tools:
xcode-select --install
make build # compile release binary → .build/release/display-toggle
sudo make install # copy to /usr/local/bin/display-toggle
make uninstall # remove from /usr/local/bin/To build a universal (arm64 + x86_64) binary:
swift build -c release --arch arm64 --arch x86_64
# binary: .build/apple/Products/Release/display-toggle
sudo cp .build/apple/Products/Release/display-toggle /usr/local/bin/SUBCOMMANDS:
list List all connected displays with IDs, resolutions, and status
status Show whether the built-in display is currently enabled or disabled
on Enable the built-in display
off Disable the built-in display (frees GPU from rendering it)
toggle Toggle: disable if enabled, enable if disabled
# See all displays
display-toggle list
# Display 1: Built-in Retina 2560x1600 ID: 69732928 [ENABLED]
# Display 2: External 2560x1440 ID: 724042646 [ENABLED]
# Current state
display-toggle status
# Disable (5-second countdown → Ctrl+C to cancel)
display-toggle off
# Disable immediately, auto-revert in 15 s unless you press Enter
display-toggle off --timeout 15
# Disable immediately, no countdown, no revert
display-toggle off --force
# Re-enable
display-toggle on
# Toggle (bind this to a hotkey)
display-toggle toggle
# Toggle with auto-revert safety net
display-toggle toggle --timeout 10
# Verbose: prints display IDs, symbol resolution, connection ID
display-toggle list --verbose- External display required:
off/toggle-offrefuse to run if no external display is active (exit code 2). Override with--force. - 5-second countdown: gives you time to Ctrl+C before the display goes dark. Skip with
--force. - SIGINT / SIGTERM handlers: if you Ctrl+C during the
--timeoutcountdown, the display re-enables before exit. - SIGKILL: cannot be caught. If the process is force-killed mid-operation the display stays off. Run
display-toggle onfrom another terminal, or restart WindowServer (sudo killall -KILL WindowServer).
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error (symbol not found, API failure, no built-in display, …) |
| 2 | No external display found |
Bind to a hotkey via Shortcuts.app:
- Open Shortcuts → New Shortcut
- Add action Run Shell Script:
/usr/local/bin/display-toggle toggle --force - Settings → Keyboard Shortcut → assign e.g. ⌃⌥⌘B
Or via Automator (Service → Run Shell Script), then bind in System Settings → Keyboard → Shortcuts → Services.
macOS WindowServer (via the private CGS / SkyLight layer) tracks which displays are enabled for compositing. The public CoreGraphics API lets you enumerate and query displays but not disable them. The private CGSConfigureDisplayEnabled(connectionID, displayID, false) function removes the display from the compositor entirely — windows that were on it migrate to the primary display.
The symbol is resolved at runtime from SkyLight.framework using dlsym, falling through these candidates in order:
CGSConfigureDisplayEnabled— macOS 13–15 (primary)CGSSetDisplayEnabled— earlier macOS fallbackSLSConfigureDisplayEnabled— SkyLight-prefixed variant
If none resolves, the tool prints the nm command to inspect your system's available symbols.
"Private API symbol not found"
Run the suggested nm command to see what's available on your macOS version:
nm /System/Library/PrivateFrameworks/SkyLight.framework/SkyLight \
| grep -iE "display|enabled"If you find a different symbol name, add it to the candidates array in main.swift.
Display stays off after crash / SIGKILL
display-toggle on
# or, if the binary is inaccessible:
sudo killall -KILL WindowServer # restarts the entire display session — all apps relaunchGPU usage didn't drop
Verify the display is actually disabled:
display-toggle status
# Built-in display (ID: 69732928): DISABLEDIf still ENABLED, the private API call succeeded with code 0 but WindowServer ignored it — this can happen on newer macOS versions that changed the internal semantics. Check --verbose output and open an issue with your macOS version.
| macOS | Status |
|---|---|
| 15 Sequoia | Expected to work (CGSConfigureDisplayEnabled present) |
| 14 Sonoma | Expected to work |
| 13 Ventura | Primary target, tested path |
| 12 Monterey | May work; minimum deployment target is 13 |
This utility uses private APIs. Apple may rename or remove them at any time.