Problem
External displays are part of System Control, but macOS exposes weak hardware control for third-party monitors. Users need scriptable brightness, contrast, volume, input switching, and a reliable way to diagnose why control is unavailable.
BetterDisplay already owns the broad GUI/display-experience space. smctl should not clone BetterDisplay. The useful smctl scope is external-display hardware control plus CLI-first diagnostics.
Research PR: #14
Research doc: docs/research-display-control.md
Proposed scope
Start with a read-only surface:
smctl display list --json
smctl display status
smctl display edid --display <id>
smctl display capabilities --display <id>
smctl display doctor
Then add safe hardware controls:
smctl display brightness get/set --display <id>
smctl display contrast get/set --display <id>
smctl display volume get/set --display <id>
smctl display input list/get/set --display <id>
Non-goals
- BetterDisplay clone
- GUI-first display settings app
- virtual displays
- PIP/PBP/KVM
- custom EDID or EDID override
- HDR/XDR extra brightness
- display mode/resolution writes in the first implementation
- silently falling back from hardware brightness to software dimming
Design requirements
- Enumerate displays with stable identity, not only display name.
- Combine CoreGraphics state, IOKit/IODisplay identity, EDID hash, and DDC capability results.
- Report a DDC capability matrix before exposing writes.
- Distinguish unsupported, blocked, timeout, broken-read, unverified-write, and verified-write states.
- Map common input names like
hdmi1, hdmi2, dp1, dp2, and usb_c, while allowing per-display aliases.
- Avoid default writes to an ambiguous display when multiple external monitors are connected.
- Keep software dimming visibly separate from hardware brightness.
- Decide whether DDC read/write belongs in the CLI process, the daemon, or a split model.
Open questions
- Should the first implementation be Apple Silicon only, or should Intel be included if DDC transport is portable?
- Which Swift DDC transport path is most stable on current macOS?
- How should smctl identify Apple Studio Display, LG UltraFine, built-in panels, and other native/Apple-protocol displays?
- What should
--no-verify mean for displays that apply writes but return unreliable MCCS data?
- Where should display aliases live:
/etc/smctl/config.toml, per-user config, or both?
- Should compatibility reporting exist, and if so how does it stay default-off and privacy-preserving?
Acceptance criteria for the design pass
- A command contract for V0 read-only inventory and doctor output.
- A JSON schema sketch for display identity, EDID, transport, and DDC capability state.
- A decision on CLI vs daemon ownership for DDC probing and writes.
- A safety model for write verification and degraded states.
- A small hardware test matrix that covers direct USB-C/DisplayPort, HDMI, docked monitors, DisplayLink, and at least one unsupported display path.
Problem
External displays are part of System Control, but macOS exposes weak hardware control for third-party monitors. Users need scriptable brightness, contrast, volume, input switching, and a reliable way to diagnose why control is unavailable.
BetterDisplay already owns the broad GUI/display-experience space. smctl should not clone BetterDisplay. The useful smctl scope is external-display hardware control plus CLI-first diagnostics.
Research PR: #14
Research doc:
docs/research-display-control.mdProposed scope
Start with a read-only surface:
smctl display list --jsonsmctl display statussmctl display edid --display <id>smctl display capabilities --display <id>smctl display doctorThen add safe hardware controls:
smctl display brightness get/set --display <id>smctl display contrast get/set --display <id>smctl display volume get/set --display <id>smctl display input list/get/set --display <id>Non-goals
Design requirements
hdmi1,hdmi2,dp1,dp2, andusb_c, while allowing per-display aliases.Open questions
--no-verifymean for displays that apply writes but return unreliable MCCS data?/etc/smctl/config.toml, per-user config, or both?Acceptance criteria for the design pass