Skip to content

UI rendering artifacts (duplicated/offset rows) in Ghostty 1.3 with grapheme-width-method = unicode #327

@Abeansits

Description

@Abeansits

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)

Screenshots
Image

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions