Switch Apple display reference modes from Terminal, scripts, or a Stream Deck.
Refmode is a focused macOS command-line tool for discovering, reading, switching, and resetting the factory and custom presets exposed by compatible Apple displays. It is deterministic, script-friendly, and designed to fail safely when the display, session, or underlying macOS API is not suitable for a change.
$ refmode current --display builtin
Apple XDR Display (P3-1600 nits)
$ refmode set --display builtin "Photography (P3-D65)"
Built-in Retina Display: Apple XDR Display (P3-1600 nits) → Photography (P3-D65)Important
macOS does not provide a public API for switching reference presets. Refmode dynamically loads a very small set of undocumented CoreDisplay functions and validates every capability at runtime. Apple may change or remove this interface in any macOS update. Refmode is suitable for source, signed-download, and Homebrew distribution, but not the Mac App Store.
Note
Current qualification status: physical discovery, current-preset lookup, set with positive read-back, factory-default reset, idempotence, and restoration all pass on the documented ARM64 built-in Liquid Retina XDR test machine. Coverage is currently limited to that single-display configuration; see the observed compatibility matrix.
Reference modes affect gamut, white point, transfer function, luminance, and display processing. They are not ColorSync ICC profiles; choose a mode appropriate for the content and viewing environment.
| Feature | Command call | What it does |
|---|---|---|
| Check readiness | refmode doctor |
Reports the GUI session, OS/build, architecture, private API symbols, displays, and mutation readiness without changing anything. |
| Discover displays | refmode displays |
Lists every online display, including unsupported displays, with identity, state, capability, and the active preset when readable. |
| List reference modes | refmode presets --display builtin |
Lists every valid factory or custom preset returned for one display and marks the active preset when readable. |
| Read the current mode | refmode current --display builtin |
Prints the active preset name; verbose and JSON modes expose its preset ID and display UUID when available. |
| Switch by exact name | refmode set --display builtin "Photography (P3-D65)" |
Selects one exact preset name; a real change calls the setter once and requires positive read-back. |
| Switch by stable ID | refmode set --display uuid:<uuid> --preset-id <preset-id> |
Uses durable identifiers recommended for scripts and hardware buttons. |
| Restore the factory preset | refmode reset --display builtin |
Selects the factory-default preset reported by CoreDisplay and verifies it. It does not delete custom modes or reset calibration. |
| Emit machine-readable output | refmode --json displays |
Emits exactly one versioned JSON object and preserves meaningful process exit statuses. |
| Run silently on success | refmode --quiet set ... |
Suppresses successful output while preserving errors and the exit status. |
| Inspect extra detail | refmode --verbose presets ... |
Adds runtime index, default/writable/origin fields, descriptions, and defensive decoding diagnostics. |
| Show help and version | refmode help set / refmode --version |
Shows command-specific examples or the executable version. |
Safety is part of the command contract:
- an already-active request succeeds without calling the setter;
- a real change makes exactly one setter call and then polls for positive read-back;
- changing operations require an active, unmirrored, UUID-backed display;
- display identity and topology are checked immediately before mutation and throughout verification;
- ambiguous displays or presets are rejected instead of choosing the first match;
- custom reference modes work automatically when CoreDisplay reports them as valid;
- no command prompts, opens System Settings, takes focus, uses
sudo, or requires Accessibility, Screen Recording, Automation, Input Monitoring, or network access.
Install the qualified Apple Silicon release from the Homebrew tap:
brew tap totocaster/tap
brew install totocaster/tap/refmode
command -v refmodeThe last command prints the absolute executable path, normally /opt/homebrew/bin/refmode on Apple Silicon. Use that path in GUI automation tools, which often start with a minimal environment.
The initial Homebrew formula supports Apple Silicon on macOS 13 Ventura or later. Intel release artifacts remain gated on physical Intel testing of the private API; an x86_64 cross-build or Rosetta run alone is not treated as native support.
Install Xcode Command Line Tools with Swift 6, then run:
git clone https://github.com/totocaster/refmode.git
cd refmode
swift build
swift test
swift build -c release
install -d "$HOME/.local/bin"
install -m 755 .build/release/refmode "$HOME/.local/bin/refmode"Start with the read-only diagnostic and discover stable identifiers:
refmode doctor
refmode displays
refmode presets --display builtin
refmode current --display builtinSwitch by an exact localized name for interactive use:
refmode set --display builtin "Photography (P3-D65)"For durable automation, copy the display UUID and preset ID printed by displays and presets:
refmode --quiet set \
--display uuid:<display-uuid> \
--preset-id <preset-id>Restore the factory-default preset reported by the display API:
refmode reset --display builtin# Built-in display
refmode current --display builtin
# Main display
refmode presets --display main
# Stable UUID — recommended for automation
refmode current --display uuid:<display-uuid>
# Full localized name
refmode current --display "name:Built-in Retina Display"If --display is omitted, Refmode proceeds only when exactly one active reference-capable display exists. It never silently prefers the built-in or main display when multiple capable displays are connected.
# Exact name
refmode set --display builtin "Internet & Web (sRGB)"
# Stable preset ID
refmode set \
--display uuid:<display-uuid> \
--preset-id 5753ced2-1e19-4de6-a539-01eb59550fc9
# Allow up to five seconds for verified read-back
refmode set --timeout 5 \
--display builtin \
"Photography (P3-D65)"Names are exact, Unicode-normalized matches with a case-insensitive fallback; Refmode never uses substring or fuzzy matching. Preset IDs are safer when a name is localized or user-editable. Runtime preset indices are intentionally not part of the public selection interface.
refmode --json displays
refmode --json current --display uuid:<display-uuid>
refmode --json set --display uuid:<display-uuid> --preset-id <preset-id>Every expected success or failure is one newline-terminated schema-versioned JSON object on stdout. Mutation results include changed, before, after, and verified. The process exit status remains authoritative; --verbose adds diagnostics on stderr without changing JSON stdout.
#!/bin/zsh
REFMODE=/opt/homebrew/bin/refmode
if "$REFMODE" --quiet set \
--display uuid:<display-uuid> \
--preset-id <preset-id>; then
echo "Reference mode ready"
else
status=$?
echo "Refmode failed with status $status" >&2
exit "$status"
fiCreate an executable wrapper such as ~/bin/refmode-photography.sh:
#!/bin/zsh
exec /opt/homebrew/bin/refmode --quiet set \
--display uuid:<display-uuid> \
--preset-id <preset-id>chmod +x "$HOME/bin/refmode-photography.sh"Assign the wrapper to Elgato Stream Deck’s System → Open action, or invoke the absolute command from a shell-command action. See Stream Deck and trigger integration for feedback handling and other launchers.
refmode [global-options] <command> [command-options]
| Command | Purpose | Command options |
|---|---|---|
displays |
List all online displays and capability | None |
presets |
List valid presets for one display | --display <selector> |
current |
Show the active preset for one display | --display <selector> |
set <exact-name> |
Select a preset by exact name | --display <selector>, --timeout <seconds> |
set --preset-id <id> |
Select a preset by stable ID | --display <selector>, --timeout <seconds> |
reset |
Select CoreDisplay’s factory-default preset | --display <selector>, --timeout <seconds> |
doctor |
Run read-only environment diagnostics | None |
help [command] |
Show root or command-specific help | None |
--timeout accepts 0.1 through 30 seconds and defaults to 3.0.
| Option | Behavior |
|---|---|
--json |
Emit the stable JSON envelope |
-q, --quiet |
Suppress normal success output |
-v, --verbose |
Emit additional human detail and stderr diagnostics |
--no-color |
Disable ANSI styling; the NO_COLOR convention is also honored |
-h, --help |
Show help |
--version |
Show the executable version |
Global options may appear before or after the subcommand. --json and --quiet are mutually exclusive.
| Selector | Meaning | Automation guidance |
|---|---|---|
builtin |
The built-in display | Convenient when the machine has one built-in panel |
main |
The current Core Graphics main display | Can change as topology changes |
uuid:<canonical-uuid> |
Stable Core Graphics display UUID | Recommended |
serial:<unsigned-decimal> |
Display serial number | May be absent or duplicated |
name:<full-localized-name> |
Full display name | Localized and potentially duplicated |
id:<decimal-runtime-id> |
Current CGDirectDisplayID |
Diagnostic only; unstable across hot-plugging |
Bare names, serials, and UUIDs are not accepted. Read commands can inspect mirrored or UUID-less displays, but a changing set or reset requires a stable UUID and rejects mirror leaders and followers before the setter is called.
Human success output goes to stdout. Human errors and verbose diagnostics go to stderr. Quiet mode suppresses successful stdout only; it never hides errors.
| Exit | Symbolic code | Meaning |
|---|---|---|
| 0 | success |
Command completed |
| 1 | internal_error |
Unexpected internal failure |
| 2 | usage_error |
Invalid arguments or option combination |
| 3 | api_unavailable |
CoreDisplay framework, symbol, or API mismatch |
| 4 | display_not_found |
Selector matched no online display |
| 5 | display_ambiguous |
Selector or default matched multiple displays |
| 6 | display_unsupported |
Display has no usable reference presets |
| 7 | display_unavailable |
Display is inactive, sleeping, or unsafe to change |
| 8 | preset_not_found |
No valid preset matched |
| 9 | preset_ambiguous |
More than one valid preset matched |
| 10 | switch_rejected |
CoreDisplay rejected the setter call |
| 11 | verification_failed |
Read-back did not confirm the requested preset |
| 12 | gui_session_unavailable |
No usable WindowServer session |
| 13 | mirrored_unsupported |
Target belongs to a mirror set |
| 14 | topology_changed |
Target identity or topology changed during verification |
Refmode requires:
- macOS 13 Ventura or later;
- an active WindowServer GUI session owned by the invoking user;
- a display for which CoreDisplay returns at least one well-formed valid preset;
- a stable display UUID for any operation that would change a preset.
Support is capability-based rather than hardcoded to model names. Compatible hardware is expected to include supported Liquid Retina XDR MacBook Pro displays, Studio Display, Studio Display XDR, and Pro Display XDR. Check your actual environment with refmode doctor and consult the physically observed private API compatibility matrix.
Refmode deliberately does not create, edit, or delete presets; assign ICC profiles; control third-party DDC modes; change brightness, resolution, refresh rate, HDR, True Tone, or Night Shift; run a daemon or menu-bar app; or bundle a Stream Deck plugin. Version 1 provides the reliable CLI integration surface for those automation tools.
System LaunchDaemons, pre-login processes, sudo, and SSH-only sessions do not share the logged-in user’s display session and are unsupported. A user LaunchAgent inside the active GUI session may work.
swift build
swift test
swift build -c release
./Scripts/release/self-test.shThe ordinary test suite never changes a real display. Physical mutation tests require an explicit REFMODE_RUN_MUTATING_TESTS=1 opt-in and restoration safeguards. See Releasing Refmode for hardware gates, signing/notarization, release archives, and Homebrew tap automation.
The private boundary is isolated in Sources/RefmodeCore/CoreDisplaySPI.swift; CoreDisplay is dynamically loaded rather than statically linked. Domain rules, public display discovery, private dictionary decoding, CLI rendering, and the executable composition root remain independently testable.
- Private CoreDisplay API and compatibility
- Stream Deck and trigger integration
- Release process
- Implementation specification
Refmode is available under the MIT License.
Copyright © 2026 Tornike (Toto) Tvalavadze and Refmode Contributors.