Skill: oakland/mac-display-control (version 1.0.0)

--- name: mac-monitor-brightness-control description: > Step-by-step guide for controlling external display or monitor settings on a Mac without third-party GUI apps. Covers Apple Silicon and Intel Macs, all major display brands (LG, Dell, BenQ, Samsung, ASUS, etc.), all connection types (USB-C, DisplayPort, HDMI, DVI), and a software fallback for displays that don't support DDC/CI. Controls include brightness, contrast, volume, input source switching, color temperature, power, and more. Use this skill whenever a user wants to control external display brightness, volume, contrast, color, input, or any other setting via the command line or keyboard shortcuts on macOS. --- # External Display Control on macOS (No Third-Party GUI Apps) ## Overview macOS doesn't natively expose controls for third-party displays, but most modern displays support **DDC/CI** — a protocol that lets software send commands directly to display hardware: brightness, contrast, volume, input source, color temperature, power, and more. **This skill is split into a setup section (below) and per-control reference files.** Once set up, jump to the reference file for the control you need. ### Reference Files (read after setup) | File | Controls covered | |---|---| | `references/brightness.md` | Brightness — scripts, keyboard shortcuts, cron presets | | `references/contrast.md` | Contrast — tips for color-mode lock | | `references/volume.md` | Display speaker volume, mute toggle | | `references/input-source.md` | Input switching, KVM setup, per-brand codes | | `references/color-temperature.md` | Color presets, RGB gain, night/day mode scripts | | `references/power-and-misc.md` | Power on/off, rotation, factory reset, capability probing | --- ## Step 0 — Identify Your Setup ### What Mac chip? ```bash uname -m # arm64 = Apple Silicon | x86_64 = Intel ``` Or: Apple menu → About This Mac. ### How is your display connected? | Cable | Apple Silicon | Intel | |---|---|---| | **USB-C / Thunderbolt** | ✅ Full DDC support | ✅ Full DDC support | | **DisplayPort** | ✅ Works | ✅ Works | | **HDMI (built-in port)** | ⚠️ Blocked on M1/M2 Mac Mini, M1 MBP, Mac Studio | ✅ Works | | **HDMI via Thunderbolt adapter** | ✅ Usually works | ✅ Works | | **DisplayLink dock** | ❌ No DDC | ❌ No DDC | > If you're on Apple Silicon with HDMI and can't switch cables → jump to **Software Fallback**. --- ## Step 1 — Install the Right Tool ### Apple Silicon → `m1ddc` ```bash brew install m1ddc m1ddc display list # your display should appear here ``` ### Intel → `ddcctl` ```bash brew install ddcctl ddcctl -d 1 -p 1 # probe display 1 — lists supported controls ``` > **Homebrew not installed?** > ```bash > /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" > ``` --- ## Step 2 — Quick Smoke Test Verify DDC is working before scripting anything: ```bash # Apple Silicon m1ddc set luminance 30 # screen should visibly dim m1ddc set luminance 80 # screen should brighten # Intel ddcctl -d 1 -b 30 ddcctl -d 1 -b 80 ``` No change? → See **Software Fallback** below. Multiple displays? Target a specific one: ```bash m1ddc display list # find index m1ddc display 2 set luminance 60 ddcctl -d 2 -b 60 # Intel equivalent ``` --- ## Step 3 — Set Up Shell Scripts All controls work as one-line shell commands. Create a `~/scripts/` folder and save scripts there so Automator, cron, and keyboard shortcuts can call them. ```bash mkdir -p ~/scripts ``` Always use **full binary paths** in scripts — Automator and cron don't load your shell PATH: - Apple Silicon: `/opt/homebrew/bin/m1ddc` - Intel: `/usr/local/bin/ddcctl` **See each `references/*.md` file for ready-to-paste scripts per control.** Make scripts executable after creating them: ```bash chmod +x ~/scripts/*.sh ``` --- ## Step 4 — Keyboard Shortcuts (Automator) Works for any script. Do this once per action you want to bind to a key. 1. Open **Automator** → New Document → **Quick Action** 2. "Workflow receives" → **no input** in **any application** 3. Add **Run Shell Script** → paste the full script path (e.g. `/Users/yourname/scripts/brightness-up.sh`) 4. Save as e.g. **Brightness Up** 5. **System Settings → Keyboard → Keyboard Shortcuts → Services → General** 6. Find your Quick Action → assign a shortcut (e.g. `⌃⌥↑`) > If the shortcut doesn't fire: System Settings → Privacy & Security → Automation → grant access. --- ## Step 5 — Time-Based Presets (Optional) Use cron to switch display settings automatically at certain times: ```bash crontab -e ``` ``` # Day mode at 8am 0 8 * * * /Users/yourname/scripts/day-mode.sh # Night mode at 9pm 0 21 * * * /Users/yourname/scripts/night-mode.sh ``` See `references/color-temperature.md` for ready-made day/night scripts. --- ## Software Fallback (No DDC Support) If your display doesn't respond to DDC (TVs, budget displays, DisplayLink docks), use macOS **Gamma table control** to dim the image in software: ```bash # Set brightness to 60% (range: 0.0–1.0) osascript -e 'tell application "System Events" to set brightness of (first screen of (get every screen)) to 0.6' ``` As a script (`~/scripts/brightness-soft.sh`): ```bash #!/bin/bash # Usage: brightness-soft.sh 0.6 osascript -e "tell application \"System Events\" to set brightness of (first screen of (get every screen)) to ${1:-0.7}" ``` > ⚠️ Software dimming changes appearance only — no power saving, slight colour shift at > low values. Hardware DDC is always preferable when available. --- ## Troubleshooting | Symptom | Fix | |---|---| | `m1ddc display list` returns nothing | Must use USB-C; HDMI blocked on M1/M2 Mac Mini | | Display found but control has no effect | DDC/CI may be off in OSD; or Dynamic Contrast is on | | Wrong display changes | Use `m1ddc display 2 …` or `ddcctl -d 2 …` | | Command not found in Quick Action | Use full path: `/opt/homebrew/bin/m1ddc` | | Shortcut doesn't fire | System Settings → Privacy & Security → Automation | | No DDC at all | Use Software Fallback (osascript gamma) | --- ## References - `m1ddc` (Apple Silicon): https://github.com/waydabber/m1ddc - `ddcctl` (Intel): https://github.com/kfix/ddcctl - DDC/CI HDMI block on Apple Silicon: https://github.com/MonitorControl/MonitorControl#readme

