Important
This exists so that I can avoid Logi Options+ for managing my Logitech MX Mechanical Mini. It hasn't been tested with anything else, and I make no pretence towards supporting general use cases. It's supplied as-is, and make melt your machine/end reality/just break. It's also entirely vibe-coded, so caveat emptor.
A minimalist command-line tool for macOS that enumerates Logitech wireless devices paired to a Unifying or Bolt receiver, and lets you read and switch the OS layout, Fn key mode, and backlight state of HID++ 2.0 keyboards.
- macOS (uses IOKit HID)
- Clang with C++17 support (ships with Xcode Command Line Tools)
- A Logitech Unifying or Bolt USB receiver
make
Produces ./minilogi. No external dependencies.
minilogi [-q] <command>
| Command | Description |
|---|---|
ls |
List all receivers and their paired devices |
get-layout |
Show the current OS layout of all paired keyboards |
get-battery |
Show the battery level of all paired devices |
get-fn |
Show whether Fn keys are in standard or media mode |
get-backlight |
Show the backlight state of all paired keyboards |
set-layout=<os> |
Switch all paired keyboards to the given OS layout |
set-fn=<mode> |
Switch all paired keyboards to the given Fn key mode |
set-backlight=<state> |
Turn backlight on or off on all paired keyboards |
-q suppresses all output; the exit code still reflects success or failure.
mac, windows, linux, ios, android, chromeos
standard — F1–F12 are the primary action (press Fn for media keys)
media — media keys are the primary action (press Fn for F1–F12)
on — enable the backlight
off — disable the backlight
0— success (finding no paired devices is not a failure)1— argument error, no receiver found, receiver could not be opened, orset-layout/set-fn/set-backlightfailed to apply to a keyboard
$ minilogi ls
HID++ Device Enumerator
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC531)
Slot Type Name
--------------------------------------------------
(no paired devices found)
Receiver : USB Receiver (PID 0xC548)
Slot Type Name
--------------------------------------------------
1 Keyboard MX Mechanical Mini
$ minilogi get-battery
HID++ Battery Reporter
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC548)
Slot 1 MX Mechanical Mini 100% discharging
Receiver : USB Receiver (PID 0xC531)
(no HID++ 2.0 devices found)
$ minilogi get-layout
HID++ Layout Reporter
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC548)
Slot 1 MX Mechanical Mini Mac
Receiver : USB Receiver (PID 0xC531)
(no HID++ 2.0 keyboards found)
$ minilogi get-fn
HID++ Fn Key Reporter
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC548)
Slot 1 MX Mechanical Mini standard (F1-F12 primary)
Receiver : USB Receiver (PID 0xC531)
(no HID++ 2.0 keyboards found)
$ minilogi get-backlight
HID++ Backlight Reporter
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC548)
Slot 1 MX Mechanical Mini off
Receiver : USB Receiver (PID 0xC531)
(no HID++ 2.0 keyboards found)
$ minilogi set-layout=mac
HID++ Layout Switcher
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC531)
(no HID++ 2.0 keyboards found)
Receiver : USB Receiver (PID 0xC548)
Slot 1 MX Mechanical Mini already Mac layout
$ minilogi set-fn=standard
HID++ Fn Key Switcher
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC548)
Slot 1 MX Mechanical Mini already standard
Receiver : USB Receiver (PID 0xC531)
(no HID++ 2.0 keyboards found)
$ minilogi set-backlight=on
HID++ Backlight Switcher
==================================================================
Found 2 receiver(s).
Receiver : USB Receiver (PID 0xC548)
Slot 1 MX Mechanical Mini switched to on
Receiver : USB Receiver (PID 0xC531)
(no HID++ 2.0 keyboards found)
The included plist org.infernus.minilogi.set-mac-layout.plist registers a
LaunchAgent that runs minilogi -q set-layout=mac once each time you log
in, keeping all paired keyboards on Mac layout automatically.
Why a LaunchAgent and not a LaunchDaemon?
IOKit HID requires a user GUI session to open input devices. LaunchDaemons run as root with no session attached and cannot reach the HID stack. A LaunchAgent running in theAquasession type works correctly.
-
Build, sign, and copy the binary to
/usr/local/bin/:sudo make installThe
installtarget signs the binary with an ad-hoc signature before copying it. Ad-hoc signatures are tied to the binary's content hash, so you must re-grant Input Monitoring access after every reinstall (see Notes below). -
Grant Input Monitoring access to
/usr/local/bin/minilogiin
System Settings → Privacy & Security → Input Monitoring. -
Copy the plist to your user LaunchAgents directory:
sudo make install-launchagent -
Load it for the current session (or simply log out and back in):
launchctl load ~/Library/LaunchAgents/org.infernus.minilogi.set-mac-layout.plist
The agent runs once at login and exits. Output (if any) is written to
/tmp/minilogi.log.
launchctl unload ~/Library/LaunchAgents/org.infernus.minilogi.set-mac-layout.plist
rm ~/Library/LaunchAgents/org.infernus.minilogi.set-mac-layout.plist
To use a different layout, edit the plist and change set-layout=mac to your
preferred value (windows, linux, ios, android, or chromeos), then
reload the agent:
launchctl unload ~/Library/LaunchAgents/org.infernus.minilogi.set-mac-layout.plist
launchctl load ~/Library/LaunchAgents/org.infernus.minilogi.set-mac-layout.plist
| Receiver | PID(s) |
|---|---|
| Bolt | any Logitech PID at UsagePage 0xFF00 |
| Unifying | 0xC52B, 0xC531, 0xC532, 0xC534 |
- Only HID++ 2.0 devices are supported. Older HID++ 1.0 devices paired to a receiver will not appear in any command's output.
- macOS requires Input Monitoring permission to open HID receivers. The binary
is ad-hoc signed by default, meaning macOS ties the TCC grant to the binary's
content hash. After every
make installyou must re-grant Input Monitoring access in System Settings → Privacy & Security → Input Monitoring (remove the old entry and add the new binary). If you have an Apple Developer ID certificate you can supply it viamake install SIGN="Developer ID Application: Your Name (TEAMID)"to get a stable identity that survives rebuilds. - The first enumeration after a receiver is plugged in (or a device wakes from sleep) takes up to ~1.5 s per slot. Subsequent runs are much faster (~0.4 s total for a warm receiver).