-
Notifications
You must be signed in to change notification settings - Fork 194
Description
Description
When navigating the session list with arrow keys, rows render with increasing vertical offset, causing duplicated/ghosted lines for groups, sessions, and the bottom status bar. The effect compounds as you scroll further down the list.
This occurs in Ghostty 1.3 which defaults grapheme-width-method = unicode. The same agent-deck version renders correctly in Ghostty with grapheme-width-method = legacy, and on other setups with older Ghostty versions.
Environment
- agent-deck: v0.25.1
- Ghostty: 1.3.0 (stable, Metal renderer, macOS)
- tmux: 3.6a
- OS: macOS (Darwin 25.3.0)
Root Cause Theory
The rendering chain is Bubble Tea (go-runewidth) → tmux → Ghostty, and all three calculate character widths independently.
In my agent-deck setup I use emojis for session identifiers and some statuses are also rendered using emojis by agent-deck. When Ghostty 1.3 uses its unicode grapheme width mode, it may allocate 2 cells for an emoji that go-runewidth v0.0.16 counts as 1 cell (or vice versa). This per-character drift accumulates line by line, so Bubble Tea's incremental redraws write content at the wrong vertical positions, this produces the duplicated/offset rows.
This seem very much like this is a known issue with go-runewidth:
- mattn/go-runewidth#59 — "Width is 1 when it should be 2" (open since 2022)
- mattn/go-runewidth#39 — "Wrong width for flag symbols" (open since 2021)
go-runewidth calculates widths using the first rune only, which breaks for grapheme clusters (emoji with modifiers, ZWJ sequences, variant selectors).
Workaround
Adding grapheme-width-method = legacy to Ghostty config forces POSIX wcswidth() width tables, which align with what tmux and go-runewidth expect. This fixes rendering but downgrades Unicode handling globally for all terminal apps.
Proposed Solutions
Medium effort (?) - Bubble Tea v2 upgrade:
Bubble Tea v2.0 (released recently) ships a new "Cursed Renderer" built on charmbracelet/x/cellbuf, based on the ncurses rendering algorithm. It was specifically designed to fix this class of width calculation bugs. The upgrade path is documented in the official upgrade guide. agent-deck currently uses Bubble Tea v1.3.10. Not sure what the lvl of effort would be here.
Largest effort - Mode 2027 negotiation:
Unicode mode 2027 allows the terminal and application to agree on which Unicode width tables to use at runtime. Ghostty supports it; once the Charm ecosystem adds support, this would resolve the mismatch permanently.
