wasm-pack build --target web rs/adapters/browsernpx serve rs/adapters/browser # or: python -m http.server -d rs/adapters/browserThen open
http://localhost:3000/www/ (or the port your server uses).
Hotkey Reference
| CLX‑Edit (cursor) | |
| HJKL | ← ↓ ↑ → (accel) |
| Y / O | Home / End |
| U / I | Page Up / Down |
| G | Enter |
| T | Delete |
| N / P | Focus next / prev |
| CLX‑Mouse (virtual cursor) | |
| WASD | Move virtual cursor |
| R / F | Scroll up / down at cursor |
| E / Q | Left / Right click (visual only) |
| CLX‑Media (F5–F11) | |
| F5 | Play / Pause |
| F6 / F7 | Prev / Next track |
| F8 | Stop |
| F9 / F10 | Volume + / − |
| F11 | Mute |
| Trigger keys | |
| CapsLock | Hold to activate |
| Space | Hold to activate |
| CapsLock+Space | Lock CLX (tap either to unlock) |
Cursor / Edit Test · hold CapsLock then use HJKL
Key Log — events that reached the page (CLX-intercepted keys are absent)
Scroll box · CLX + R / F
How it works
Hook: capture-phase keydown/keyup listeners on window.
Intercepted events get preventDefault() + stopPropagation().
Cursor (HJKL): synthetic ArrowLeft/Right/Up/Down dispatched on the
focused element. isTrusted=false but browsers still move the text cursor.
Virtual mouse (WASD): WASM dispatches clx:mouse_move [dx,dy];
JS renders a cursor overlay and moves it. Real mousemove snaps it back.
Scroll (R/F): WASM dispatches clx:scroll_v/h;
JS walks up from elementFromPoint(vx, vy) to find the nearest
scrollable ancestor and calls scrollBy on it.
Focus (N/P): WASM dispatches clx:focus ±1;
JS cycles through querySelectorAll of all tabbable elements.
Focus test · CLX + N (next) / P (prev)
Virtual cursor: hold CLX + WASD to move the crosshair cursor. Move it over the scroll box above, then CLX+F to scroll that box, not the page. Real mouse movement instantly snaps the virtual cursor back.