Quickshell draws the terminal grid on the GPU: one DrawInstanced of twenty-byte cells per frame, and no draw call at all on a frame where nothing changed. Sessions, keys, SFTP and port forwards are in the window. Nothing else is, and the list of what will never be added is published.
Trying 10.42.7.19:22 … prod-eu-1 host key known ed25519 SHA256:9cE2r+wQ…kQ4 aes256-gcm@openssh.com Last login: Thu Aug 27 09:14:02 2026 from 10.4.2.19 alex@prod-eu-1:~$ printf '%s\n' 'ascii │ 日本語 │ café │ 🚀 done' ascii │ 日本語 │ café │ 🚀 done alex@prod-eu-1:~$ systemctl is-active nginx postgresql active active alex@prod-eu-1:~$ tail -f /var/log/nginx/access.log 10.4.2.19 - - [27/Aug/2026:09:14:38] "GET /health" 200 2 10.4.2.19 - - [27/Aug/2026:09:14:41] "POST /orders" 201 511 10.4.2.19 - - [27/Aug/2026:09:14:43] "GET /orders/8812" 502 166
The clients this replaces grew an X server, a POSIX userland, a macro recorder and a plugin host around a terminal that still redraws the whole screen to move a cursor. Quickshell is the other trade: a small surface, drawn properly, with the cost of every part written down before it was built.
DirectWrite rasterises each glyph once into an atlas keyed on its subpixel offset, so a character keeps its weight in every column. The whole visible grid is then one DrawInstanced of twenty-byte cells, blended in linear light so text weighs the same on either background.
Every mutation moves a generation the renderer compares against the one it last drew, and a scroll dirties one row rather than the screen. When the host stops writing, the window authorises no further frame: an idle Quickshell submits zero draw calls and holds no raised timer resolution.
Output volume is the host's choice and echo latency is what you feel, so the two never share a queue. Under a hundred-megabyte cat the delay from key to glyph is the same as it is at rest, because frames are dropped under load and bytes never are.
Every connection is checked against known_hosts, written in the format OpenSSH reads back unchanged. A key that has changed raises a dialog with no default accept button: the old entry has to be removed deliberately, because a client that defaults to accept is a client whose encryption is decoration.
Patterns, Include and ProxyJump chains are read as written, so a host you already defined for OpenSSH opens here without being defined a second time. MobaXterm and PuTTY sessions import, and every setting this client will not honour is named per session rather than dropped.
Six figures, the machine they are measured on and the method that settles each one live in docs/PERFORMANCE.md, and a regression past any of them fails a build rather than reaching a release. A number without a machine is a mood.
A link that drops for ten seconds is ordinary on mobile and on a VPN, so it costs a reconnect and not the session. What cannot be recovered is said in a sentence naming the hop, the method and the remedy.
link lost prod-eu-1 no data for 4.0 s reconnecting … attempt 1 refused (network unreachable) reconnecting … attempt 2 refused (network unreachable) restored prod-eu-1 on attempt 3, after 11.4 s scrollback kept, 18 240 rows · tab kept · 3 forwards restored forward -L 5432 → db-1:5432 up · -R 9000 up · SOCKS 1080 up REFUSED build-runner-4 the host key does not match the one on record stored ed25519 SHA256:UkP0m1s+7Jd…Ax8 first seen 2026-03-04 offered ed25519 SHA256:t7Qa9Rr2Zz…bN1 not accepted This is what a machine in the middle looks like. It is also what a rebuilt host looks like. Remove the stored entry deliberately to tell them apart.
A terminal is judged by the programs that already exist, so this one is measured against them rather than against tests its own author wrote.
quickshell · protocol trace · session prod-eu-1 · secrets redacted → host CSI c "what are you" ← us ESC [ ? 65 ; 1 ; 9 ; 15 ; 22 c a VT500-series terminal, and here is what it has → host OSC 52 ; c ; ? BEL "read me the clipboard" ← us (nothing) refused: write-only when on, off by default → host OSC 0 ; deploy: staging BEL set the window title ← us (nothing) title set, never reported back → you click at row 12, column 240 ← us X10 encoding cannot name column 240; asked the host for SGR (1006) the alternative is naming a different cell and calling it a click
OSC 52 cannot read your clipboard, the title is set and never reported back, and a paste is bracketed so the host cannot run it as though you had typed it.A transfer and a forward are channels on a connection that exists. Opening a second one would cost you a second password, a second second-factor and a second entry in someone's audit log, for no gain.
127.0.0.1 without an explicit choice, on a machine with any number of interfaces.netstat to understand it.A first run on a clean profile shows a title bar and a terminal. Everything else is reachable and nothing else is resident on the screen, which is a decision the defaults make on your behalf and the settings let you undo.
These were written before the code they bind, and each is changed only by a commit that argues for the change. A regression past any of them fails a build.
A keystroke echoed by a local shell, from the key going down to the glyph being on the glass. Settled by a high-speed capture of key and screen in one frame, or an instrumented path that timestamps the input event and the present. Never by feel.
Mixed text and escape sequences, end to end, on a headless harness with no renderer attached. Parsing must never be the reason output is slow, so it is measured where nothing else can be blamed for it.
One filled grid redrawn continuously, GPU and CPU time, in a steady state rather than on the first frame. Leaving the frame budget almost entirely unspent for one pane is what keeps several panes affordable.
A window nobody is typing into: zero draw calls submitted over an idle interval, no measurable occupancy on any core, and no raised system timer resolution held by the process. This is the figure a laptop user feels as battery life, so small is not a pass here.
Process creation to an interactive local shell, which means a prompt that accepts a keystroke and not a window that has appeared. Reported for a cold file cache, with the warm figure beside it where a cold one cannot be arranged.
The private working set after the session has settled. It is also held flat across a seventy-two-hour soak, because a number that passes on minute one and drifts is a leak that passed.
The reference machine is named in docs/PERFORMANCE.md: an i7-14700, an RTX 4060, a 3840 × 2160 display at 60 Hz, on Windows 11 Pro. A second machine may be measured, and then the machine is named beside the number, because two machines quoted as one is how a regression becomes a rounding difference. A figure quoted without the run that produced it is not a measurement.
The session tree is the artefact you built over years, and recreating it by hand is the real cost of changing client. It is also the reason most people never get past the first evening with a new one.
An OpenSSH config, a MobaXterm session file or a PuTTY registry export. Patterns, includes and jump chains are read as written rather than flattened into a list.
Every setting this client will not honour is reported per session, by name. An X11 setting or a macro is refused out loud, because a silent drop is a defect report three weeks later.
Nothing is rewritten in place: the files the incumbent reads are left as they are, and the known_hosts this client writes is one OpenSSH reads back unchanged.
The full list is in the roadmap and it is not a wish list of things not yet reached. A client is lean because of what it refuses, and refusing it in writing is what makes the refusal hold.
The single largest thing the incumbent carries, and the reason its install is measured in gigabytes.
No Cygwin, no BusyBox. Windows has a package manager and a WSL, and neither of them is this client's job.
One protocol, done properly. A second protocol is a second product wearing the same window.
No Electron, no WebView2, no JavaScript terminal. The frame budget on this page is the whole argument.
D3D11 and nothing beside it. WARP covers the machine with no usable GPU, and a CPU-rasterised grid is refused outright.
Parity is not the goal, and a macro recorder, a scripting engine and a plugin host are all refused in the MVP.
Windows 10 or 11, x64. It installs under %LOCALAPPDATA% and asks for nothing else, which is what reaches a managed laptop with SmartScreen on.
The asset carries its version in its name and SHA256SUMS.txt beside it is what a download is checked against. Building from source needs the .NET 10 SDK and Windows, and it is how a contributor works on this rather than how anybody has to run it.