# Assistant canvas: design Date: 2026-10-16. Status: approved in brainstorming, not implemented. ## Goal A Luma-style conversation canvas for the local text assistant, after the model of Modesty's Luma (read for ideas only, never copied: Modesty is GPLv3). SUPER+Home opens a centred card over DP-1 with the conversation, an input and the history. It takes llamachat's place on that bind while it is tested. The canvas is only a view. desktop-assistant is the daemon that owns the model, the tools and the history; its protocol and storage are specified in that repo, `docs/superpowers/specs/2026-10-16-text-daemon-design.md`. ## Out of scope for v1 Voice, a model picker, attachments, launcher or file search, desktop actions with review. Each can come later without reshaping the canvas. ## Where it lives `desktop/assistant/`, inside the `desktop` process like `island/`. The canvas does not need the drawer or the island, but living in the integrated process means one keepalive window and one restart path. - A `PanelWindow` on DP-1, layer overlay, `ExclusionMode.Ignore`, `WlrLayershell.keyboardFocus: Exclusive` while shown, namespace `quickshell-assistant`. Frosting comes from a `blur-assistant` layer rule in hypr-theme's `sections/decorations.lua`. - `IpcHandler { target: "assistant" }` with `toggle()`. The bind is `qs -p /desktop ipc call assistant toggle`. - Key events reach a focused item, not the window (AGENTS.md), so Escape and Enter are handled on the input. ## Connection A `Socket` on `$XDG_RUNTIME_DIR/desktop-assistant.sock` with a `SplitParser`, inside a `LazyLoader` that is toggled off and on to retry, because a `Socket` whose connect failed never retries in Quickshell 0.3.1. The retry runs every 2s while disconnected, as the old overlay did. While disconnected the card shows one line, "assistant not running", and the input is disabled. `hello` on connect redraws the current conversation, so a daemon restart or a canvas reopened mid-reply catches up. ## Layout A centred card, about 760px wide and 70% of the screen high, with the theme's surface colour and translucency. - **Header:** the model name, the context meter (`ctx` used of max, amber at 75%, red at 90%, as llamachat does), a History button, a New button. - **Body:** a `ListView` of turns, following the bottom while a reply streams unless the user has scrolled up. - **Footer:** a multi-line input. Enter sends, Shift+Enter inserts a newline, Escape closes the card. While a reply streams, a Stop button replaces Send. - **History:** a panel that slides over the body. A search field on top, the conversation list below; each row is a title, a date and a delete button. Clicking a row sends `open` and closes the panel. With text in the field the list shows `results` with their snippets; clearing the field shows `conversations` again. Escape closes the panel before it closes the card. ## Messages - `desktop/assistant/Md.js` splits a message into segments: prose, and fenced code `{lang, text}`. An unclosed fence, which is normal while a reply streams, yields a code segment marked open. - Prose renders in a read-only `TextEdit` with `textFormat: TextEdit.MarkdownText`: selectable, unlike `Text`. - A code segment renders monospace on a tinted block with a copy button that runs `wl-copy`. An open segment has no copy button yet. - User messages go through the same renderer. - Thinking (`think` deltas) shows as one collapsed `▸ thinking` line above the reply, expanded on click, labelled live while it streams. A resumed conversation has no thinking: the daemon does not store it. - A tool call shows as a chip with the tool's name, dimmed when `done`. - `error` shows as a line in `Theme.red`. Glyphs come from `Theme.iconFamily` and must exist in Inconsolata Nerd Font. ## Switch-over - `git rm -r assistant/`, the voice overlay. AGENTS.md's tree line and the `Socket` retry note's file reference move to `desktop/assistant/`. - `desktop/modules/ai/README.md`: the desktop-assistant row stays; the line about status failing when the overlay is down goes. - hypr-theme (the live config, linked from `~/.config/hypr`): `sections/autostart.lua` starts the daemon and drops the commented overlay line, `llamachat --daemon` stays; `sections/keybindings.lua` rebinds SUPER+Home to the IPC toggle; `sections/decorations.lua` gains `blur-assistant`. Then `hyprctl reload`. - A new directory under `desktop/` is a new import, so the running desktop shell needs a restart from the user's terminal (`./reload.sh desktop`). Order: the daemon first (testable alone with `socat`), then the canvas, then the switch-over. Work goes on master in all three repos. ## Testing `node desktop/assistant/test_md.js`: plain prose, one fence, two fences, a fence with a language, an unclosed fence, inline backticks that are not a fence, a fence inside a list item. Visual checks are the user's: the card, streaming, the thinking line, copy, the history panel and search.