OpenMouse Bridge is a small per-user companion process for the OpenMouse web control panel. The first target is Windows. Its core and loopback protocol are portable so Linux and macOS adapters can follow without changing the web app.
The initial service provides:
- a minimal native Windows and macOS status window with a shortcut to OpenMouse;
- process-based detection for configured game executables;
- discovery of visible Windows and macOS applications and the foreground application;
- persistent application profiles tied to a specific mouse;
- low-battery notifications with a configurable threshold and cooldown;
- Windows startup-at-login registration under the current user;
- a versioned HTTP API bound only to
127.0.0.1:17846; - an explicit browser-origin allowlist.
It does not run as an elevated Windows Service. It runs in the signed-in user's session, which is required for desktop notifications and avoids administrator permissions. Closing the status window hides it to the system tray while game detection and the loopback API continue running. The tray menu can restore the window, open OpenMouse, or explicitly quit Bridge.
Install stable Rust, then run:
cargo runBridge creates config.json in the operating system's per-user application
configuration directory. It automatically seeds and updates its tracked games
from the bundled games.json catalog. Custom entries written via
the API or added to the config are preserved when new catalog entries ship.
The relevant part of the generated config looks like this:
{
"batteryThresholdPercent": 20,
"alertCooldownMinutes": 360,
"games": [
{
"name": "Counter-Strike 2",
"executables": ["cs2.exe"]
}
],
"profiles": [],
"allowedOrigins": [
"https://dev.openmouse.app",
"http://localhost:5173"
]
}For development and portable tests, OPENMOUSE_BRIDGE_CONFIG can point to an
explicit configuration file.
GET /v1/statusreports the Bridge version, platform, active games, battery threshold, autostart state, and whether an OpenMouse client has completed a recent handshake.PUT /v1/handshakerenews OpenMouse's 20-second connection lease. The client sends this heartbeat every five seconds while connected.GET /v1/gamesreturns the full executable catalog currently being tracked.PUT /v1/gamesadds or updates custom tracked games and persists them. Bundled catalog entries are retained so a client cannot accidentally disable detection.GET /v1/applicationslists running games and identifies the foreground game. Only applications from the registered catalog are returned. Each item includes aniconId; requestingGET /v1/applications/{iconId}/iconreturns its extracted icon as a PNG.PUT /v1/default-profilekeeps Bridge synchronized with the mouse and settings currently selected in OpenMouse. Bridge shows this profile whenever no game-specific profile is active.GET /v1/profilesreads saved application profiles;PUT /v1/profilesreplaces and persists them.PUT /v1/batteryaccepts{ deviceId, deviceName, percent, charging }and applies the notification threshold and cooldown.PUT /v1/autostartaccepts{ enabled }. It is implemented on Windows.
Only configured web origins receive CORS access. The listener never binds to a LAN or public interface.
⚠️ Beta. Native device control is new and still being validated on hardware. It changes DPI and polling rate only, never touches firmware, and is fully reversible — but treat it as experimental.
Some mice keep their configuration channel on a USB interface the browser is not
allowed to reach. The Attack Shark X11 is the hard case: its HID descriptor
declares no feature reports, so neither WebHID nor the OS HID API can configure
it (on Windows, HidD_SetFeature returns ERROR_INVALID_FUNCTION). Bridge
solves this the same way the reference driver does — it claims USB interface
2 and sends raw control transfers with nusb,
bypassing HID entirely.
Supported devices (VID 0x1d57): Attack Shark X11 wireless receiver
(0xfa60) and wired (0xfa55), and the Attack Shark R1 (0xfa61).
What works today: six-stage DPI (50–22000, in 50 steps), polling rate (125/250/500/1000 Hz), and battery on the wireless receiver. Lighting and macros are not implemented yet.
Reaching interface 2 raw needs a suitable driver bound to it. This is a one-time step; the mouse keeps working as a normal mouse throughout (pointing and clicking are on a different interface and are never touched).
Windows must hand interface 2 to the WinUSB driver. The easiest path is in OpenMouse itself: open Interface settings → Bridge → Native devices and click “Enable native control”. Bridge installs a small, scoped WinUSB driver package for interface 2 of the Attack Shark (self-signed and trusted on your machine, behind one Windows admin prompt). Remove driver in the same place reverts it.
The driver package and its scripts live in driver/. To install it
manually instead, run driver/sign-and-install.ps1
from an administrator PowerShell, or use Zadig to
assign WinUSB to the device's Interface 2. See
driver/README.md for details, safety notes, and how to
sign for distribution. Nothing here writes firmware, and only interface 2 of the
three known product IDs is ever affected.
nusb detaches the kernel HID driver from interface 2 automatically; it only
needs permission to open the device. Create a udev rule granting the logged-in
user access to the Attack Shark:
sudo tee /etc/udev/rules.d/70-openmouse-attackshark.rules >/dev/null <<'RULE'
# Attack Shark X11 / R1 (VID 1d57) — allow the local user to configure it.
SUBSYSTEM=="usb", ATTRS{idVendor}=="1d57", MODE="0660", TAG+="uaccess"
RULE
sudo udevadm control --reload-rules && sudo udevadm triggerThen unplug and replug the mouse. No Zadig or driver swap is needed on Linux.
Untested. nusb can claim interfaces on macOS, but the Attack Shark path has not
been validated there yet.
GET /v1/devices— list attached Attack Shark devices with their current state:id("1d57:fa60"),name,connection("wired"/"wireless"),controllable(true once the driver is bound),batteryPercent,pollingRateHz,supportedPollingRates,dpiStages,activeDpiStage, and the DPI range (dpiMin/dpiMax/dpiStep).PUT /v1/devices/{id}/polling—{ hz }. Set the polling rate.PUT /v1/devices/{id}/dpi—{ stages, activeStage }. Write all six DPI stages (an array) and the active stage (1-based).PUT /v1/driver—{ action: "install" | "uninstall" }(Windows only). Runs the WinUSB driver install/removal behind a UAC prompt.
A device is only controllable after its interface 2 is bound (WinUSB on
Windows, or the udev rule on Linux); until then it is still listed so the UI can
explain what is needed.
For most mice, battery readings come from the connected OpenMouse control panel
via PUT /v1/battery. Natively supported devices (currently the Attack Shark,
see above) are read directly over USB, so their low-battery alerts fire even
while the browser is closed. Extending native battery and control to more mice
is ongoing. Game detection already runs independently in the background.
cargo fmt --check
cargo test
cargo clippy --all-targets -- -D warningsGitHub Actions tests and lints the service on Windows, macOS, and Linux. Every
successful push to main updates the rolling dev-build prerelease with a
Windows x64 zip and checksum. The same files remain available as workflow
artifacts for individual runs.
Pushing a stable version tag such as v1.0.0 publishes it as the latest GitHub
release with generated changelog notes, Windows x64 and universal macOS
archives, and SHA-256 checksums. Windows signing is automatic when the
repository has WINDOWS_CERTIFICATE_BASE64 and
WINDOWS_CERTIFICATE_PASSWORD secrets; unsigned development builds continue
to work without those secrets.