← Writing

Core Swap · Part 3 of 5

Sealed Weights

Brief

The first ranking of cores for Terminal Delight put wezterm-term three hundredths ahead of rio-vt, on weights the agent building it had guessed. Reading it, I wasn’t sold on any of them. Ghostty had the popularity pull, the other two were dark horses, and nothing had judged them on what Terminal Delight is for.

So I answered four questions about what matters, and my answers went into a file before the next test produced a number. Speed and memory came first, then whether an agent can work on the core fluently, since I will never read it, then a published package used as it ships. Pictures came fourth, and only need to reach the pane you’re looking at.

The test those weights called for timed each core reading 8 MB of text with twenty panes open. wezterm-term took 472 ms and fell to third. libghostty-vt was fastest at 59 ms, rio-vt next at 82, and on the weights rio-vt led, 0.76 to 0.72. Counting rows kept caught a trap first: libghostty-vt’s history setting says lines and counts bytes, so its first run held 489 rows to everyone else’s 10,040 and looked lighter than it was.

Story tells it as a hiring panel writing its scorecard. Technical has the weights, the twenty-pane numbers and how each score was made.

Portfolio

Story

The scorecard before the interviews

By the end of the first ranking, Terminal Delight had four measured candidates for its emulator core, the library that turns a program’s output into the grid a terminal draws, and a scorecard someone else had written. The agent assembling the research had weighted eight things by its own best guess, from picture support and fit with Terminal Delight’s code to the size of the rewrite and how many people maintain each core, and wezterm-term, WezTerm’s core, came out three hundredths ahead of rio-vt, the core inside the Rio terminal. My reaction was mostly vibes. Ghostty is the candidate everyone has heard of, and I felt “the popularity pull for sure!”, while wezterm-term and rio-vt were dark horses. And what I wanted most was a core that fits Terminal Delight’s purpose and philosophy, which no column measured.

Vibes aren’t a scorecard, and a hiring panel that has already met the candidates writes a different scorecard from one that hasn’t, which is why careful panels write theirs before the interviews. So I answered four either-or questions in my own words, and the answers went into a file that was committed before any new measurement existed. I had already seen the first ranking, and the file says so. Speed and memory won outright: “100% speed and memory”. Being Rust end to end, which Terminal Delight had always been, mostly fell away as a requirement if the alternative would perform. An agent being able to work on the core fluently came next, because I will never read it myself. A published package, used as it ships, beat a bigger team of maintainers. Open source stopped being a weight and became a gate. And pictures, asked whether they must survive, came back “ATTENTIONAL! not persistent”: a picture is there while you look at its pane and gone when you switch tabs.

That last answer took the weight off the test the first ranking had been waiting on, whether a picture survives the snapshot a window receives from Terminal Delight’s session host when it attaches. A window already runs its own copy of the core over the live stream, so a picture drawn while you watch reaches it. The snapshot matters when you come back later, and by then the picture is meant to be gone.

Then the interviews. The top line of the scorecard had never been tested at the size Terminal Delight runs, so each candidate ran twenty panes, each given a picture and 10,000 lines of history, and was timed reading 8 MB of ordinary text, three rounds apiece. libghostty-vt, Ghostty’s core, was fastest at 59 milliseconds. rio-vt took 82, alacritty’s core, the one Terminal Delight was using, 140, and wezterm-term 472. Holding its history, a rio-vt pane used 11.0 MB, a libghostty-vt pane 11.6, an alacritty pane 28.5 and a wezterm-term pane 5.9.

The first round gave libghostty-vt a different memory figure, and it was wrong. Each harness also reported how many rows of history it was holding, and libghostty-vt was holding 489 where every other core held 10,040. Its history setting is documented as a number of lines and counts bytes, so asking for 10,000 had bought it a twentieth of the history. On memory it looked like the lightest candidate in the room because it was carrying the least. A sweep found the byte budget that holds 10,164 rows, the nearest it gets to 10,040, and its rounds ran again at that.

On the sealed scorecard wezterm-term fell from first to third at 0.60, pulled down by that 472 and by never having been published as a package. rio-vt led at 0.76, and libghostty-vt followed at 0.72. The second line of the scorecard, whether an agent can work on the core fluently, carried a quarter of the weight and had no measurement yet. It was left out of the sums, which is different from scoring it zero, and it was heavy enough to swap the top two either way.

I’d love to work with you. See the portfolio, or get in touch.

