Please help me install and set up "Rufous" from veered.org on my own computer or server. What it is: Map extra mouse buttons to keys, shortcuts and commands. It runs on: Any Linux desktop — it works underneath the desktop, so it does not matter which one you use. Project page: https://veered.org/linux-mouse-button-remap/ Source code download (zip): https://veered.org/linux-mouse-button-remap/rufous-mouse-remap.zip How I'd like you to help: 1. First ask me what you need to know: my operating system and version, my desktop environment if it matters, whether I'm comfortable with the terminal, and any accounts or hardware this project needs. 2. Then take me through it one step at a time. For each command, say briefly what it does, and wait for me to paste back the result before moving on. 3. Before any step that changes system settings, uses sudo, or edits an existing configuration file, tell me, and have me make a backup first. 4. If something fails, help me work out why. If the instructions below don't fit my system, say so rather than guessing. 5. At the end, show me how to check that it works, and how to uninstall it. The project is shared as-is by its author, with no warranty. If we find a problem in the project itself, please help me write a short, clear note I can send to support@veered.org. Here is the project's documentation (README files from the download): ===== README.md ===== # Linux Mouse Button Remapper (Rufous) *Why Rufous? A red-brown found in the names of small animals, like the rufous mouse lemur.* **Runs on** any Linux desktop — it works underneath the desktop, so it does not matter which one you use. **Version 1.0.** Part of [Veered](https://veered.org): free tools, shared as-is. Questions: support@veered.org Map a mouse's extra buttons to clicks, keys, shortcuts, commands and hold-to-shift layers on Wayland. `mouse-remap` grabs one physical mouse through evdev and re-emits its events through uinput virtual devices, so it works under COSMIC or any other compositor. X11 tools such as `xbindkeys` and `xinput` do nothing on Wayland. Behaviour comes from a small TOML profile. A profile for the **Evoluent VerticalMouse D** is included, as is a commented template for any other mouse. ![A mouse profile, and the check that validates it](docs/screenshot.jpg) *A profile is a small text file: one line per button. `--check` tells you it is sound before you use it.* ## Please test before relying on it This is shared as-is, with no warranty. It works on my own computers, but your system, settings and software versions may differ, so please try it in a safe setting first. If something doesn't work, you can ask Claude (or another AI coding assistant) to look into it, and I'd appreciate hearing what you found and how you fixed it. You are also welcome to just let me know at support@veered.org, and I'll look into it. ## Information for nerds: requirements, install, profiles and permissions - Python 3.11 or newer (for `tomllib`) and python-evdev: `sudo apt install python3-evdev` - Read access to the mouse's `/dev/input/event*` node and write access to `/dev/uinput` (see [Permissions](#permissions)). - Do not run another remapper (input-remapper, keyd, etc.) on the same mouse; only one program can grab it. ### Install ```bash ./install.sh --profile evoluent-verticalmouse-d # or: --profile generic-example sudo ./install-udev-rule.sh --profile ~/.config/cosmic-tools/mouse-remap.toml systemctl --user daemon-reload && systemctl --user enable --now mouse-remap journalctl --user -u mouse-remap -f # watch it work ``` `install.sh` puts the program in `~/.local/share/cosmic-tools/mouse-remap` (linked from `~/.local/bin/mouse-remap`), copies the profile to `~/.config/cosmic-tools/mouse-remap.toml` unless one exists, and installs a systemd **user** unit. Pass `--enable` to start the service straight away. After editing the profile: `mouse-remap --check`, then `systemctl --user restart mouse-remap`. ### Making a profile for your mouse ```bash mouse-remap --list-devices # find the name or vendor:product cp profiles/generic-example.toml ~/.config/cosmic-tools/mouse-remap.toml $EDITOR ~/.config/cosmic-tools/mouse-remap.toml # set [device] mouse-remap --identify # press buttons to see their codes mouse-remap --check # validate ``` `--identify` reads without grabbing, so the buttons still do their normal thing while you test. ### Profile format ```toml [device] # all given fields must match name = "VerticalMouse" # case-insensitive substring of the device name vendor = 0x1a7c # USB ids, as shown by lsusb or --list-devices product = 0x0197 # path = "/dev/input/by-id/usb-...-event-mouse" # or one exact node [options] scroll_divisor = 1.6 # 1 = unchanged, 2 = half speed; remainders carry over click_gap_ms = 50 # between synthetic clicks click_hold_ms = 15 # how long each synthetic click is held key_gap_ms = 30 # between the keys of a combo [buttons] # buttons not listed pass through untouched BTN_MIDDLE = { click = 2 } BTN_SIDE = { button = "BTN_RIGHT" } BTN_FORWARD = { combo = ["KEY_LEFTMETA", "KEY_W"] } [layers.BTN_EXTRA] # hold BTN_EXTRA to shift; tap it for `tap` tap = { key = "KEY_PLAY" } scroll_up = { key = "KEY_PAGEUP" } scroll_down = { key = "KEY_PAGEDOWN" } [layers.BTN_EXTRA.buttons] BTN_LEFT = { exec = ["wpctl", "set-volume", "@DEFAULT_AUDIO_SINK@", "5%-"] } ``` Buttons are evdev names (`BTN_LEFT`, `BTN_RIGHT`, `BTN_MIDDLE`, `BTN_SIDE`, `BTN_EXTRA`, `BTN_FORWARD`, `BTN_BACK`, `BTN_TASK`) or numeric codes as strings (`"280"`). Key names come from [`linux/input-event-codes.h`](https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h) (`KEY_VOLUMEUP`, `KEY_LEFTCTRL`, ...). | Action | Effect | | --- | --- | | `"pass"` | Leave the button alone | | `"disable"` | Swallow the button | | `{ click = N }` | N left clicks (1 to 5) | | `{ button = "BTN_..." }` | Act as another mouse button, including press-and-hold | | `{ key = "KEY_..." }` | Tap a key | | `{ hold_key = "KEY_..." }` | Hold a key for as long as the button is held | | `{ combo = ["KEY_A", "KEY_B"] }` | Press keys in order, release in reverse | | `{ exec = ["prog", "arg"] }` | Run a program (argument list, no shell) | Layers: while a layer button is held, buttons listed under the layer and the wheel use the layer's actions; other buttons keep their normal mapping. Releasing the layer button without having used the layer fires `tap`. Holding the layer button while scrolling swallows both the coarse and the hi-res wheel streams, so the page does not also scroll. Tips: - Desktops can intercept media keys through their own shortcut settings. If a `KEY_VOLUMEUP` mapping appears to do nothing, check the desktop's keyboard shortcuts, or use `exec` with `wpctl` or `playerctl` instead. - Commands from `exec` run as your user with the service's environment. A systemd user service has your session bus, so `wpctl`, `playerctl` and `notify-send` work. ### Permissions `mouse-remap` needs to read one input device and write `/dev/uinput`. Pick one: 1. **udev rule (recommended).** `sudo ./install-udev-rule.sh --profile FILE` (or `--vendor 1a7c --product 0197`, or `--name "Device Name"`) writes `/etc/udev/rules.d/70-mouse-remap.rules`, which tags `/dev/uinput` and just that mouse with `uaccess`, so the user at the active local seat gets access. It also loads the `uinput` module at boot. Use `--dry-run` to see the rules first and `--remove` to undo. Unplug and replug the mouse afterwards. 2. **`input` group.** `sudo usermod -aG input $USER`, plus a rule giving the group `/dev/uinput` (`KERNEL=="uinput", GROUP="input", MODE="0660"`), then log out and in. Simpler, but it lets every program you run read **every** input device, keyboards included. Either way, write access to `/dev/uinput` lets programs you run inject input events. That is inherent to any uinput remapper; running it as root instead does not reduce the risk. ### Uninstall ```bash systemctl --user disable --now mouse-remap ./uninstall.sh # keeps your profile; --purge deletes it sudo ./install-udev-rule.sh --remove ``` ### Tests ```bash python3 -m unittest discover -s tests -v ``` The tests exercise every gesture of the Evoluent profile, the profile loader and its error messages, and the installer in a throwaway HOME. They open no input devices and create no uinput devices. ## Information for nerds: the files | File | Purpose | | --- | --- | | `mouse-remap` | The daemon and CLI (grab, re-emit, `--check`, `--identify`, `--list-devices`) | | `remap_logic.py` | Pure decision logic: events in, actions out. Change behaviour here. | | `remap_profile.py` | TOML profile loader and validator | | `profiles/` | Evoluent VerticalMouse D profile and a generic template | | `systemd/mouse-remap.service` | systemd user unit | | `install-udev-rule.sh` | Optional root step for device permissions | ----- For Claude Code users ----- Download https://veered.org/linux-mouse-button-remap/rufous-mouse-remap.zip, unzip it into a new folder, read every README.md in it, and help me install and set up "Rufous" (Map extra mouse buttons to keys, shortcuts and commands) on this machine. Check the requirements against this system first and tell me what is missing. Ask me before running anything with sudo, installing packages, or changing existing configuration files, and back those files up first. Finish by showing me how to test it and how to uninstall it.