A lightweight, open-source, fully local alternative to Logitech Options+ for remapping Logitech HID++ mice.
5,227
stars
284
commits
Python
primary language
Aug 13, 2026
updated
English | 中文文档
A lightweight, open-source, fully local alternative to Logitech Options+ for remapping Logitech HID++ mice. The current best experience is on the MX Master and MX Anywhere families, with detection and fallback UI support for additional Logitech models.
No telemetry. No cloud. No Logitech account required.
No install required. Just download, extract, and double-click.
Mouser-Windows.zipMouser-macOS.zipMouser-macOS-intel.zipMouser-Linux.zip/Applications, wherever).Mouser.exe, Mouser.app, or ./Mouser.That's it. The app opens, drops a tray / menu-bar icon, and starts remapping immediately.
/dev/hidraw*, /dev/input/event*, and write access to /dev/uinput. Run the bundled helper once after extracting:
cd /path/to/extracted/Mouser
./install-linux-permissions.sh
Reconnect the mouse, then relaunch.%APPDATA%\Mouser\config.json (Windows)~/Library/Application Support/Mouser/config.json (macOS)~/.config/Mouser/config.json (Linux)%APPDATA%\Mouser\logs, ~/Library/Logs/Mouser, or $XDG_STATE_HOME/Mouser/logs.| Mouse & Profiles | Point & Scroll |
|---|---|
![]() | ![]() |
Ctrl+Shift+P) directly in the UI.Cycle DPI Presets action you can map to a button.0x2111), with a sensitivity threshold and a mappable Toggle SmartShift action.WH_MOUSE_LL, CGEventTap, evdev + uinput).Mouser-macOS-intel.zip and Mouser-macOS.zip artifacts; the menu-bar app runs as LSUIElement (no Dock icon).Logi Bolt only when the receiver PID is positively identified).config.json and restored on next launch.| Family / model | Detection + HID++ probing | UI support |
|---|---|---|
| MX Master 4 / 3S / 3 / 2S / MX Master | Yes | Dedicated interactive per-model layouts |
| MX Anywhere 3S / 3 / 2S | Yes | Dedicated interactive per-model layouts |
| MX Vertical | Yes | Generic fallback card (with DPI switch button support) |
| Unknown Logitech HID++ mice | Best effort by PID/name | Generic fallback card |
MX Master and MX Anywhere devices have dedicated visual overlays. Other devices are still detected, show their model name, and can opt into an experimental layout override — button positions just may not line up until a real overlay lands. See CONTRIBUTING_DEVICES.md to add yours.
| Button | Default action |
|---|---|
| Back button (XButton1) | Alt + Tab (Switch Windows) |
| Forward button (XButton2) | Alt + Tab (Switch Windows) |
| Middle click | Pass-through |
| Gesture button | Pass-through |
| Gesture swipes (up / down / left / right) | Pass-through |
| Mode shift (scroll click) | Switch Scroll Mode (Ratchet / Free Spin) |
| Horizontal scroll left | Browser Back |
| Horizontal scroll right | Browser Forward |
| DPI switch (MX Vertical) | Pass-through |
Action labels adapt per platform. Windows exposes Win+D and Task View; macOS exposes Mission Control, Show Desktop, App Exposé, and Launchpad; Linux falls back to compositor-native equivalents.
| Category | Actions |
|---|---|
| Navigation | Alt+Tab, Alt+Shift+Tab, Show Desktop, Previous Desktop, Next Desktop, Task View (Windows), Mission Control / App Exposé / Launchpad (macOS), Page Up / Page Down / Home / End |
| Browser | Back, Forward, Close Tab (Ctrl+W), New Tab (Ctrl+T), Next Tab (Ctrl+Tab), Previous Tab (Ctrl+Shift+Tab) |
| Editing | Copy, Paste, Cut, Undo, Select All, Save, Find |
| Media | Volume Up, Volume Down, Volume Mute, Play / Pause, Next Track, Previous Track |
| Scroll | Switch Scroll Mode (Ratchet / Free Spin), Toggle SmartShift, Cycle DPI Presets |
| Mouse | Left Click, Right Click, Middle Click, Back (Mouse Button 4), Forward (Mouse Button 5) |
| Custom | User-defined keyboard shortcuts (any key combination, captured in the UI) |
| Other | Do Nothing (pass-through) |
You only need this if you want to hack on Mouser or run a development build. Most users should grab a release zip — see Download & Run.
git and a working build toolchaingit clone https://github.com/TomBadash/Mouser.git
cd Mouser
python -m venv .venv
.\.venv\Scripts\activate
pip install -r requirements.txt
# Run from source
python main_qml.py
# Or start straight into the tray
python main_qml.py --start-hidden
# Build a portable zip
build.bat # standard
build.bat --clean # force clean rebuild
build.bat installs requirements, verifies that hidapi is importable, and packages with PyInstaller. The output lives in dist\Mouser\ — zip the folder and ship it.
To launch a source checkout without a console window, create a shortcut that uses pythonw.exe; see DEVELOPMENT.md.
source .venv/bin/activate
pip install -r requirements.txt
# Run from source
python main_qml.py
python main_qml.py --start-hidden # launch directly to menu bar
# Build the native menu-bar bundle
pip install pyinstaller
./build_macos_app.sh
The output is dist/Mouser.app. The script reuses images/AppIcon.icns when present, otherwise generates one from images/logo_icon.png. Signing depends on whether MOUSER_SIGN_IDENTITY is set in the environment:
codesign --sign -. Convenient for one-off builds, but the bundle's code identity can change on rebuild, so macOS may ask for Accessibility permission again.security find-identity -v -p codesigning to list them — SHA-1 form preferred): signs every nested .dylib / .so / .framework with hardened runtime options, then signs the outer app with the hardened-runtime exceptions at build_resources/Mouser.entitlements. This is a local developer signing path for repeated builds; stable macOS permission behavior depends on keeping the same source, resolved Python interpreter, dependency versions, architecture, signing identity, entitlements, and timestamp policy. A failing codesign --verify --deep --strict check aborts the build.MOUSER_SIGN_IDENTITY="ABCD1234..." ./build_macos_app.sh # local signed build
arm64 Python produces an Apple Silicon bundle, an x86_64 Python produces an Intel bundle. Set PYINSTALLER_TARGET_ARCH=arm64|x86_64|universal2 to override.Mouser-macOS.zip (Apple Silicon) and Mouser-macOS-intel.zip (Intel) automatically on tag pushes.source .venv/bin/activate
pip install -r requirements.txt
# Run from source
python main_qml.py
# Install device permissions (only needed once, then reconnect the mouse)
./packaging/linux/install-linux-permissions.sh
# Build a portable bundle
sudo apt-get install libhidapi-dev
pip install pyinstaller
pyinstaller Mouser-linux.spec --noconfirm
The helper installs 69-mouser-logitech.rules, reloads udev, and tries to modprobe uinput. After a successful run, reconnect the mouse, fully quit Mouser, and launch normally — no sudo. On systems without logind / uaccess, adding the user to the input group is the distro-specific fallback.
The first normal Linux launch creates or refreshes:
~/.local/share/applications/io.github.tombadash.mouser.desktop
The generated launcher uses absolute paths for the current portable app or source checkout, and syncs Mouser's app icon into the per-user hicolor icon theme when possible. If you move the checkout, launch Mouser once from the new path to refresh the app-menu entry. Enabling Start at login also manages:
~/.config/autostart/io.github.tombadash.mouser.desktop
That Linux autostart entry includes a short GNOME startup delay so Mouser does not race Bluetooth / HID initialization immediately after login.
xdotool enables per-app profile switching on X11; kdotool adds KDE Wayland support. Other Wayland compositors fall back to the default profile.
Automated releases: pushing a
v*tag triggers.github/workflows/release.yml, which builds Windows, macOS (Apple Silicon + Intel), and Linux artifacts in CI and uploads them to the GitHub Release.
For project layout, the architecture diagram, the HID++ gesture detector, the Engine + reconnection flow, debug CLI flags (--hid-backend=iokit|hidapi|auto), and how to run the test suite, see DEVELOPMENT.md. To add a new device, see CONTRIBUTING_DEVICES.md.
xdotool, KDE Wayland works via kdotool, GNOME / other Wayland compositors still fall back to the default profile./dev/hidraw*, /dev/input/event*, and /dev/uinput. Use install-linux-permissions.sh once instead of running as root.REPROG_CONTROLS_V4 controls instead of the current fixed setsContributions are welcome.
If Mouser saves you from installing Logitech Options+, consider supporting development:
Every bit helps keep the project going — thank you.
0x2111) with sensitivity control and scroll-mode sync.hidapi fallback path.0x2111) devices, with a per-device Scroll page slider.This project is licensed under the MIT License.
Mouser is not affiliated with or endorsed by Logitech. "Logitech", "MX Master", and "Options+" are trademarks of Logitech International S.A.
Python
84.4%
QML
15.0%
A lightweight, open-source, fully local alternative to Logitech Options+ for remapping Logitech HID++ mice.
5,227
stars
284
commits
Python
primary language
Aug 13, 2026
updated
English | 中文文档
A lightweight, open-source, fully local alternative to Logitech Options+ for remapping Logitech HID++ mice. The current best experience is on the MX Master and MX Anywhere families, with detection and fallback UI support for additional Logitech models.
No telemetry. No cloud. No Logitech account required.
No install required. Just download, extract, and double-click.
Mouser-Windows.zipMouser-macOS.zipMouser-macOS-intel.zipMouser-Linux.zip/Applications, wherever).Mouser.exe, Mouser.app, or ./Mouser.That's it. The app opens, drops a tray / menu-bar icon, and starts remapping immediately.
/dev/hidraw*, /dev/input/event*, and write access to /dev/uinput. Run the bundled helper once after extracting:
cd /path/to/extracted/Mouser
./install-linux-permissions.sh
Reconnect the mouse, then relaunch.%APPDATA%\Mouser\config.json (Windows)~/Library/Application Support/Mouser/config.json (macOS)~/.config/Mouser/config.json (Linux)%APPDATA%\Mouser\logs, ~/Library/Logs/Mouser, or $XDG_STATE_HOME/Mouser/logs.| Mouse & Profiles | Point & Scroll |
|---|---|
![]() | ![]() |
Ctrl+Shift+P) directly in the UI.Cycle DPI Presets action you can map to a button.0x2111), with a sensitivity threshold and a mappable Toggle SmartShift action.WH_MOUSE_LL, CGEventTap, evdev + uinput).Mouser-macOS-intel.zip and Mouser-macOS.zip artifacts; the menu-bar app runs as LSUIElement (no Dock icon).Logi Bolt only when the receiver PID is positively identified).config.json and restored on next launch.| Family / model | Detection + HID++ probing | UI support |
|---|---|---|
| MX Master 4 / 3S / 3 / 2S / MX Master | Yes | Dedicated interactive per-model layouts |
| MX Anywhere 3S / 3 / 2S | Yes | Dedicated interactive per-model layouts |
| MX Vertical | Yes | Generic fallback card (with DPI switch button support) |
| Unknown Logitech HID++ mice | Best effort by PID/name | Generic fallback card |
MX Master and MX Anywhere devices have dedicated visual overlays. Other devices are still detected, show their model name, and can opt into an experimental layout override — button positions just may not line up until a real overlay lands. See CONTRIBUTING_DEVICES.md to add yours.
| Button | Default action |
|---|---|
| Back button (XButton1) | Alt + Tab (Switch Windows) |
| Forward button (XButton2) | Alt + Tab (Switch Windows) |
| Middle click | Pass-through |
| Gesture button | Pass-through |
| Gesture swipes (up / down / left / right) | Pass-through |
| Mode shift (scroll click) | Switch Scroll Mode (Ratchet / Free Spin) |
| Horizontal scroll left | Browser Back |
| Horizontal scroll right | Browser Forward |
| DPI switch (MX Vertical) | Pass-through |
Action labels adapt per platform. Windows exposes Win+D and Task View; macOS exposes Mission Control, Show Desktop, App Exposé, and Launchpad; Linux falls back to compositor-native equivalents.
| Category | Actions |
|---|---|
| Navigation | Alt+Tab, Alt+Shift+Tab, Show Desktop, Previous Desktop, Next Desktop, Task View (Windows), Mission Control / App Exposé / Launchpad (macOS), Page Up / Page Down / Home / End |
| Browser | Back, Forward, Close Tab (Ctrl+W), New Tab (Ctrl+T), Next Tab (Ctrl+Tab), Previous Tab (Ctrl+Shift+Tab) |
| Editing | Copy, Paste, Cut, Undo, Select All, Save, Find |
| Media | Volume Up, Volume Down, Volume Mute, Play / Pause, Next Track, Previous Track |
| Scroll | Switch Scroll Mode (Ratchet / Free Spin), Toggle SmartShift, Cycle DPI Presets |
| Mouse | Left Click, Right Click, Middle Click, Back (Mouse Button 4), Forward (Mouse Button 5) |
| Custom | User-defined keyboard shortcuts (any key combination, captured in the UI) |
| Other | Do Nothing (pass-through) |
You only need this if you want to hack on Mouser or run a development build. Most users should grab a release zip — see Download & Run.
git and a working build toolchaingit clone https://github.com/TomBadash/Mouser.git
cd Mouser
python -m venv .venv
.\.venv\Scripts\activate
pip install -r requirements.txt
# Run from source
python main_qml.py
# Or start straight into the tray
python main_qml.py --start-hidden
# Build a portable zip
build.bat # standard
build.bat --clean # force clean rebuild
build.bat installs requirements, verifies that hidapi is importable, and packages with PyInstaller. The output lives in dist\Mouser\ — zip the folder and ship it.
To launch a source checkout without a console window, create a shortcut that uses pythonw.exe; see DEVELOPMENT.md.
source .venv/bin/activate
pip install -r requirements.txt
# Run from source
python main_qml.py
python main_qml.py --start-hidden # launch directly to menu bar
# Build the native menu-bar bundle
pip install pyinstaller
./build_macos_app.sh
The output is dist/Mouser.app. The script reuses images/AppIcon.icns when present, otherwise generates one from images/logo_icon.png. Signing depends on whether MOUSER_SIGN_IDENTITY is set in the environment:
codesign --sign -. Convenient for one-off builds, but the bundle's code identity can change on rebuild, so macOS may ask for Accessibility permission again.security find-identity -v -p codesigning to list them — SHA-1 form preferred): signs every nested .dylib / .so / .framework with hardened runtime options, then signs the outer app with the hardened-runtime exceptions at build_resources/Mouser.entitlements. This is a local developer signing path for repeated builds; stable macOS permission behavior depends on keeping the same source, resolved Python interpreter, dependency versions, architecture, signing identity, entitlements, and timestamp policy. A failing codesign --verify --deep --strict check aborts the build.MOUSER_SIGN_IDENTITY="ABCD1234..." ./build_macos_app.sh # local signed build
arm64 Python produces an Apple Silicon bundle, an x86_64 Python produces an Intel bundle. Set PYINSTALLER_TARGET_ARCH=arm64|x86_64|universal2 to override.Mouser-macOS.zip (Apple Silicon) and Mouser-macOS-intel.zip (Intel) automatically on tag pushes.source .venv/bin/activate
pip install -r requirements.txt
# Run from source
python main_qml.py
# Install device permissions (only needed once, then reconnect the mouse)
./packaging/linux/install-linux-permissions.sh
# Build a portable bundle
sudo apt-get install libhidapi-dev
pip install pyinstaller
pyinstaller Mouser-linux.spec --noconfirm
The helper installs 69-mouser-logitech.rules, reloads udev, and tries to modprobe uinput. After a successful run, reconnect the mouse, fully quit Mouser, and launch normally — no sudo. On systems without logind / uaccess, adding the user to the input group is the distro-specific fallback.
The first normal Linux launch creates or refreshes:
~/.local/share/applications/io.github.tombadash.mouser.desktop
The generated launcher uses absolute paths for the current portable app or source checkout, and syncs Mouser's app icon into the per-user hicolor icon theme when possible. If you move the checkout, launch Mouser once from the new path to refresh the app-menu entry. Enabling Start at login also manages:
~/.config/autostart/io.github.tombadash.mouser.desktop
That Linux autostart entry includes a short GNOME startup delay so Mouser does not race Bluetooth / HID initialization immediately after login.
xdotool enables per-app profile switching on X11; kdotool adds KDE Wayland support. Other Wayland compositors fall back to the default profile.
Automated releases: pushing a
v*tag triggers.github/workflows/release.yml, which builds Windows, macOS (Apple Silicon + Intel), and Linux artifacts in CI and uploads them to the GitHub Release.
For project layout, the architecture diagram, the HID++ gesture detector, the Engine + reconnection flow, debug CLI flags (--hid-backend=iokit|hidapi|auto), and how to run the test suite, see DEVELOPMENT.md. To add a new device, see CONTRIBUTING_DEVICES.md.
xdotool, KDE Wayland works via kdotool, GNOME / other Wayland compositors still fall back to the default profile./dev/hidraw*, /dev/input/event*, and /dev/uinput. Use install-linux-permissions.sh once instead of running as root.REPROG_CONTROLS_V4 controls instead of the current fixed setsContributions are welcome.
If Mouser saves you from installing Logitech Options+, consider supporting development:
Every bit helps keep the project going — thank you.
0x2111) with sensitivity control and scroll-mode sync.hidapi fallback path.0x2111) devices, with a per-device Scroll page slider.This project is licensed under the MIT License.
Mouser is not affiliated with or endorsed by Logitech. "Logitech", "MX Master", and "Options+" are trademarks of Logitech International S.A.
Python
84.4%
QML
15.0%