Umbra (astronomical/Latin): The deepest part of a shadow during an eclipse, where the light source is fully blocked. Mascot: a slow loris with wide eyes inside a dark circle. Tagline: Full shadow, on demand.
  • Rust 96.2%
  • Just 3.3%
  • Nushell 0.5%
Find a file
David bb8ef94bb7
All checks were successful
Check / fmt + clippy + build + tests (push) Successful in 32s
Merge pull request 'feat(justfile): add dev-clean / dev-clean-all teardown recipes' (#24) from feat/dev-clean-recipes into main
Reviewed-on: #24
2026-06-13 19:47:40 +02:00
.forgejo/workflows fix(ci): run check job inside rust-builder-glibc image 2026-06-06 22:50:56 -04:00
.idea feat: Initial app 2026-05-02 18:42:32 -04:00
crates Merge remote-tracking branch 'origin/main' into feat/abyssus-line-devicespecs-UMBRA-9 2026-06-06 23:22:54 -04:00
install_files/udev feat: Initial app 2026-05-02 18:42:32 -04:00
oci-build chore(build): bump rust-builder-glibc to v1.0.1 2026-06-06 22:25:26 -04:00
.dockerignore chore(governance): ship binaries to Pandora's Box Generic Packages 2026-06-02 08:32:11 -04:00
.gitignore chore: Sync .gitignore 2026-06-06 15:34:02 -04:00
Cargo.lock chore: expose crate version, git hash, and build date 2026-05-07 18:20:44 +02:00
Cargo.toml chore(governance): ship binaries to Pandora's Box Generic Packages 2026-06-02 08:32:11 -04:00
CLAUDE.md fix(ci): run check job inside rust-builder-glibc image 2026-06-06 22:50:56 -04:00
justfile feat(justfile): add dev-clean / dev-clean-all teardown recipes 2026-06-13 12:52:04 -04:00
LICENSE.md chore(governance): ship binaries to Pandora's Box Generic Packages 2026-06-02 08:32:11 -04:00
README.md Merge remote-tracking branch 'origin/main' into feat/abyssus-line-devicespecs-UMBRA-9 2026-06-06 23:22:54 -04:00

umbra

Standalone, cross-platform Rust tools for configuring Razer mice. No kernel modules, no daemon, no D-Bus. Talks to the device directly over HID feature reports using the OS's built-in HID stack (hidraw on Linux, IOKit on macOS, HID.dll on Windows).

The wire protocol is ported from the OpenRazer kernel driver, which is the de-facto reference for Razer's USB control protocol.

Supported devices

Device VID:PID DPI max Polling Lighting Battery
Razer Cobra 1532:00A3 8500 yes Logo (1 zone) n/a
Razer Cobra Pro (Wired) 1532:00AF 30,000 yes Logo + Scroll, static/spectrum yes
Razer Cobra Pro (Wireless) 1532:00B0 30,000 yes Logo + Scroll, static/spectrum yes
Razer DeathAdder 2013 1532:0037 n/a yes none n/a
Razer DeathAdder 1800 1532:0038 n/a yes none n/a
Razer DeathAdder Chroma 1532:0043 10,000 yes none n/a
Razer DeathAdder 2000 1532:004F 2000 yes none n/a
Razer DeathAdder 3500 1532:0054 3500 yes none n/a
Razer DeathAdder Elite 1532:005C 16,000 yes Logo + Scroll (2 zones) n/a
Razer Mamba Elite 1532:006C 16,000 yes Logo + Scroll + L + R (4 zones) n/a
Razer Lancehead (Wired) 1532:0059 16,000 yes Logo + Scroll + L + R (4 zones) yes
Razer Lancehead (Wireless) 1532:005A 16,000 yes Logo + Scroll + L + R (4 zones) yes
Razer Lancehead Tournament Edition 1532:0060 16,000 yes Logo + Scroll + L + R (4 zones) n/a
Razer Lancehead Wireless 2018 (Receiver) 1532:006F 16,000 yes Logo + Scroll + L + R (4 zones) yes
Razer Lancehead Wireless 2018 (Wired) 1532:0070 16,000 yes Logo + Scroll + L + R (4 zones) yes
Razer Mamba 2012 (Wired) 1532:0024 6400 yes none yes
Razer Mamba 2012 (Wireless) 1532:0025 6400 yes none yes
Razer Mamba 2015 (Wired) 1532:0044 16,000 yes none yes
Razer Mamba 2015 (Wireless) 1532:0045 16,000 yes none yes
Razer Mamba Tournament Edition 1532:0046 16,000 no none n/a
Razer Mamba Wireless 2018 (Receiver) 1532:0072 16,000 yes Logo + Scroll (2 zones) yes
Razer Mamba Wireless 2018 (Wired) 1532:0073 16,000 yes Logo + Scroll (2 zones) yes
Razer DeathAdder Essential 1532:006E 6400 yes Logo + Scroll, limited effects n/a
Razer DeathAdder Essential (White) 1532:0071 6400 yes Logo + Scroll, limited effects n/a
Razer DeathAdder Essential (2021) 1532:0098 6400 yes Logo + Scroll, limited effects n/a
Razer DeathAdder V2 Pro (Wired) 1532:007C 20,000 yes Logo (1 zone) yes
Razer DeathAdder V2 Pro (Wireless) 1532:007D 20,000 yes Logo (1 zone) yes
Razer DeathAdder V2 1532:0084 20,000 yes Logo + Scroll (2 zones) n/a
Razer DeathAdder V2 Mini 1532:008C 8500 yes Logo (1 zone) n/a
Razer DeathAdder V2 X HyperSpeed 1532:009C 14,000 yes none yes
Razer DeathAdder V2 Lite 1532:00A1 8500 yes Logo (1 zone) n/a
Razer DeathAdder V3 1532:00B2 30,000 no none n/a
Razer DeathAdder V3 Pro (Wired) 1532:00B6 30,000 yes none yes
Razer DeathAdder V3 Pro (Wireless) 1532:00B7 30,000 yes none yes
Razer DeathAdder V3 Pro (Wired, alt PID) 1532:00C2 30,000 yes none yes
Razer DeathAdder V3 Pro (Wireless, alt PID) 1532:00C3 30,000 yes none yes
Razer DeathAdder V3 HyperSpeed (Wired) 1532:00C4 30,000 yes none yes
Razer DeathAdder V3 HyperSpeed (Wireless) 1532:00C5 30,000 yes none yes
Razer DeathAdder V4 Pro (Wired) 1532:00BE 45,000 no none yes
Razer DeathAdder V4 Pro (Wireless) 1532:00BF 45,000 no none yes
Razer Viper Mini 1532:008A 8500 yes Logo (1 zone) n/a
Razer Basilisk 1532:0064 16,000 yes Logo + Scroll (2 zones) n/a
Razer Basilisk Essential 1532:0065 6400 yes Logo (1 zone) n/a
Razer Basilisk X HyperSpeed 1532:0083 16,000 yes none yes
Razer Basilisk V2 1532:0085 26,000 yes Logo + Scroll (2 zones) n/a
Razer Basilisk Ultimate (Wired) 1532:0086 26,000 yes Logo + Scroll + L + R (4 zones) yes
Razer Basilisk Ultimate (Receiver) 1532:0088 26,000 yes Logo + Scroll + L + R (4 zones) yes
Razer Basilisk V3 1532:0099 26,000 yes Logo + Scroll, static/spectrum n/a
Razer Basilisk V3 Pro (Wired) 1532:00AA 30,000 yes Logo + Scroll, static/spectrum yes
Razer Basilisk V3 Pro (Wireless) 1532:00AB 30,000 yes Logo + Scroll, static/spectrum yes
Razer Basilisk V3 X HyperSpeed 1532:00B9 18,000 yes Scroll (1 zone) yes
Razer Basilisk V3 35K 1532:00CB 35,000 yes Logo + Scroll, static/spectrum n/a
Razer Basilisk V3 Pro 35K (Wired) 1532:00CC 35,000 yes Logo + Scroll, static/spectrum yes
Razer Basilisk V3 Pro 35K (Wirelss) 1532:00CD 35,000 yes Logo + Scroll, static/spectrum yes
Razer Basilisk Mobile (Wired) 1532:00D3 18,000 yes none yes
Razer Basilisk Mobile (Receiver) 1532:00D4 18,000 yes none yes
Razer Basilisk V3 Pro 35K Phantom Green (Wired) 1532:00D6 35,000 yes Scroll (1 zone) yes
Razer Basilisk V3 Pro 35K Phantom Green (Wireless) 1532:00D7 35,000 yes Scroll (1 zone) yes
Razer Viper 1532:0078 20,000 yes Logo (1 zone) n/a
Razer Viper Ultimate (Wired) 1532:007A 20,000 yes Logo (1 zone) yes
Razer Viper Ultimate (Wireless) 1532:007B 20,000 yes Logo (1 zone) yes
Razer Viper 8KHz 1532:0091 20,000 no Logo (1 zone) n/a
Razer Viper Mini SE (Wired) 1532:009E 30,000 no none yes
Razer Viper Mini SE (Wireless) 1532:009F 30,000 no none yes
Razer Viper V2 Pro (Wired) 1532:00A5 30,000 yes none yes
Razer Viper V2 Pro (Wireless) 1532:00A6 30,000 yes none yes
Razer Viper V3 HyperSpeed 1532:00B8 30,000 yes none yes
Razer Viper V3 Pro (Wired) 1532:00C0 35,000 yes none yes
Razer Viper V3 Pro (Wireless) 1532:00C1 35,000 no none yes
Razer Naga 1532:0015 n/a yes none n/a
Razer Naga Epic 1532:001F n/a yes none yes
Razer Naga 2012 1532:002E n/a yes none n/a
Razer Naga Hex (Red) 1532:0036 n/a yes none n/a
Razer Naga Epic Chroma 1532:003E 8200 yes none yes
Razer Naga Epic Chroma Dock 1532:003F 8200 yes none yes
Razer Naga 2014 1532:0040 8200 yes none n/a
Razer Naga Hex 1532:0041 n/a yes none n/a
Razer Naga Hex V2 1532:0050 16,000 yes none n/a
Razer Naga Chroma 1532:0053 16,000 yes none n/a
Razer Naga Trinity 1532:0067 16,000 yes Matrix (1 zone), static n/a
Razer Naga Left-Handed Ed. 2020 1532:008D 16,000 yes Logo + Scroll + R (3 zones) n/a
Razer Naga Pro (Wired) 1532:008F 20,000 yes Logo + Scroll (2 zones) yes
Razer Naga Pro (Wireless) 1532:0090 20,000 yes Logo + Scroll (2 zones) yes
Razer Naga X 1532:0096 18,000 yes Scroll + Left (2 zones) n/a
Razer Naga V2 Pro (Wired) 1532:00A7 30,000 yes Logo (1 zone) yes
Razer Naga V2 Pro (Wireless) 1532:00A8 30,000 yes Logo (1 zone) yes
Razer Naga V2 HyperSpeed (Recv.) 1532:00B4 30,000 yes none yes
Razer Abyssus 1800 1532:0020 n/a yes none n/a
Razer Abyssus 2014 1532:0042 n/a yes none n/a
Razer Abyssus V2 1532:005B 5000 yes none n/a
Razer Abyssus 2000 1532:005E 2000 yes none n/a
Razer Abyssus Elite (D.Va Edition) 1532:006A 7200 yes Logo (1 zone) n/a
Razer Abyssus Essential 1532:006B 7200 yes Logo (1 zone) n/a
Razer Imperator 2012 1532:002F 6400 yes none n/a
Razer Ouroboros 2012 1532:0032 8200 yes none yes
Razer Taipan 1532:0034 8200 yes none n/a
Razer Diamondback Chroma 1532:004C 16,000 no none n/a
Razer Atheris (Receiver) 1532:0062 7200 yes none yes
Razer HyperPolling Wireless Dongle 1532:00B3 30,000 no none yes
Razer Pro Click (Receiver) 1532:0077 16,000 yes none yes
Razer Pro Click (Wired) 1532:0080 16,000 yes none yes
Razer Pro Click Mini (Receiver) 1532:009A 12,000 yes none yes
Razer Pro Click V2 Vertical Ed. (Wired) 1532:00C7 30,000 yes Matrix (1 zone), static/spectrum yes
Razer Pro Click V2 Vertical Ed. (Wireless) 1532:00C8 30,000 yes Matrix (1 zone), static/spectrum yes
Razer Pro Click V2 (Wired) 1532:00D0 30,000 yes Matrix (1 zone), static/spectrum yes
Razer Pro Click V2 (Wireless) 1532:00D1 30,000 yes Matrix (1 zone), static/spectrum yes
Razer Orochi 2011 1532:0013 n/a no none n/a
Razer Orochi 2013 1532:0039 6400 yes none n/a
Razer Orochi Chroma 1532:0048 8200 yes none n/a
Razer Orochi V2 (Receiver) 1532:0094 18,000 yes none yes
Razer Orochi V2 (Bluetooth) 1532:0095 18,000 yes none yes

Polling rates supported on every model: 125 / 500 / 1000 Hz. The 4 / 8 kHz rates available on some Pro models use a different command path and are not wired up yet.

Some older Naga models list n/a DPI / none lighting because their pre-Chroma protocol (1-byte DPI, on/off LEDs) or non-extended matrix path (Naga Chroma, Naga Hex V2, Epic Chroma) needs command builders umbra does not ship yet; those PIDs are still recognized by umbra info, and the missing builders are tracked as follow-up work. DPI ceilings for the Naga line are sensor-derived (the OpenRazer driver does not clamp DPI) and noted as such in each model file.

Adding more devices is a matter of adding a DeviceSpec to crates/umbra-hid/src/models/, mirroring the per-PID branches in OpenRazer's razermouse_driver.c.

Build prerequisites

Linux

The hidapi crate links against libudev for HID device enumeration:

  • openSUSE: sudo zypper install systemd-devel libusb-1_0-devel pkg-config
  • Debian/Ubuntu: sudo apt install libudev-dev libusb-1.0-0-dev pkg-config
  • Fedora: sudo dnf install systemd-devel libusbx-devel pkgconf-pkg-config

macOS

No extra dependencies. The hidapi crate uses the IOKit framework that ships with the OS. Build natively:

cd rust
cargo build --release
./target/release/umbra info

Windows

No extra dependencies. The hidapi crate uses Win32's HID API. Build natively under PowerShell or cmd:

cd rust
cargo build --release
.\target\release\umbra.exe info

Cross-compilation: not provided

This repo only ships native build paths for each OS. Cross-compiling the GUI to macOS or Windows from Linux is technically possible but pulls in non-redistributable Apple SDKs or a fragile mingw + winit toolchain. CI verifies all three OS targets per push (.github/workflows/rust.yml).

Build and run (native)

cd rust
cargo build --release

# CLI: install the udev rule once, then run as your user.
./target/release/umbra udev install
./target/release/umbra info
./target/release/umbra dpi 1600
./target/release/umbra poll 1000
./target/release/umbra effect spectrum
./target/release/umbra effect static '#ff0000'
./target/release/umbra --device 1532:00a3 -vv info   # target a specific PID, verbose log

# GUI: hot-reconnects automatically when the device is replugged.
./target/release/umbra-gui

On macOS and Windows, sudo is not required.

Why no daemon and no D-Bus?

D-Bus is just IPC. Something at the bottom of the stack still has to do USB I/O. OpenRazer puts that work in a kernel module that the daemon talks to over sysfs:

client -> D-Bus -> openrazer-daemon -> sysfs -> razermouse.ko -> USB controller -> mouse

We do the USB I/O ourselves, in our process, using the HID layer the OS already ships:

us -> hidapi -> hidraw (Linux) | IOKit (macOS) | HID.dll (Windows) -> mouse

No out-of-tree kernel module, no service, no IPC.

Linux permissions

By default /dev/hidraw* is root-owned, so the CLI and GUI need sudo. The bundled udev rule grants the active local-seat user access via uaccess (no group membership needed). Install it through the CLI:

./umbra udev install     # re-execs via sudo if not already root
./umbra udev show        # print the rule body and installed status
./umbra udev uninstall   # remove and reload

The rule body lives at install_files/udev/99-umbra-userspace.rules (also embedded in the binary via include_str!). It tags every hidraw* and usb node belonging to vendor 0x1532 with uaccess, which systemd-logind translates into ACLs for the currently active session. Replug the mouse (or reboot) after install. After that, ./umbra info and ./umbra-gui work without sudo.

Wayland note: running GUI apps with sudo on Wayland fails because the compositor socket lives in the user's $XDG_RUNTIME_DIR and X authority lives in $XAUTHORITY. The udev rule is the right fix; running as root is not.