Terminal client
August 26, 2026 ยท View on GitHub
The terminal client is a backend of the native Xpra client that draws forwarded windows inside a terminal emulator instead of on a desktop. Window contents are sent to the terminal as images using the kitty graphics protocol, keyboard input is read with the kitty keyboard protocol, and the pointer is read from SGR pixel mouse reports.
It needs no display server, no GTK and no OpenGL on the client side, so it works over a plain
ssh login as long as the terminal emulator at the other end of that login speaks the graphics
protocol.
- a terminal emulator implementing the kitty graphics protocol: kitty, Ghostty, WezTerm or Konsole
- a terminal reporting its size in pixels (
TIOCGWINSZ), which all of the above do - the client built with
--with-terminal_client(the default, the rpm and debian packages ship it)
At startup the client asks the terminal whether it understands the graphics protocol. If no answer arrives, the session is aborted with an error rather than filling the terminal with escape sequences.
xpra attach ssh://host/100 --backend=terminal
xpra attach --backend=help lists every client backend available on the system.
With the default --backend=auto, this backend is also picked automatically: if there is no
$DISPLAY or $WAYLAND_DISPLAY (and the client isn't running on MS Windows or macOS, which
always have a display), standard input and output are a terminal, and that terminal identifies
itself as one of the emulators listed above. This is only a best-effort guess from environment
variables (KITTY_WINDOW_ID, TERM, KONSOLE_VERSION, TERM_PROGRAM) made before connecting -
actual protocol support is always confirmed with the startup probe described below.
The terminal is left alone until the connection handshake completes, so password prompts still work normally. After that the client switches to the alternate screen, hides the cursor and puts the terminal in raw mode; all of this is undone when the session ends.
Because the terminal is used for pixels, log output is written elsewhere: to standard error when
that is not the terminal, otherwise to xpra-terminal-<pid>.log in the first writable directory
listed by XPRA_LOG_DIRS - by default the xpra runtime directory (/run/user/$UID/xpra), then
the system temporary directory. The path is printed before the terminal switches to the alternate
screen, and if no directory can be written to, the client's own log output is discarded rather
than drawn over the session. Use -d terminal to trace the tty setup, graphics and input parsing.
Keyboard - the kitty keyboard protocol is enabled for the duration of the session. It reports key presses, repeats and releases, the modifiers held, and the text a key produces. Terminals that ignore it fall back to legacy escape sequences, which cannot report key releases, so the client synthesises one for every press.
Pointer - SGR pixel mouse reporting (modes 1002, 1003, 1006 and 1016) gives motion,
buttons and wheel events in pixels rather than character cells, which is what window hit
testing needs.
Clipboard - receive only, using OSC 52: what is copied in the remote session is offered
to the terminal's clipboard, and the client never claims the selection itself. Whether the
terminal accepts it is the terminal's decision - kitty, for instance, requires
clipboard_control to list write-clipboard. Pasting into the remote session is not
supported, because reading the clipboard back over OSC 52 is disabled or gated behind a
user prompt by default in every terminal that implements it.
- the terminal must support the kitty graphics protocol - there is no fallback renderer
- no system tray and no notifications
- no client OpenGL acceleration; windows are painted as images
- no window decorations, no menus and no session info dialogs
- the mouse cursor is painted by the client as one more image on top of the windows
- keyboard layout handling is minimal: the terminal reports characters, not keycodes, so server side keymaps are not synchronised
- damaged windows are re-sent whole by default, or patched through shared memory
when the terminal runs on the same machine and answers the startup probe;
XPRA_TERMINAL_FRAME_EDITS=-1probes for direct frame edits instead,1forces them - the pixel coordinate base of SGR mouse reports varies between terminals:
the client assumes
0under kitty and1everywhere else,XPRA_TERMINAL_MOUSE_COORDINATE_BASE=0|1overrides it
- Client - the native client and its options
- Client implementations - the other clients that speak the xpra protocol
- Keyboard and Clipboard