feat(ui): kitty graphics layer and terminal detection #66

Closed
opened 2026-10-08 21:55:09 -05:00 by deadstyle · 1 comment
Owner

Problem

Inline images (#60) need a terminal-graphics layer: detect kitty-protocol terminals and emit images as Unicode placeholders that scroll like text. Nothing user-visible changes in this ticket.

Acceptance criteria

  1. New package internal/ui/termimg: Support{OK, Tmux bool; CellW, CellH int}, Transmit(id, img, cols, rows, tmux) string, Place(...), Cells(id, cols, rows) []string, Delete(id, tmux) string, and an IDs LRU allocator over 16-255 that emits a delete when it reuses an ID. Exact-string tests.
  2. Transmit uses a=T,U=1,i=N,p=1,c=cols,r=rows; every placeholder cell carries row and column diacritics; the ID is a 38;5;N foreground.
  3. Detection once per session. Outside tmux: XTVERSION names kitty or ghostty and the a=q query is answered before DA1, 1s timeout. Inside tmux: allow-passthrough is on/all and client_termtype names kitty or ghostty; sequences wrapped in ansi.TmuxPassthrough. Colour profile at least ANSI256. Cell size from CSI 16 t, default 8x16. We never change the user's tmux settings.
  4. The App receives the detection messages and holds Support.
  5. A renderer test (tea.Program into a buffer, ANSI256, scrolling) asserts placeholders, diacritics and 38;5;N survive the cell-diff renderer.

Plan

Decided by Opus (design summary on #60). x/ansi v0.11.8 (already in the module graph) provides kitty.EncodeGraphics, kitty.Placeholder, kitty.Diacritic, ansi.TmuxPassthrough; it becomes a direct dependency, no new module. Opus prototyped the placeholder approach under Bubble Tea v2 + viewport scrolling: placeholders and diacritics survive the diff renderer; the image ID survives as 38;5;N under TrueColor/ANSI256 but not ANSI16.

Out of scope

Fetching (#65), markdown and details integration (later ticket), WezTerm (unverified).

Refs #60

## Problem Inline images (#60) need a terminal-graphics layer: detect kitty-protocol terminals and emit images as Unicode placeholders that scroll like text. Nothing user-visible changes in this ticket. ## Acceptance criteria 1. New package `internal/ui/termimg`: `Support{OK, Tmux bool; CellW, CellH int}`, `Transmit(id, img, cols, rows, tmux) string`, `Place(...)`, `Cells(id, cols, rows) []string`, `Delete(id, tmux) string`, and an `IDs` LRU allocator over 16-255 that emits a delete when it reuses an ID. Exact-string tests. 2. Transmit uses `a=T,U=1,i=N,p=1,c=cols,r=rows`; every placeholder cell carries row and column diacritics; the ID is a `38;5;N` foreground. 3. Detection once per session. Outside tmux: XTVERSION names kitty or ghostty and the `a=q` query is answered before DA1, 1s timeout. Inside tmux: `allow-passthrough` is `on`/`all` and `client_termtype` names kitty or ghostty; sequences wrapped in `ansi.TmuxPassthrough`. Colour profile at least ANSI256. Cell size from `CSI 16 t`, default 8x16. We never change the user's tmux settings. 4. The App receives the detection messages and holds `Support`. 5. A renderer test (tea.Program into a buffer, ANSI256, scrolling) asserts placeholders, diacritics and `38;5;N` survive the cell-diff renderer. ## Plan Decided by Opus (design summary on #60). `x/ansi` v0.11.8 (already in the module graph) provides `kitty.EncodeGraphics`, `kitty.Placeholder`, `kitty.Diacritic`, `ansi.TmuxPassthrough`; it becomes a direct dependency, no new module. Opus prototyped the placeholder approach under Bubble Tea v2 + viewport scrolling: placeholders and diacritics survive the diff renderer; the image ID survives as `38;5;N` under TrueColor/ANSI256 but not ANSI16. ## Out of scope Fetching (#65), markdown and details integration (later ticket), WezTerm (unverified). Refs #60
Author
Owner

🤖 merged: #70

🤖 merged: https://git.bobparsons.dev/deadstyle/lazyforge/pulls/70
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
deadstyle/lazyforge#66
No description provided.