display-switch: a USB switch as a multi-monitor KVM
Turn a $30 USB switch into a full-featured multi-monitor KVM switch
At a glance
- What is it?
- haimgel/display-switch is a small Rust daemon that watches USB connect and disconnect events and switches monitor inputs over DDC/CI. It is for people with two computers and one set of monitors, and it is honest about the case where it works badly.
- Who is it for?
- Adopt display-switch if both computers stay awake and you already own a USB switch with a button, because the design assumes the daemon runs on every machine attached to those monitors. Do not adopt it if the second machine sleeps aggressively or if you need switching to work with one computer powered off, since the README states that a sleeping computer will switch the monitors straight back.
- 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 30 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: one button, two computers, three monitors
A hardware KVM for multiple monitors costs real money, and it inserts another box and more cables between the machines and the displays. A cheap USB switch does the peripheral half of the job for about $30: press the button and the keyboard, mouse and dock move to the other computer. The monitors do not follow, because the video cables never moved. You are left pressing the monitor's own input button, once per display.
display-switch closes that gap in software. It watches for a USB device appearing or disappearing, and when that happens it sends a DDC/CI command to each monitor telling it which input to select. The README describes the result as turning "a simple USB switch into a full-fledged KVM solution." The audience is narrow and specific: people with two computers, a shared set of monitors, and a USB switch they already own. If you have one computer, this tool has nothing to do.
How the watching and the switching actually work
The daemon uses rusb to enumerate USB devices and receive connect and disconnect events. You give it one device to watch, identified as vendor ID and product ID in hex, for example 1050:0407. That is the dock or switch that moves when you press the button.
On a match, the program sends DDC/CI commands over the display link. The platform-specific crates in Cargo.toml show how: ddc-macos on macOS, ddc-i2c plus uinput on Linux, ddc-winapi plus nvapi on Windows. Each monitor receives an input-select command, either a named value such as Hdmi1 or DisplayPort1, or a raw decimal or hexadecimal value such as 0x10 if your display uses a code the names do not cover.
The design is deliberately one-directional. The README states the app "only switches monitors one way" and relies on itself running on the other computers to switch back. That is not laziness, it is the only arrangement that stays consistent: whichever machine sees the USB device arrive is the machine that should now own the screens. The optional on_usb_disconnect setting exists, but the README flags it as problematic, because a computer that has put the monitors to sleep will pull them straight back.
Installing display-switch and making the first switch
On macOS the Homebrew tap is the documented path. This installs the binary and nothing else; the configuration file is yours to write.
brew install haimgel/tools/display_switchOn Linux and Windows the README says to download the files from the releases page and place them where you see fit. Linux builds need extra packages before compiling from source:
sudo apt install libxi-dev xorg-devNext, find the USB ID of the device that moves when you press the switch button. On Linux, capture the device list before and after the switch and diff it:
lsusb > a
# switch the usb dock here
lsusb > b
diff -u a bThe lines that appear or disappear in the diff are the candidates. Take the vendor and product ID from the one that corresponds to your dock.
Now write the configuration file. On Linux it belongs at $XDG_CONFIG_HOME/display-switch/display-switch.ini or ~/.config/display-switch/display-switch.ini; on macOS at ~/Library/Preferences/display-switch.ini; on Windows at %APPDATA%\display-switch\display-switch.ini.
usb_device = "1050:0407"
on_usb_connect = "Hdmi1"
on_usb_disconnect = "Hdmi2"Start the daemon and press the switch button. The monitors should change input. If they do not, the log file is the first place to look: on Linux it is written to $XDG_DATA_HOME/display-switch/display-switch.log or ~/.local/share/display-switch/display-switch.log, and on macOS to /Users/USERNAME/Library/Logs/display-switch/display-switch.log. Install the same binary and the mirrored configuration on the second computer, or the switch will only work in one direction.
Per-monitor sections and external commands
Monitors do not all want the same input. display-switch handles that with named sections, matched by a case-insensitive substring against the monitor ID, as in this README example where "len" matches a LEN P27u-10:
on_usb_connect = "DisplayPort2"
on_usb_disconnect = "Hdmi1"
[monitor1]
monitor_id = "len"
on_usb_connect = "DisplayPort1"Section values override the global defaults, and if two sections match the same monitor, the first one wins. That ordering rule is worth remembering, because overlapping substrings are easy to create by accident.
There is also on_usb_connect_execute and on_usb_disconnect_execute, which run a command when the switch happens. The README is explicit about the limits: the program splits the string into application name and parameters and supports no other shell features, so pipes, redirection and globbing will not work. Paths with spaces need single quotes, and on Windows backslashes must be doubled. This is enough to fire a script that remaps a keyboard or restarts an audio service, and not enough to do anything clever.
Where display-switch is the wrong tool
The sleep problem is the real one, and the README states it plainly: switching away is problematic because if the other computer has put the monitors to sleep, they will switch immediately back to the original input. Any setup where the idle machine suspends its displays will fight the daemon. You can work around it with on_usb_disconnect, but that is the configuration the README itself discourages, so treat it as a fallback rather than a plan.
The second constraint is that the daemon must run on every computer attached to those monitors. This is not a standalone utility that flips inputs from one machine. It is a pair of daemons agreeing on who owns the screens. If you cannot install software on the second machine, the tool does not apply.
The third is DDC/CI support. The switching depends on the monitor accepting input-select commands over its video connection. Monitors that ignore DDC/CI, or that only expose it on certain ports, will not respond no matter how the configuration is written. There is no fallback path in the documentation for a display that refuses the command.
Compared with a hardware KVM
A hardware KVM switches the video signal itself. The monitors see a cable change, so a powered-off or sleeping computer is irrelevant, and no software runs on either machine. It also costs far more than a USB switch and adds a box in the middle of the video path, which can matter if you run high refresh rates or long cables.
display-switch takes the opposite approach: the video cables never move, and the monitors are told to change input. That is why it is cheap and why it inherits the sleep problem. The two are not interchangeable so much as suited to different constraints. If the second machine is usually off, hardware wins. If both machines are on and you already have a USB switch, the software path costs nothing beyond configuration.
Maintenance, licence, and what upgrades cost you
The repository is not archived, and the last push was on 2026-09-01. Releases are infrequent: 1.4.1 arrived on 2025-09-28, 1.4.0 on 2024-11-11, and 1.3.1 on 2023-10-24. Cargo.toml lists version 1.5.0, ahead of the newest published release, which suggests work in progress on the main branch. That cadence means security fixes and platform updates arrive slowly, and a macOS or Windows API change could leave you waiting.
The licence is MIT, which permits commercial and private use and modification, provided the copyright notice and permission notice are included. If you build from source and ship the binary inside a product, that notice obligation follows the binary. This is a description of the licence text, not legal advice.
Upgrade cost is low in one sense and annoying in another. The configuration file format is small and stable across releases, so most upgrades are a binary swap. The friction is platform-specific build tooling: the Makefile builds a universal macOS binary with lipo across the x86_64-apple-darwin and aarch64-apple-darwin targets, and Linux builds pull in ddc-i2c and uinput. Building from source on macOS expects Xcode and Rust to be installed first.
Editorial conclusion
Adopt display-switch if both computers stay awake and you already own a USB switch with a button, because the design assumes the daemon runs on every machine attached to those monitors. Do not adopt it if the second machine sleeps aggressively or if you need switching to work with one computer powered off, since the README states that a sleeping computer will switch the monitors straight back. Before trusting it, run lsusb before and after the switch to confirm the vendor and product ID you intend to watch, and check the log file at ~/.local/share/display-switch/display-switch.log on Linux or the equivalent path on your platform to confirm the daemon saw the event.
Frequently asked questions
How can I switch between HDMI and DisplayPort with display-switch?
Set on_usb_connect to the input you want when the watched USB device appears, and on_usb_disconnect to the other input. The README lists Hdmi1, Hdmi2, DisplayPort1, DisplayPort2, Dvi1, Dvi2 and Vga1 as supported names, and notes that a USB-C monitor port is usually reported as DisplayPort2.
Is display-switch a DisplayPort switch?
No. It does not switch the video signal. It watches USB connect and disconnect events and sends DDC/CI commands that tell each monitor which input to select, so the cables stay where they are.
Do I still need a KVM switch if I use display-switch?
You need a USB switch, not a full KVM. The README describes the utility as turning a simple USB switch into a KVM solution: the USB switch moves your peripherals, and display-switch moves the monitor inputs to match.
How do I switch between two desktop screens with display-switch?
Install the daemon on both computers and give each one a configuration file pointing at the same USB device. The README states the app only switches monitors one way and relies on itself running on the other computers to switch back.
What is display-switch?
It is a Rust utility that watches for USB device connect and disconnect events and switches monitor inputs via DDC/CI. It runs on macOS, Windows and Linux, and the README says it should function on all three.
Official sources
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.
[](https://hysenlabs.com/projects/haimgel-display-switch)