CLI tool
waydabber/m1ddc avatar
waydabber/m1ddc

m1ddc drives external display brightness from the command line

This little tool controls external displays (connected via USB-C/DisplayPort Alt Mode) using DDC/CI on Apple Silicon Macs. Useful to embed in various scripts.

749 stars70 forksObjective-CMIT

At a glance

What is it?
m1ddc is a small Objective-C command line tool that sends DDC/CI commands to external displays attached to an Apple Silicon Mac, so brightness, contrast, volume and input switching can be scripted. The limits are equally clear: Apple Silicon only, and a fixed set of VCP codes that only some display models implement.
Who is it for?
m1ddc suits someone scripting their desk setup on an Apple Silicon Mac, where brightness, contrast, colour gain or input switching needs to follow something else, such as a Hammerspoon script reacting to keyboard media keys. It does not suit an Intel Mac, since the README states the tool does not support them, and it does not suit a display whose vendor ignores DDC/CI, where the get commands simply report that the value is unsupported.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 82 days ago.
What is it written in?
Mainly Objective-C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

DDC/CI over Apple Silicon, without a display driver

The problem is that a modern Mac gives you almost no control over an external display's picture settings. The native display controls in macOS cover the built-in panel, and third party tools exist, but the scripting route has usually meant a larger application. m1ddc is the small version of that: a command line tool that controls external displays using DDC/CI, the Display Data Channel over Control and Instrumentation, a protocol built into most monitors and TVs so they can be adjusted from a computer. The README is specific about the hardware it covers, saying it works on Apple Silicon Macs including displays connected through USB-C with DisplayPort Alt Mode and supported built-in HDMI ports. That last qualifier, supported built-in HDMI ports, is doing real work in the sentence, since not every port on every machine passes DDC/CI through. The build and the run are each one command:

shell
make
shell
./m1ddc [options]

Apple Silicon only, and the README says so in a warning

There is a warning box early in the README, and its content decides who can use this. The tool does not support Intel Macs, and the README points to BetterDisplay for free DDC control on all Macs and all ports. That is an unusual admission for a project README, and it tells you something about the mechanism: on Apple Silicon, the display stack exposes an interface that lets a program reach the DDC path, and on Intel Macs it does not, or at least not in a way this tool could use. The same paragraph recommends BetterDisplay's CLI capabilities as a much more advanced solution. So the honest framing is that m1ddc is a minimal scriptable front end for a specific hardware combination, and the same author maintains the fuller tool. If you want one command to set the brightness, this is that. If you want a full display control application, the README is directing you elsewhere.

Building is make, and clang is the only prerequisite

The build is a Makefile and nothing else, and the prerequisite list is short. The README notes that you need clang from Apple's Command Line Tools, and that it installs automatically if not present. After downloading, you enter make in Terminal, and then you run the resulting binary as ./m1ddc with options. The Makefile in the repository confirms the shape of the project. The name is m1ddc, the compiler is clang, and the flags are -Wall -Werror -Wextra with -fmodules, which is what Objective-C needs for its module support:

makefile
# -- VARIABLES

# Project name
NAME =		m1ddc
LIB = 		lib$(NAME)

# Compiler
CC =		clang
CFLAGS =	-Wall -Werror -Wextra -fmodules
CPPFLAGS =	-I $(INC_DIR)
DEPFLAGS =	-MMD

# Libraries

The library line is the interesting one for anyone trying to reuse the code, because it links against the CoreDisplay framework, which is the piece of the system that exposes the display stack. The Makefile also builds a static library and a combined header from the two non-binary sources, i2c and ioregistry, which is what the separate AppleSiliconDDC project is described as being.

The command shape is set, get, max and chg

The command surface follows a regular grammar, and once you see it the reference becomes obvious. There are four verbs. set takes a property and a number. get returns the current value of a property. max returns the maximum value of a property, which is usually 100 for luminance, contrast, the colour channel gains and volume. chg changes a property by a signed amount rather than to an absolute value, and the reference is explicit that chg requires both current value and maximum value reading support. The properties are luminance, which is the display's brightness, contrast, the red, green and blue channel gains, volume, and input, which selects the source. There is also input-alt for the alternate VCP code used by some LG displays, and mute with on and off, where 1 means on and 2 means off.

get and chg fail quietly on displays that do not implement the code

The failure mode to design around is that DDC/CI is a negotiation. A display that does not implement a given VCP code simply does not answer that query, and the reference marks most of the read commands with the note that the value is returned if supported by the display. That qualifier appears on get, on max, and on chg, which the reference says requires current and maximum value reading support. The practical consequence is that a script that assumes m1ddc get luminance always prints a number will break on a display that ignores the code, and the fix is to check the exit status rather than the output. The other half of the problem is display model variation, which the reference handles by listing VCP values for particular vendors. The picture-in-picture and KVM commands, for instance, are documented as working on certain Dell displays such as the U3421W, and the asus-kvm command on certain ASUS displays such as the XG27UCDMG with Auto KVM disabled.