Portfolio

Technical

Weights first, then twenty panes

The first ranking weighted eight dimensions by the assembling agent’s first guess. This part replaces that guess with weights taken from my own answers, fixed before the measurements they would judge, and then runs the measurement they put first: speed and memory at the pane count Terminal Delight is built for.

The weights

Four either-or questions went to chat, and the answers were committed verbatim with the agent’s translation into numbers, before the performance runs produced anything. The file notes that I had already seen the first ranking, so the weights are sealed against the new measurements and not against it.1

DimensionWeightFrom
Speed and memory5“100% speed and memory”
An agent can work on it fluently4“I will never read the core”
Published, used unpatched3“Published, unpatched”, chosen over more maintainers
Pictures2“It MIGHT be better”
Maintainers1lost to published and unpatched
Other picture protocols0.5“handling more isn’t necessarily better”
Build toolchain0.25“Rust e2e falls away almost entirely”
Pictures that persist0“ATTENTIONAL! not persistent”
Open sourcea gate“OPEN SOURCE IS KEY”; kitty’s GPL-3.0 core is out

A weight of zero on persistence retired the host-to-window test the first ranking ended on. A window attached to Terminal Delight’s session host runs its own copy of the core over the live byte stream, so a picture drawn while it watches reaches that copy. Only the snapshot a window replays on attaching would lose it, and an attentional picture is not meant to outlive the moment.

Twenty panes

Each harness gained a --perf mode: twenty terminals, each fed a deterministic 8 MB text stream and one picture, holding about 10,000 lines of history, then five speed runs; three rounds per core, each in its own process. Medians:2

Core8 MB of textThroughputPer pane, history fullRows keptProcess peak
libghostty-vt 0.2.159 ms135 MB/s11.6 MB10,164245 MB
rio-vt 0.5.2882 ms97 MB/s11.0 MB10,040233 MB
alacritty_terminal 0.26140 ms57 MB/s28.5 MB10,040583 MB
wezterm-term b09b56c472 ms17 MB/s5.9 MB10,040130 MB

The rows-kept column exists because of the first round. libghostty-vt was configured with max_scrollback 10,000, which its Rust docs and C header describe as lines, and it held 489 rows where the other three held 10,040; the setting is a byte budget. Scored on that round it would have taken the memory column for holding a twentieth of the history. A sweep found that 11,000,000 bytes holds 10,164 rows, the page step nearest 10,040, and its three rounds were re-run there.23

Scores

Speed and memory score as half each, each as a ratio to the best core on that measure. Published and unpatched scores 1 for a crate used as-is (alacritty_terminal, rio-vt), 0.75 for libghostty-vt, whose crate clones Ghostty’s source at build time and needs Zig, and 0.25 for wezterm-term, which has never been published and would need a patch for placeholder pictures. Pictures are Kitty features implemented, of 14. Agent fluency has no measurement yet and is left out of both the numerator and the denominator.4

CoreSealed weightsWith the earlier fit, rewrite and API weights added back
rio-vt0.760.70
libghostty-vt0.720.66
wezterm-term0.600.57
alacritty_terminal, Terminal Delight reading pictures itself0.460.51

Agent fluency, weight 4 of 15.75, is large enough to reorder the top two in either direction, which is why the next step measured it.

What would falsify this

Three things. The numbers are the assembling agent’s translation of four answers typed in chat, including the equal split between speed and memory; I can correct any of it, and a different reading that moves the top two would mean the ranking came from the translation. The weights were sealed against the new measurements and not against the first ranking, which I had seen. And the twenty-pane runs used a synthetic text stream in harnesses outside Terminal Delight; if agent programs redrawing full screens load a core in a way plain text doesn’t, the speed column is measuring the wrong traffic.

I’d love to work with you. See the portfolio, or get in touch.

Portfolio

Sources

  1. The weights, with my answers verbatim — Committed at 08:55 on 2026-09-25, before the performance runs; the translation into numbers is marked as the assembling agent’s reading, open to correction.
  2. The twenty-pane runs — Three rounds per core in separate processes; summary.json holds the medians, every round’s timing and memory, and rows kept. libghostty-vt 0.2.1 against Ghostty a887df42 with Zig 0.15.2.
  3. The scrollback sweep — Byte budgets tried against rows held, to find the budget nearest 10,040 rows.
  4. The rank under the sealed weights — Scores per dimension and both totals in vibes/rank-2026-09-25.json.