path: references/pow-and-misc.md
content: # Power & Miscellaneous Controls

## Display Power (VCP `0xD6`)

Turn the display panel on/off without cutting power to the device.

### Apple Silicon (m1ddc)
```bash
m1ddc set poweron 1           # wake / turn on
m1ddc set poweron 4           # standby (panel off, responds to signal)
m1ddc set poweron 5           # power off
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -o 1              # power on
ddcctl -d 1 -o 4              # standby
ddcctl -d 1 -o 5              # power off
```

**Use case**: Script a "presentation mode" that turns off a secondary display when idle,
or wake it on demand without touching the physical button.

---

## Screen Orientation / Rotation (VCP `0xAA`)

| Value | Orientation |
|---|---|
| 1  | 0° (landscape) |
| 2  | 90° (portrait, rotated right) |
| 4  | 270° (portrait, rotated left) |

### Apple Silicon (m1ddc)
```bash
m1ddc get orientation
m1ddc set orientation 2       # rotate to portrait
m1ddc set orientation 1       # back to landscape
```

> ⚠️ Not all displays support software rotation via DDC. Most rely on the physical stand
> and macOS display settings instead. Try it — if no response, use System Settings → Displays → Rotation.

---

## OSD Language (VCP `0xCC`)

Change the language of the on-screen display menu.

```bash
m1ddc set osdlang 2           # English (common value; varies by brand)
```

---

## Restore Factory Defaults (VCP `0x04`)

Resets all display settings to factory state.

### Apple Silicon (m1ddc)
```bash
m1ddc set reset 1
```

### Intel (ddcctl)
```bash
ddcctl -d 1 --set-vcp 0x04 1
```

> ⚠️ This resets **everything** — brightness, contrast, color, input preferences.
> Use with caution. There is no undo.

---

## Discover All Supported Controls

Every display implements a different subset of DDC. Before scripting anything advanced,
probe what your display actually supports:

### Apple Silicon (m1ddc)
```bash
m1ddc display list
# m1ddc doesn't have a full capability dump; test controls individually
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -p 1              # probe and print all supported VCP codes
```

This output tells you exactly which VCP codes work on your specific display.

path: references/volume.md
content: # Volume Control (Built-in Display Speakers)

VCP code: `0x62` | Range: 0–100

Controls the audio output volume of a display's built-in speakers.
Only relevant if your display has built-in speakers AND you're using them as the audio output.

