# AGENTS.md Guidance for AI coding agents working in this repository. ## What this is `deck-it` turns an Android tablet into a second monitor, a stream-deck and an always-on control surface for a Slackware Hyprland desktop. The PC serves a web page on a Unix socket and exposes it to the tablet with `adb reverse`; `wayvnc` streams a headless output to AVNC. Python 3.11+ standard library, plus `websocket-client` for obs-websocket. Plain HTML/CSS/JS frontend, bash launcher. Keep the server dependency-free apart from that one package. ## How it fits together - `deckit/server.py` is the stdlib HTTP server: it listens on `$XDG_RUNTIME_DIR/deck-it/http.sock`, serves `static/`, `/theme.css`, `/icons/.svg` and `/api/[/]`. - A module is `deckit/modules/.py` exporting `make(cfg) -> Module`; the registry discovers files lazily. `state()` is read, `actions` are allow-listed, and the client sends ids, never commands. - The page shell (`static/app.js`) builds tabs from each panel's `tab` property, mounts panels and polls `/api/`. - `deckit/theme.py` reads UDT's palette (`~/.config/rofi/udt/palette.rasi`) and `~/.cache/udt/udt-border.lua`; the frontend uses only those CSS variables. Text size is keystone's (`~/.config/keystone/fonts.json`, `override.deckit` else `base`) as `--udt-font-size` on `html`, so `deck.css` sizes text in `rem`. The shell re-reads `/theme.css` every 5s, so changes reach an open page. - Launcher icons follow the icon theme Keystone sets (`gsettings org.gnome.desktop.interface icon-theme`); window icons resolve through the `.desktop` `Icon`/`StartupWMClass` mapping. - `deckit/display.py` creates the headless output, centres it under the first monitor for `position = "auto-below"`, and paints it with the first monitor's swaybg image. - The launcher (`deck-it`) handles USB and Wi-Fi (`pair`/`wifi`), the tunnels, wayvnc and AVNC. `adb mdns` may be unsupported; `deck-it wifi ` takes an explicit address. ## Conventions - New behaviour goes in a module under `deckit/modules/`, not in the server. - Panels keep their scoped wrapper class (`.music`, `.sbb`, `.llm`, `.windows`) because the CSS is scoped to it. - Hyprland Lua: a dispatcher must be wrapped in `hl.dispatch(...)` to execute. `hyprctl eval` alone only builds the dispatcher object. - No personal data in code, docs, tests or commits; use placeholders. ## Testing python3 -m unittest discover -s tests `node --check` any changed JS file. The real hardware paths (wayvnc, adb, OBS, the tablet) are manual. ## Repo facts - License: GPLv2 only (`LICENSE`, header in each source file). - Work directly on master.