# Cursor Position (CUP)

> Move the cursor to a given line and column.

- **Sequence:** `CSI Pl ; Pc H`
- **Defaults:** Pl = 1, Pc = 1
- **ECMA-48:** [§8.3.21 CUP – Cursor Position, p. 36](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n49/mode/1up)
- **DEC STD 070:** [§5.4.4 Cursor Position, p. 5-49](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n303/mode/1up)
- **VT510:** [CUP—Cursor Position](https://vt100.net/docs/vt510-rm/CUP.html)

Move the cursor to line `Pl`, column `Pc`, both counting from 1. Either can
be left out, and so can both: `CSI H` is the top-left corner. A `0` is
taken as `1`.

A position past the edge of the screen is clamped to it, so `CSI 999 ; 999 H`
is a common way of reaching the bottom-right corner without knowing the size
of the screen.

With origin mode (`CSI ? 6 h`, DECOM) on, the position counts from the top
and left margins instead of the screen's corner, and is clamped to the
margins rather than to the screen.

Moving the cursor cancels any pending wrap, as DEC STD 070 asks
([§D.6.1, p. D-13](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n1199/mode/1up)) and xterm's
[`CursorSet`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/cursor.c#L68-L93) does. `CSI Pl ; Pc f` (HVP) does the
same thing as CUP.

## Validation

### CUP-1: To a position

Input, one step per line:

```text
\e[2;3H
X
```

Expected screen:

```text
|_____|
|__X__|
|_____|
```

### CUP-2: Defaults

Input, one step per line:

```text
\e[3;3H
\e[H      # both left out
A
\e[2H     # column left out
B
\e[;4H    # line left out
C
```

Expected screen:

```text
|A__C_|
|B____|
|_____|
```

### CUP-3: Clamped to the screen

Input, one step per line:

```text
\e[999;999H
X
```

Expected screen:

```text
|_____|
|_____|
|____X|
cursor 3,5
pending-wrap yes
```

### CUP-4: With origin mode

Input, one step per line:

```text
\e[2;3r   # region is lines 2 and 3
\e[?6h    # origin mode
\e[1;1H   # the top of the region
A
\e[9;1H   # clamped to the bottom of the region
B
```

Expected screen:

```text
|_____|
|A____|
|B____|
|_____|
```

---

This is the Markdown version of <https://control-codes.page/csi/cup/>. On that page every validation case runs live in libghostty-vt, the terminal emulation core of Ghostty, compiled to WebAssembly.

The validation cases are written in the notation described in <https://control-codes.page/notation/index.html.md>.