## Commands

### Apple Silicon (m1ddc)
```bash
m1ddc get volume              # read current value
m1ddc set volume 50           # set to 50
m1ddc chg volume +10          # increase by 10
m1ddc chg volume -10          # decrease by 10
m1ddc set volume 0            # mute
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -v ?              # read current value
ddcctl -d 1 -v 50             # set to 50
```

## Mute Toggle Script

**~/scripts/display-mute-toggle.sh** (Apple Silicon)
```bash
#!/bin/bash
CURRENT=$(/opt/homebrew/bin/m1ddc get volume 2>&1 | grep -o '[0-9]*' | head -1)
if [ "$CURRENT" -gt 0 ]; then
  echo $CURRENT > /tmp/display_last_volume
  /opt/homebrew/bin/m1ddc set volume 0
else
  LAST=$(cat /tmp/display_last_volume 2>/dev/null || echo 50)
  /opt/homebrew/bin/m1ddc set volume $LAST
fi
```

## Tips

- This only works for the display's own speakers, not headphones or USB audio.
- If macOS audio output is set to a different device (e.g. Mac's speakers), this has no effect.
- Many users prefer controlling volume via macOS system audio — use DDC volume only if
  you specifically want to control the display speakers independently.

path: references/color-temperature.md
content: # Color Temperature & Color Presets

## Color Preset (VCP `0x14`) — Most Common Approach

Switches between named presets like sRGB, Warm, Cool, User.
This is the easiest way to change the "warmth" of the display.

### Standard Preset Values

| Value | Preset |
|---|---|
| 0x01 | sRGB |
| 0x04 | 5000 K (warm/paper white) |
| 0x05 | 6500 K (daylight — default for most displays) |
| 0x06 | 7500 K |
| 0x07 | 8200 K |
| 0x08 | 9300 K (cool/blue) |
| 0x0B | User 1 (custom) |
| 0x0C | User 2 (custom) |

> Values vary by display brand. Probe yours: `m1ddc get colorpreset` or check OSD presets.

### Apple Silicon (m1ddc)
```bash
m1ddc get colorpreset             # read current preset
m1ddc set colorpreset 5           # set to 6500K (daylight)
m1ddc set colorpreset 4           # set to 5000K (warm/night)
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -m ?                  # read current preset
ddcctl -d 1 -m 5                  # set to 6500K
ddcctl -d 1 -m 4                  # set to warm
```

---

## RGB Gain (VCP `0x16`, `0x18`, `0x1A`) — Fine Colour Tuning

Adjusts Red, Green, Blue channels independently (0–100 each).
Useful for reducing blue light manually without Night Shift.

### Apple Silicon (m1ddc)
```bash
m1ddc set redgain 90
m1ddc set greengain 85
m1ddc set bluegain 70     # reduce blue for warmer, night-friendly image
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -rg 90        # red gain
ddcctl -d 1 -gg 85        # green gain
ddcctl -d 1 -bg 70        # blue gain
```

---

## Night Mode Script (Warm + Dim)

Combines brightness reduction and blue reduction for comfortable evening use.

**~/scripts/night-mode.sh** (Apple Silicon)
```bash
#!/bin/bash
/opt/homebrew/bin/m1ddc set luminance 30
/opt/homebrew/bin/m1ddc set bluegain 65
/opt/homebrew/bin/m1ddc set greengain 85
/opt/homebrew/bin/m1ddc set redgain 95
```

**~/scripts/day-mode.sh** (Apple Silicon)
```bash
#!/bin/bash
/opt/homebrew/bin/m1ddc set luminance 80
/opt/homebrew/bin/m1ddc set bluegain 100
/opt/homebrew/bin/m1ddc set greengain 100
/opt/homebrew/bin/m1ddc set redgain 100
```

## Tips

- macOS **Night Shift** already does software blue-light filtering — DDC RGB gain does it
  in hardware, which is more effective and doesn't affect color-critical work.
- ⚠️ RGB gain only works when OSD color mode is set to "Custom" / "User". sRGB mode
  locks these values.
- Changes persist across power cycles (stored in display firmware).

path: references/contrast.md
content: # Contrast Control

VCP code: `0x12` | Range: 0–100

Contrast controls the difference between light and dark areas. Most displays ship at 50–75.
Lowering contrast can reduce eye strain; raising it makes text pop on bright content.

## Commands

### Apple Silicon (m1ddc)
```bash
m1ddc get contrast            # read current value
m1ddc set contrast 60         # set to 60
m1ddc chg contrast +5         # increase by 5
m1ddc chg contrast -5         # decrease by 5
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -c ?              # read current value
ddcctl -d 1 -c 60             # set to 60
```

## Tips

- ⚠️ Some displays lock contrast when a color preset (sRGB, Movie, etc.) is active.
  Switch OSD to "Custom" / "User" color mode first.
- Contrast is less often scripted than brightness, but useful for switching between
  coding (lower) and media watching (higher) modes.
- Typical comfortable range: 50–70 for everyday use.

path: references/input-source.md
content: # Input Source Switching

VCP code: `0x60` | Type: Non-continuous (enum)

Switches the active input on your display — e.g. from HDMI to DisplayPort.
Useful if you share a display between two computers.

## Standard Input Source Values

| Value (decimal) | Value (hex) | Input |
|---|---|---|
| 1  | 0x01 | VGA-1 |
| 2  | 0x02 | VGA-2 |
| 3  | 0x03 | DVI-1 |
| 4  | 0x04 | DVI-2 |
| 15 | 0x0F | DisplayPort-1 |
| 16 | 0x10 | DisplayPort-2 |
| 17 | 0x11 | HDMI-1 |
| 18 | 0x12 | HDMI-2 |
| 27 | 0x1B | USB-C / Thunderbolt |

> ⚠️ These are standard MCCS values, but **displays often use non-standard codes**.
> Always probe your specific display first (see below).

## Probe Your Display's Input Codes

### Apple Silicon (m1ddc)
```bash
m1ddc get input               # read current input code
```

Then try switching and reading again to discover which codes your display uses.

### Intel (ddcctl)
```bash
ddcctl -d 1 -i ?              # read current input source
ddcctl -d 1 --get-input-source  # alternative on some versions
```

## Switch Input Commands

### Apple Silicon (m1ddc)
```bash
m1ddc set input 15            # switch to DisplayPort-1
m1ddc set input 17            # switch to HDMI-1
m1ddc set input 27            # switch to USB-C
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -i 15             # switch to DisplayPort-1
ddcctl -d 1 -i 17             # switch to HDMI-1
```

## Two-Computer KVM Script

If you share a display between two Macs (or a Mac and a PC), script the switch:

**~/scripts/switch-to-mac.sh**
```bash
#!/bin/bash
# Switch display to USB-C (Mac Mini)
/opt/homebrew/bin/m1ddc set input 27
```

**~/scripts/switch-to-pc.sh**
```bash
#!/bin/bash
# Switch display to HDMI (PC)
/opt/homebrew/bin/m1ddc set input 17
```

## Tips

- ⚠️ Some displays only accept input-switch commands from the **currently active input**.
  If the command seems ignored, you may need to send it from the source you're switching *from*.
- After switching, the display may take 2–5 seconds to detect the new signal.
- Input codes vary by brand. LG, Dell, BenQ all use slightly different values.
  Always verify with `m1ddc get input` before scripting.

path: references/brightness.md
content: # Brightness Control

VCP code: `0x10` | Range: 0–100

## Commands

### Apple Silicon (m1ddc)
```bash
m1ddc get luminance           # read current value
m1ddc set luminance 70        # set to 70
m1ddc chg luminance +10       # increase by 10
m1ddc chg luminance -10       # decrease by 10
```

### Intel (ddcctl)
```bash
ddcctl -d 1 -b ?              # read current value
ddcctl -d 1 -b 70             # set to 70
```

## Shell Scripts

**~/scripts/brightness-up.sh** (Apple Silicon)
```bash
#!/bin/bash
/opt/homebrew/bin/m1ddc chg luminance +10
```

**~/scripts/brightness-up.sh** (Intel)
```bash
#!/bin/bash
CURRENT=$(/usr/local/bin/ddcctl -d 1 -b ? 2>&1 | grep -o 'current: [0-9]*' | awk '{print $2}')
/usr/local/bin/ddcctl -d 1 -b $((CURRENT + 10))
```

**~/scripts/brightness-set.sh** (both — change tool as needed)
```bash
#!/bin/bash
# Usage: brightness-set.sh 70
/opt/homebrew/bin/m1ddc set luminance "${1:-50}"
```

## Tips

- Good daytime range: 70–100. Night range: 20–50.
- Combine with time-based cron presets (see SKILL.md Step 6).
- If brightness doesn't respond, Dynamic Contrast (DCR) may be enabled in OSD — disable it.

Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)