Kitty Graphics Protocol (APC G)

Display inline images in the terminal using the Kitty graphics protocol.

The Kitty graphics protocol allows programs to transmit and display inline images in the terminal. It is the most capable of the modern image protocols, supporting pixel-perfect placement, multiple simultaneous images, z-ordering, and incremental updates. Wintty implements the protocol against the upstream Kitty specification.

Unlike OSC sequences, the Kitty graphics protocol uses the Application Program Command (APC) envelope so that large binary payloads (e.g. PNG images encoded as base64) can be transmitted without interfering with other terminal output:

  1. 0x1B
    ESC
  2. 0x5F
    _
  3. 0x47
    G
  4. ____
    k
  5. 0x3D
    =
  6. ____
    v
  7. 0x2C
    ,
  8. ____
    ...
  9. 0x3B
    ;
  10. ____
    d
  11. 0x1B
    ESC
  12. 0x5C
    \

Each command is a comma-separated list of key=value control pairs followed by an optional ; and a base64-encoded payload. Keys are always single characters; values are either single ASCII characters or 32-bit unsigned integers. Wintty's parser caps each APC payload at 65 MiB to bound memory use during transmission. Decoded image storage is capped by the image-storage-limit config option (default 320 MB for the desktop binary), but that cap is applied per screen, not across the terminal: the primary and alternate screens each own a separate store carrying its own budget, so the real ceiling is a multiple of the configured value.

Actions

The a key selects the high-level action. All other keys are interpreted relative to that action:

aActionDescription
tTransmitUpload an image into terminal-side storage without displaying it.
TTransmit and displayUpload an image and place it on the screen in one round-trip.
pPlace (display)Create a new placement of an already-stored image at the current cursor.
dDeleteDelete images and/or placements from storage.
qQueryAttempt a transmission but do not persist anything. Used for feature detection.
fTransmit animation frameAppend a frame to an animated image.
aControl animationStart, stop, or reset an animation.
cCompose animationCompose frames of an animation.

Note

The animation actions (f, a, c) are parsed and accepted by Wintty's command parser, but the executor currently responds with ERROR: unimplemented action. Animation is on the roadmap but does not ship today. Shared-memory transmission (t=s) is parsed but then rejected outright on Windows: the image loader fails every t=s command with EINVAL: unsupported medium. Windows programs must transmit with t=d, t=f, or t=t.

If a is omitted, it defaults to t (transmit).

Transmission keys

When transmitting an image (a=t, a=T, or a=q), the following keys describe the payload:

KeyTypeMeaning
fintPixel format: 24 (RGB), 32 (RGBA, default), or 100 (PNG).
tcharMedium: d (direct, default), f (file), t (temp file), s (shared memory).
sintImage width in pixels.
vintImage height in pixels.
SintTotal size in bytes (for file/temp/shared transports).
OintOffset within the file (for file/temp transports).
iintClient-chosen image ID.
IintClient-chosen image number (alternative to i).
pintPlacement ID, for distinguishing multiple placements of one image.
ocharCompression: z for zlib deflate. Omitted means uncompressed.
mintSet to 1 to indicate more chunks will follow for this image.
NintUsage hint bitfield. Bit 0 marks the image transient, which moves it to the front of the eviction order.

For the direct medium, payloads are base64-encoded and may be split across multiple commands by setting m=1 on every command except the last. For file, temp, and shared_memory mediums, the payload is the path or shared memory name (also base64-encoded).

Display (placement) keys

When displaying (a=T, a=p), the keys below position the image. A placement is a single on-screen instance of a stored image. One stored image may have many placements at different positions.

KeyTypeMeaning
iintImage ID to place. Required unless I is used.
IintImage number to place. Alternative to i.
pintPlacement ID. Allows multiple placements of the same image.
xintSource x offset within the image (pixels).
yintSource y offset within the image (pixels).
wintSource width to crop from the image (pixels).
hintSource height to crop from the image (pixels).
XintDestination x offset within the starting cell (pixels).
YintDestination y offset within the starting cell (pixels).
cintNumber of columns the placement should occupy.
rintNumber of rows the placement should occupy.
CintCursor movement after placing: 0 cursor moves past image, 1 cursor unchanged.
Uint1 for a virtual placement (referenced via Unicode placeholders).
zintZ-index. Negative values render behind text.
PintParent image ID (for relative placement). Parsed, then dropped.
QintParent placement ID. Parsed, then dropped.
HintHorizontal offset relative to parent (cells, signed). Parsed, then dropped.
VintVertical offset relative to parent (cells, signed). Parsed, then dropped.

Note

Relative and parent placement are not implemented. P, Q, H, and V are parsed and range-checked, but they never reach the stored placement, which carries only the source rectangle, the X/Y cell offsets, c, r, and z. A placement therefore has no parent to be positioned against, and the offsets are silently discarded. The one place P changes behavior is a rejection: pairing a parent (P greater than zero) with a virtual placement (U=1) fails with EINVAL: virtual placement cannot refer to a parent.

Storage lifecycle

Images and placements have distinct lifecycles:

  • Images live in terminal-side storage once transmitted. They can be reused by many placements. Total image bytes are bounded by image-storage-limit. When the limit is exceeded, images are evicted by a four-level priority: transient and unplaced first, then unplaced, then transient but placed, then placed. Ties are broken by the oldest generation and then the lowest image ID. Eviction is not limited to unreferenced images: if reclaiming enough bytes requires it, a referenced image is evicted and every placement of it is dropped along with it.
  • Placements are screen positions where an image is drawn. Deleting a placement leaves the underlying image intact for future placements. Deleting an image with active placements also removes those placements.

The a=d action takes a d key whose value is a single character indicating what to delete (e.g. all visible images, images by ID, images intersecting the cursor) and optionally whether the underlying image bytes are also freed (lowercase keeps the image in storage, uppercase frees it).

Quiet mode

The q key controls response chattiness:

qMeaning
0Default. Reply with success or error.
1Suppress success responses; still reply on error.
2Suppress all responses, including errors.

Responses are themselves APC sequences of the form ESC _ G i=<id>;<message> ESC \.

Detecting support

A program can detect whether the terminal speaks the Kitty graphics protocol by sending a query that should always succeed:

printf '\x1b_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\'

A conforming terminal replies with OK. A terminal that does not understand the protocol either replies with an error or stays silent.

Note

The in-box Windows console host drops DCS and APC sequences it does not recognize, which is exactly what would break this protocol over ConPTY. Wintty bundles its own conpty.dll to fix that: the bundled host forwards ESC _ ... ESC \ envelopes through intact, so Kitty graphics reaches the terminal unmangled with no special launch environment and no bypass. Bundled ConPTY is Wintty's only transport; the older raw-pipe bypass has been removed, so there is nothing to opt into. Other Windows terminals still running on the in-box host may strip these sequences, so detecting support with the query above before transmitting large payloads is still worthwhile for portable programs.

See also