Pixeye Pokey — Make them SEE it.
An Omarchy plugin that clones https://pokeyapp.com/ — a giant hand + arm that takes over your cursor during screenshares, taps with a knock on every click, and has a presentation mode where clicks only poke.
Uses Pokey's actual hand art and knock sound (extracted from pokeyapp.com).
Install
omarchy plugin add https://github.com/pixeye33/omarchy-pokey.git --enable
Then add the keybindings to ~/.config/hypr/bindings.lua:
o.bind("SUPER + U", "Pokey: toggle hand", "omarchy-shell shell call pixeye.pokey toggle \"\"")
o.bind("SUPER + SHIFT + U", "Pokey: cycle mood", "omarchy-shell shell call pixeye.pokey cycleMode \"\"")
o.bind("SUPER + CTRL + U", "Pokey: presentation mode", "omarchy-shell shell call pixeye.pokey togglePresentation \"\"")
o.bind("SUPER + CTRL + SHIFT + U", "Pokey: cycle size", "omarchy-shell shell call pixeye.pokey cycleSize \"\"")
The ALT+click "poke only" bind needs no config: the plugin adds and removes
it at runtime, only while the hand is on.
Requires membership in the input group for click/tap detection (see Requirements).
Remove
omarchy plugin remove pixeye.pokey
Then delete the three o.bind(...) lines from ~/.config/hypr/bindings.lua.
(The ALT+click mouse bind is managed by the plugin at runtime and needs no
cleanup.)
How it works
- The real OS cursor is hidden with Hyprland's runtime
cursor:invisibleflag instead of being replaced by a themed sprite. Because the active cursor theme is never swapped, the pointer is back to normal automatically on the next login/reboot — no invisible theme lingers on disk to break it.pokey_input.pykeeps watching the flag while the hand is on and re-hides the cursor if anything restores it (e.g. the Omarchy screensaver resetscursor:invisibletofalsewhen it exits), so the hand stays the only pointer. - A full-screen Quickshell overlay draws Pokey's hand + arm, fingertip parked exactly on the pointer, tracking it smoothly across all monitors. It re-creates its surface only when another overlay (menu, notification, OSD) maps above it, so it stays the topmost layer with no flicker.
- A background helper (
pokey_input.py) reads the pointer input devices (/dev/input/event*, needs theinputgroup) so it can see every click without consuming it — apps keep receiving clicks normally. Only devices with button/touch capabilities are opened (mice, clickpads, touchpads, touchscreens); keyboards are never opened, so the helper has no access to keystrokes. Physical button presses are read straight from evdev, and touchpad taps are reconstructed from the raw finger-contact events (one finger → left, two → right, three → middle), since the compositor's libinput turns taps into clicks internally and never exposes them on evdev. - On every click the hand jabs forward, ink-burst ripples ring out from the fingertip, and the knock sound plays. Click faster and the pokes get wilder, matching your energy.
- Presentation mode is the real Pokey trick: the overlay grabs all clicks, so clicks only make the hand tap — they never advance a slide, open a link, or select anything. Your keyboard stays fully live.
- ALT + click is "poke only" on demand, without presentation mode: hold
ALTand click (or tap) and the hand pokes while the click never reaches the app underneath — handy for a quick "look at this" during a share. While the hand is on, the plugin adds a Hyprland mouse bind that consumesALT+left-click and removes it again when the hand is turned off, soALT+click behaves normally whenever Pokey is off. The overlay still animates because the helper sees the press on the pointer device.
Keybindings
| Keys | Action |
|---|---|
SUPER + U |
Toggle the hand on/off |
SUPER + SHIFT + U |
Cycle the hand design (Classic → Sleek → Bold) |
SUPER + CTRL + U |
Toggle presentation mode |
SUPER + CTRL + SHIFT + U |
Cycle the hand size (187 → 281 → 425 px) |
Bar widget
A pixeye.pokey bar widget ships with the plugin — a hand icon in the bar
that mirrors the overlay state (mode and on/off) and opens a menu on click:
- Left click opens the Pokey menu.
- Right click toggles the overlay on/off directly.
- Scroll cycles the hand size (any size works with any mode).
- The menu lets you pick a hand mode (Classic / Sleek / Bold), pick a hand size (187 / 281 / 425 px), turn Pokey off, or flip presentation mode.
The icon is dimmed and tinted with the bar's foreground while Pokey is off;
it lights up with the accent color and shows the selected hand while on.
State is polled from the overlay every few seconds, so hotkey-driven changes
(SUPER+U etc.) show up on the icon without interaction.
To place it elsewhere, move the widget like any other: omarchy bar move pixeye.pokey --section left.
Note: because the shell's QML hot-reload can't clear its type cache on
newer Qt, edits to the plugin's QML files need an omarchy restart shell
to take effect.
Hand designs & size
Mode and size are independent — any of the three hand designs can be shown at any of the three sizes. The design (Classic / Sleek / Bold) picks which hand+arm art from pokeyapp.com's "It actually clicks" feature SVG is used; the size (187 / 281 / 425 px tall) picks how big it is rendered. The fingertip hotspot and aspect are properties of the design, so the finger always lands exactly on the pointer at every size.
- Classic — the hero hand (the default cursor from the site's hero).
- Sleek — a second design.
- Bold — a third, bolder design.
IPC
Everything is reachable through the Omarchy shell:
omarchy-shell shell call pixeye.pokey toggle ""
omarchy-shell shell call pixeye.pokey cycleMode ""
omarchy-shell shell call pixeye.pokey setMode 2
omarchy-shell shell call pixeye.pokey cycleSize ""
omarchy-shell shell call pixeye.pokey cycleSizeBack ""
omarchy-shell shell call pixeye.pokey setSize 425
omarchy-shell shell call pixeye.pokey togglePresentation ""
omarchy-shell shell call pixeye.pokey status ""
status returns JSON:
{"on":bool,"mode":1-3,"modeName":"...","size":187|281|425,"presentation":bool,"pointer":[x,y]}.
Files
| File | Purpose |
|---|---|
manifest.json |
Plugin manifest (overlay + bar widget, keep-loaded) |
Overlay.qml |
The plugin: overlay windows, hand + arm, jab/ripple animation, presentation mode, IPC |
BarWidget.qml |
Bar icon: hand preview per mode, on/off state, hosts the menu panel |
Panel.qml |
The bar menu: mode selection, enable/disable, presentation toggle |
FlashRipple.qml |
The ink-burst ripple component (flash-1..5) |
pokey_input.py |
Background pointer tracker + click listener (evdev + touchpad-tap reconstruction) + raise detection + cursor-reappearance watch |
ensure_assets.py |
Prepares the runtime assets: renders the hand PNGs (idempotent, skipped when fresh) |
hand-meta.json |
Per-hand canvas aspect + fingertip hotspot |
hand1.svg, hand2.svg, hand3.svg |
The three hand + arm designs |
tap-series.wav |
Pokey's knock sound from pokeyapp.com |
assets/ |
Hand + arm PNGs (3 designs × 3 sizes) + flash SVGs |
Requirements
hyprctl(Hyprland),paplay(PipeWire/PulseAudio) for the knock,python3.- The user must be in the
inputgroup sopokey_input.pycan read/dev/input/event*for click detection. It only ever opens pointer devices (mice, touchpads, touchscreens); keyboards are never opened, so it has no access to keystrokes. Without the group, motion still works (viahyprctl cursorpospolling) but clicks won't trigger taps/sound. rsvg-convertis only needed to regenerate the assets.
Notes
- The hand renders on the
Overlaylayer, so it shows up in every screen share and recording — including the bar and fullscreen apps. - Clicks are detected passively; nothing is intercepted in normal mode, so click, drag, select: everything works exactly as before.
- Tap tuning: a contact counts as a tap when it lasts under
TAP_TIMEOUT(0.25 s) and travels less thanTAP_MOVE_MM(5 mm), matching libinput's defaults. SetPOKEY_DIAG=1when runningpokey_input.pyto tag each click assrc: taporsrc: buttonwhile tuning.