Selecting a display by number, UUID or EDID

With more than one display attached, a command has to say which one it means, and m1ddc offers several ways to identify a display, described as identification methods with a default of uuid. The methods are id, which is the display_id, uuid, the system_uuid, edid, the edid_uuid, seid, which combines an alphanumeric serial with the edid_uuid, basic, which is vendor, model and serial, ext, which adds the manufacturer, alphanumeric serial and product name, and full, which adds the io_location as well. The method is passed as method=value, so a command can name a display by any of these strings. This matters for scripts, because display list numbers change when you unplug something, while a UUID does not. The README also points out that the attributes behind these identifiers can be printed with the display list detailed command, which is how you find the value to hard-code.

The script example drives volume and brightness from media keys

The intended use is a script, and the README points at a concrete one. The example is a Hammerspoon script that controls the volume, brightness and contrast of an external display over DDC using m1ddc, and also controls a Yamaha AV receiver over the network, and it listens for the standard Apple keyboard media keys while showing the standard macOS brightness and volume overlays through a separate utility. The link to that script is a gist, not a file in the repository. The shape is worth understanding because it shows what the tool is for. The media keys are already handled by macOS, so the script intercepts them and reissues them to the external display through m1ddc, and the overlay is shown separately so the user still sees feedback. That is a composition of a small command line tool with a hotkey daemon and an overlay utility, and it is the reason m1ddc is described as useful to embed in various scripts rather than as a standalone display app.

The licence is MIT, the versions are old, and the code is small

The project is MIT licensed, with the licence file at the root, and the repository is small: a .gitignore, a LICENSE, a Makefile, the README, a headers directory and a sources directory. The source language is Objective-C, and the Makefile builds three source units, i2c, ioregistry and m1ddc, where the first two are compiled into a reusable static library and the third is the command line front end. That split is why the README can point at a complete self-contained library, AppleSiliconDDC, as a separate project. On the release side, the tagged versions are v1.0.0 from 2023-01-09, v1.1.0 from 2023-10-31 and v1.2.0 from 2024-01-10, while the last push to the repository was on 2026-08-02. The gap between the newest tag and the last commit is worth noting, and the README does not document a release policy or a rollback path, so treat the tagged build as the version to pin.

Editorial conclusion

m1ddc suits someone scripting their desk setup on an Apple Silicon Mac, where brightness, contrast, colour gain or input switching needs to follow something else, such as a Hammerspoon script reacting to keyboard media keys. It does not suit an Intel Mac, since the README states the tool does not support them, and it does not suit a display whose vendor ignores DDC/CI, where the get commands simply report that the value is unsupported. Before adopting, run m1ddc display list to confirm the display answers DDC/CI at all, check the model against the VCP values in the command reference, and note that the last push to the repository was on 2026-08-02 with the newest tagged release v1.2.0 from 2024-01-10.

Frequently asked questions

How do I build and run m1ddc?

Run `make` in the repository directory, then run the binary as `./m1ddc [options]`. The only prerequisite is clang from Apple's Command Line Tools, which the README notes installs automatically if it is not present.

Does m1ddc work on Intel Macs?

No. The README carries a warning that the tool does not support Intel Macs, and points to BetterDisplay for free DDC control on all Macs and all ports. m1ddc targets Apple Silicon, including displays connected through USB-C with DisplayPort Alt Mode and supported built-in HDMI ports.

How do I set the brightness of an external display with m1ddc?

Use the set command with luminance and a value, for example `m1ddc set luminance 5` for the default display, or `m1ddc display 1 set luminance 5` to target a display by its list number. The l shorthand works too, and the reference notes that values run between 0 and the maximum, usually 100.

How do I change the input source on a display?

The input command sets the source, with common values DisplayPort 1: 15, DisplayPort 2: 16, HDMI 1: 17, HDMI 2: 18 and USB-C: 27. The input-alt command uses the alternate VCP code used by some LG displays, where the same inputs are 208, 209, 144, 145 and 210 for USB-C or DP 3.

How do I make sure a command applies to the right display?

Displays can be selected by list number, or by identifier using an identification method, with uuid as the default. The available methods are id, uuid, edid, seid, basic, ext and full, and the matching attributes can be printed with the `display list detailed` command.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. waydabber/m1ddc on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/waydabber-m1ddc.svg)](https://hysenlabs.com/projects/waydabber-m1ddc)

Was this useful?