Skip to content

Design: display control surface for smctl #15

Description

@harryisfish

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions