deniz.in

Markets

Weather

Loading weather

· via Hacker News – Front Page (native)

Ratatui maintainer demos terminal borders drawn on cell edges without using cells

Ratatui's maintainer has prototyped a terminal protocol that draws borders as a cell attribute rather than text, with working patches in Ghostty and Rio, freeing TUIs from spending rows and columns on box-drawing characters.

Ratatui maintainer demos terminal borders drawn on cell edges without using cells

A new take on terminal borders

The maintainer of the Ratatui terminal UI framework has published a proposal for a terminal protocol that draws thin lines on the edges of character cells, letting applications render borders, underlines and outlines without giving up a row or column of screen space. According to the post on joshka.net, which reached the Hacker News front page, the protocol is already working as a patch to the Ghostty terminal, with an earlier version implemented in Rio, and demo applications have been built with Ratatui. The author is asking terminal and TUI developers for feedback.

The cost of box-drawing characters

Terminals today draw borders using the Unicode box-drawing block, which offers 128 characters for lines, corners and joins. The author argues this is still not enough, because those characters are text: every line is a glyph that occupies an entire cell.

The consequence is space. On the author's 16-inch laptop the terminal measures roughly 200 columns by 50 rows, and a layout with a couple of levels of nested panels can easily spend six to eight of those 50 rows on nothing but lines, according to the post.

Further limitations follow from borders being text. There is no way to place a line between two cells that both contain content, so underlining a text field or outlining a button requires padding. Rounded corner glyphs carry a single background color, leaving a small square of the wrong color when a panel's background differs from its surroundings. And copying a text selection inside a box copies the box too, which anyone who has pasted from a TUI into a chat app has experienced.

Borders as a cell attribute

The proposed protocol treats a cell border as a cell attribute, similar to a background color. Each cell can carry up to twelve line segments: both halves of each of its four edges, plus four arms extending from the cell's center. Each segment has its own color, width, placement and style, and the terminal draws them over the cell grid.

Because borders are stored in the cells themselves, they scroll, erase, insert and reflow with the text. The post notes that questions about erase and scroll behavior already have answers, the same ones used for colors. Edges are split into halves so borders align with quadrant block characters, which makes it possible to outline shapes drawn half a cell in from the grid.

Lines can be solid, double, dashed or dotted, and corners and centers can be square or rounded with a configurable radius and anti-aliased arcs. A rounded corner can also specify an outside color so the area beyond the arc renders correctly against a differing background.

When two neighboring cells both place a line on their shared edge, the strokes merge, with priority, then width, then position determining the winner. The author says an earlier rule in which the right or bottom stroke always wins had to be abandoned after a focused pane lost part of its outline.

A DCS-based wire format

The protocol is carried in a single DCS escape sequence with a namespace, ESC P 1 + b cell-border ; OP ; FIELDS... ESC \. The common path uses a pen held in cursor state, like the current background color: set the pen, print text, and the printed cells acquire the borders. Rectangle commands can set or clear borders on existing cells without touching the pen, and a capability query lets applications detect support.

Detection works by sending the query followed by a standard DA1 request. If the DA1 reply arrives without a cell-border reply first, the application falls back to box-drawing characters and reserves the space they need. Terminals that do not understand the DCS sequence simply ignore it, as with any unknown DCS.

The minimum implementation is the pen, the rectangle commands and solid strokes. Line styles, rounded joints, priority and outside colors are extension fields advertised in the capability reply, and unknown fields are ignored so they can be added later. The spec labels itself version 1, which the author says should be read as v0.1 or a draft rather than something stable. The post also cites prior art, including DEC ruled lines in DECterm, and states upfront that the post and its code were written with substantial help from AI.

Suggested uses include panes and panels that avoid losing a row and column per side, menus and popups that overlay content while still reading as overlays, widgets such as text fields, buttons and checkboxes that want a line tight against their text, and chart gridlines that can sit on cell edges between braille dots instead of claiming a whole row.

Why it matters

Terminal interfaces have long been constrained by a model where everything visible must be a character. Making borders a cell attribute would let TUI applications render dense, nested layouts without paying a row and a column per panel, produce cleaner text when copied out, and draw interface elements the box-drawing set cannot express at all. The proposal is explicitly a draft seeking input, so its fate depends on whether terminal implementers beyond the Ghostty and Rio prototypes adopt it. If it does catch on, it would be one of the more visible upgrades to the terminal's drawing model in years, arriving through the same escape-sequence path that terminals have always extended.

  • #terminal
  • #tui
  • #ratatui
  • #ghostty
  • #protocol