Monitor input switcher
Use the ddcctl monitor protocol to create a display input switcher hotkey.
Next ChapterAPIs used today | Description |
hs.execute | Allows you to call shell commands from Hammerspoon. |
hs.host | Query the OS for hostname information. |
hs.hotkey | Everything you need to bind functions to hotkeys. |
What you’re building #
In this chapter, you’re going to build a hotkey that seamlessly switches between your display inputs.
I have a Dell 3419UW monitor, with my work Macbook plugged into the USB-C input, and my personal desktop Mac plugged into DisplayPort 1. For a while, I was manually switching between computers dozens of times a day by menu diving on the actual monitor.
If you have a multiple computer setup like me, I’ll show you how to set up a single hotkey with Hammerspoon to seamlessly switch your display inputs, without having to mess with your monitor’s controls.
Install ddcctl on both computers #
The first thing we need to do is install ddcctl
. ddcctl
is an open-source command line program that lets you talk to your monitor using the Display Data Channel protocol. Among other things, it lets you switch inputs!
Run this command on both of your computers:

brew install ddcctl
If you run ddcctl
, you should see output like this:
D: NSScreen #724072469 (3440x1440 0°) 109.00 DPI
I: found 1 external display
2020-09-03 00:10:24.436 ddcctl[33078:42148351] Usage:
ddcctl -d <1-..> [display#]
-w 100000 [delay usecs between settings]
----- Basic settings -----
-b <1-..> [brightness]
-c <1-..> [contrast]
-rbc [reset brightness and contrast]
----- Settings that don't always work -----
-m <1|2> [mute speaker OFF/ON]
-v <1-254> [speaker volume]
-i <1-18> [select input source]
-p <1|2-5> [power on | standby/off]
-o [read-only orientation]
----- Settings (testing) -----
-rg <1-..> [red gain]
-gg <1-..> [green gain]
-bg <1-..> [blue gain]
-rrgb [reset color]
----- Setting grammar -----
-X ? (query value of setting X)
-X NN (put setting X to NN)
-X <NN>- (decrease setting X by NN)
-X <NN>+ (increase setting X by NN)
Figure out the monitor input number #
Each input source (USB-C, HDMI, DisplayPort 1, etc) has an input source number. There is a table of input sources on ddcctl’s README. However, I found it to be incomplete–for example, my monitor’s USB-C input source wasn’t in the table.
Just to be safe, let’s use ddcctl
to figure out exactly what the input source number is. Run this command on your first computer:

ddcctl -d 1 -i ?
When I ran this command on my desktop, I got the following output:
I: VCP control #96 (0x60) = current: 15, max: 18
The current: 15
corresponds to my input number, which is the DisplayPort connection for my desktop.
Repeat the ddcctl -d 1 -i ?
command on your second computer. When I ran it on my laptop, I go the following output:
I: VCP control #96 (0x60) = current: 27, max: 35
Your numbers will probably be different! Make a note of them, though. My numbers are as follows:
Source | Input number |
---|---|
Desktop (DisplayPort) | 15 |
Laptop (USB-C) | 27 |
Figure out your hostnames #
Before moving onto the next step, run the hostname
command on each of your computers and make a note of it. Here’s what I got when I ran those commands:
Computer | Hostname |
---|---|
Desktop | sorny |
Laptop | st-dbalatero1 |
We’ll use the hostname in our Hammerspoon script to correctly toggle the opposite monitor input when pressing the hotkey.
Create a new config file #
First, make a config file to hold all your audio switcher code.

touch ~/.hammerspoon/monitor-switcher.lua
And require it in your main config:

require("monitor-switcher")
Detect which computer you’re on #
First, create a function that detects which computer you’re on. We’ll return "laptop"
or "desktop"
, depending on the hostname. hs.host
provides a handy way to get the current computer’s hostname:

desktopHostname = "sorny"
local function currentComputer()
if hs.host.localizedName() == desktopHostname then
return "desktop"
else
return "laptop"
end
end
Bind a key to switch monitor inputs #

hs.hotkey.bind(hyper, 'm', function()
-- FIXME: Change these input numbers to the ones you found in the previous
-- step.
local desktopInput = 15
local laptopInput = 27
-- Figure out which input number we should switch to, based on the current
-- computer we're on.
local inputNumber = nil
if currentComputer() == "desktop" then
-- We're on the desktop, we want to switch to the laptop
inputNumber = laptopInput
else
-- Otherwise, we switch from the laptop -> desktop
inputNumber = desktopInput
end
-- Issue an input switch command with `ddcctl`.
hs.execute("/usr/local/bin/ddcctl -d 1 -i " .. inputNumber)
end)
Once you’ve added this, reload your Hammerspoon config and press ⌘⇧⌥⌃M give it a try! Your monitor should switch to your other computer.
Automatically mute your audio on wake
Get the entire script #
Want to just paste in this whole project to your monitor-switcher.lua
file?

TK fill this in at the very end once we're sure all the code is solid