Grok Does Not Speak Gamepad
The Grok TUI is a keyboard. Enter sends. Esc cancels. Ctrl+P opens the palette. F8 starts dictation. That is the whole contract.
A Nintendo Switch Pro Controller on the desk does not speak that language. Linux sees buttons and axes. Grok sees keycodes. Nothing in the middle.
So I wrote the middle.
What this is
grok-pad is a small Python daemon. It watches hid-nintendo evdev nodes (and Switch 2 hidraw, which hid-generic leaves silent until a USB handshake runs). When a Hyprland window title or class contains grok, it injects the keys Grok already knows through uinput.
Home toggles the mapper. Off, the pad is inert. On, A is Enter, B is Esc, X is the palette, Y is dictation, Plus is model/multiline, d-pad is arrows.
It also pairs over Bluetooth (grok-pad pair), talks to DualSense and a Flipper in Keynote HID mode, and — because this machine runs Omarchy — uses the shoulders and sticks for terminals, workspaces, and screenshots. Those extras no-op if Omarchy is not there. The Grok map still works.
grok-pad # daemon
grok-pad pair # Bluetooth scan + pair + trust + connect
grok-pad status # attached pads + Grok focus
USB-C also works. Plug it in.
What I learned building it
The Switch 2 Pro was the actual problem. Linux enumerates 057e:2069. Then nothing happens. The pad stays mute until Nintendo's USB init sequence runs in userspace. That helper is forty-odd lines of pyusb. Without it, the rest of the mapper looks broken when the hardware is fine.
Focus-gating was the other one. A pad that always types into whatever has focus is a footgun. Checking hyprctl activewindow and refusing to inject unless Grok is in front is the whole product. The Home toggle is for when you want the extras without a Grok window.
I kept the process as a systemd user unit, not a Hyprland exec, so a crash restarts it and pairing stays a separate command.
The larger question
A controller should not need the app to grow a gamepad API. The app already has keys. The mapper should speak those keys, stay quiet when you did not ask, and leave your data on the machine.
Does this empower or extract? It maps a pad you already own onto a TUI you already run. No account. No telemetry. MIT.
Code: github.com/HermeticOrmus/grok-pad
-- Ormus