Something went wrong. Try again.
A reference for terminal control sequences whose examples run live in libghostty-vt compiled to WebAssembly.
Something went wrong. Try again.
4.6 kB · 135 lines
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136---.title = "Pointer Shape (OSC 22)",.description = "Change the shape of the mouse pointer while it is over the terminal.",.date = .date("2026-10-02T00:00:00"),.layout = "sequence.shtml",.custom = { "mnemonic": "OSC 22", "name": "Change Pointer Shape", "sequence": "OSC 22 ; Pt ST", "ecma48": "8.3.89", "ecma48_name": "OSC – Operating System Command", "ecma48_page": 51, "xterm": "Operating System Commands", "spec": "https://sw.kovidgoyal.net/kitty/pointer-shapes/", "spec_name": "Mouse pointer shapes, kitty documentation",},---`OSC 22 ; Pt ST` sets the shape of the mouse pointer over the terminal to`Pt`, so that a program can show a hand over a link or a watch while it isbusy. It is xterm's, and xterm takes `Pt` as a name from the X cursor font:`left_ptr` for an arrow, `hand2`, `watch`, `xterm` for the I-beam, and so on.A name it does not know, or none at all, gives the I-beam, its default([`xtermSetupPointer`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L991-L1029),[`LookupCursorShape`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L891-L988)).
kitty extended it in its[Mouse pointer shapes](https://sw.kovidgoyal.net/kitty/pointer-shapes/)document, which uses the CSS cursor names (`default`, `pointer`, `wait`,`text`, …) rather than X's, adds a stack, `OSC 22 ; > name ST` to push and`OSC 22 ; < ST` to pop, and lets a program ask, with `OSC 22 ; ? names ST`,which shapes the terminal has and which is current.
libghostty-vt keeps a shape its host can read and draw. It accepts the CSSnames, and the X names that have a CSS equivalent: `watch` is `wait`,`left_ptr` is `default`, `xterm` is `text`. An empty `Pt` puts back `text`.It ignores a name it does not know, rather than falling back as xterm does,and it does not have kitty's stack or queries. The cases follow a defaultxterm, and give each shape by its CSS name, which is what a case's`pointer` line checks; the X cursors xterm sets are given by their CSSequivalents. Those where a name is one only libghostty-vt knows, or neitherdoes, are known differences.
# Support
| Terminal | Version | Support | Notes || --- | --- | --- | --- || VT220 | [manual](https://vt100.net/docs/vt220-rm/), 2nd ed., 1984 | No | OSC is not among the controls it recognizes ([§4.2](https://vt100.net/docs/vt220-rm/chapter4.html#S4.2)) || VT510 | [manual](https://vt100.net/docs/vt510-rm/), 1st ed., 1993 | No | ignores an OSC string ([chapter 4](https://vt100.net/docs/vt510-rm/chapter4.html)) || xterm | patch 412, [xterm-411a](https://github.com/ThomasDickey/xterm-snapshots/tree/xterm-411a) | Yes | X cursor font names; an unknown name gives the I-beam || libghostty-vt | [919dca5](https://github.com/ghostty-org/ghostty/tree/919dca5c848d43a489a4cb2e1feade016f0fa2db) | Partly | CSS names and X names with a CSS equivalent; ignores unknown names; no stack or queries (OSC22-5, OSC22-6) || Konsole | 26.11.70, [a24c3d71](https://invent.kde.org/utilities/konsole/-/tree/a24c3d71be3684f24d030aa2dbe9bd723d985233) | Partly | CSS names and Qt's, not X's `hand2` or `watch`; an unknown name resets it; no stack or queries || kitty | 0.49.2, its documentation | Yes | CSS names, a stack and queries: [Mouse pointer shapes](https://sw.kovidgoyal.net/kitty/pointer-shapes/) || ConEmu | build 230724, its [documentation](https://conemu.github.io/en/AnsiEscapeCodes.html) | No | not in its [ANSI escape codes](https://conemu.github.io/en/AnsiEscapeCodes.html) |
# Validation
## OSC22-1: The I-beam to begin with
>[]($block.attrs("vt-case"))> ```> A> ```> ```> |A_____|> pointer text> ```
## OSC22-2: An X cursor name
>[]($block.attrs("vt-case"))> ```> \e]22;watch\e\\> ```> ```> |______|> pointer wait> ```
## OSC22-3: Another
>[]($block.attrs("vt-case"))> ```> \e]22;left_ptr\e\\> ```> ```> |______|> pointer default> ```
## OSC22-4: Empty puts back the I-beam
>[]($block.attrs("vt-case"))> ```> \e]22;watch\e\\> \e]22;\e\\> ```> ```> |______|> pointer text> ```
## OSC22-5: A CSS name, which xterm does not know
>[]($block.attrs("vt-case","known-difference"))> ```> \e]22;watch\e\\> \e]22;pointer\e\\ # not an X cursor: the I-beam> ```> ```> |______|> pointer text> ```
## OSC22-6: A name neither knows
>[]($block.attrs("vt-case","known-difference"))> ```> \e]22;watch\e\\> \e]22;nosuch\e\\> ```> ```> |______|> pointer text> ```
## OSC22-7: kitty's query is not answered
>[]($block.attrs("vt-case"))> ```> \e]22;?__current__\e\\> ```> ```> |______|> reply none> ```