Architecture Decision Records for deckd, in numbered chronological order.
Config key strings (e.g. ctrl+t) are parsed as physical evdev key names with no keymap translation. On non-QWERTY layouts users may need to specify physical keys rather than the character they see.
The client sends jog_end with release velocity; the daemon owns the decay loop. All clients inherit correct momentum behavior without reimplementing it.
Client has fixed chrome always visible: right-side full-height jogstrip (suppressible per-deck) and bottom strip with app badge + controls. Per-app decks render in the remaining space.
Decks authored in landscape. Portrait transposes every widget's grid diagonally [x,y,w,h] -> [y,x,h,w]. Same buttons, same arrangement, cells sized for the surface.
Superseded by: 0010 — there is no fixed grid shape to author against
0005-dynamic-widget-state-future.md
Protocol is stateless per widget now. Planned: delta updates to widget properties (label, icon, value) without replacing whole deck. Primary driver: MPRIS live state.
Widgets carry color and icon attributes. Daemon treats them as opaque strings; client bundles Lucide (glyphs) + Simple Icons (brand logos).
Amends: 0003 — presentation is a second class of info the daemon carries without interpreting
0007-chrome-app-identity-badge.md
Bottom chrome's app badge carries display_name, theme (CSS colour), and icon from the deck YAML. Daemon relays verbatim; no .desktop file or web resolution.
Extends: 0006 — presentation-relay seam reaches per-deck now, not just per-widget
A client can pin its session to a specific deck via select_view. Daemon pushes a view-tagged DeckMessage. Created for MPRIS now-playing; general mechanism for future chrome views.
Amends: 0003 — chrome knowledge now includes payload-per-view content delivered by the daemon
Replace --host with repeatable --bind supporting literal IPs and iface:<name>. Default 127.0.0.1 + ::1. Localhost-only by default; LAN reachability is opt-in.
Widgets become an ordered list that reflows to the viewport; grid: [x,y,w,h] coordinates and the portrait transpose are deleted. Cell size is a client-side device preference, never authored in deck YAML.
Supersedes: 0004 — authored coordinates + diagonal transpose Superseded by: 0011 — the sizing geometry, the band, and the overflow default
Sizing picks the row count that makes cells largest, using both axes, so no tuned constants remain. Rows fill to the column count with the remainder in the bottom row; the grid block centres on both axes with rows washed left. minCell / maxCell gain distinct jobs, and overflow becomes a device setting defaulting to clip.
Supersedes: 0010 — keeps the ordered-list model, replaces the geometry
0012-linux-distribution-appimage.md
AppImage is the primary Linux artifact (unsandboxed, distro-agnostic); the root-only uinput step is a first-run pkexec/sudo helper shared by all channels. Flatpak/Snap are rejected — a sandbox cannot write the udev rule, see /dev/uinput, reach the session bus unfiltered, or install the compositor plugin. deb/rpm remain a later thin wrap of the same relocatable tree.