# 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 ` or `[wifi] address` gives an explicit one; otherwise the last address that worked (`~/.config/deck-it/last-wifi`, kept across `stop` and reboots). `[display] enabled = false` skips the headless output, wayvnc and AVNC. `deck-it status` prints one JSON line for keystone's page; keep its keys. - Config: `deckit/config.py` merges `~/.config/deck-it/config.toml` over the shipped `config.toml` per key within each table (a list is replaced whole). Keystone's deck-it page (quickshell repo, `desktop/modules/deckit`) writes that sparse file and reads the defaults from `deck-it defaults`; keep that JSON shape stable. - Launchers are `[launch] apps`, desktop ids run with `gtk-launch`; label and icon come from the `.desktop` file. The client sends the id, which must be configured and installed. ## 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.