Releases: directvt/vtm
Releases · directvt/vtm
v2026.04.28
v2026.04.27
v2026.04.26
v2026.04.25
v2026.04.24
Changes
- Revise grapheme cluster parsing.
- Terminal:
- Implement XTGETTCAP.
- Implement DECRQM.
- Fix color text copy (regression).
- Don't repeat arrow keys on mouse wheel in alternate scroll mode (one mouse event - one key press).
- Fix android builds (std::execution).
- Add option to print available fonts
vtm --fonts [v[erbose]].
v2026.04.19
Changes
- Implement DSR and DECRQSS 'm'+'r'. #909
- AnyPlex: Re-rasterize (resize) layers on cell size change.
v2026.04.18
Changes
- This release is not compatible with previous releases.
- AnyPlex Protocol, (tracked in #902):
- Implement image layering (recursive rendering is not implemented yet).
- Fix deletion of image references in the terminal scrollback.
An example of a three-layer composition using two images (tiger.svg and grade.svg as a stretched background):

Attribute Scoping
Attributes are divided into Shared (object-wide), Layer (layer specific) and Unique (per-instance/cell).
- Shared Attributes:
l,u,v,uw,vh,x,y,w,h,fit,rt,a,f,o. Global to all instances of theid. - Layer Attributes: All Shared attributes can be overridden per layer inside
l=id(key=val). - Unique Attributes:
W,H,r,c,gc. Specific to the instance and the grid slice.
Attributes
| Attribute | Scope | Value/Range | Default | Description |
|---|---|---|---|---|
| l | Shared | <id>[/sub-id][(<layer attrs>)] |
empty string ("") |
Adds a layer. Can be specified multiple times. |
v2026.04.16
Known Issues
- References to deleted images from the scrollback are not removed. (fixed in cb895a7)
- There is no way to do image inheritance and composition.
Changes
- This release is not compatible with previous releases.
- AnyPlex Protocol, (tracked in #902):
- Change the way images are displayed. See the updated specification.
Attributes
| Attribute | Scope | Value/Range | Default | Description |
|---|---|---|---|---|
| id | - | <id>[/sub-id] |
empty string ("") |
Object reference ID. |
| u, v | Shared | float |
0.0 |
Top-left of the source crop (0.0-1.0). |
| uw, vh | Shared | float |
1.0 |
Size of the source crop (0.0-1.0). Negative flips. |
| x, y | Shared | float |
0.0 |
Offset of the Clipping Box inside the W x H area (cells). |
| w, h | Shared | float (0.0-65535.0] |
W, H |
Dimensions of the Clipping Box inside the W x H area (cells). |
| fit | Shared | inside|outside|stretch|none |
inside |
Fit logic: How the crop fits into the w x h Clipping Box. (none = exact pixels). |
| tr | Shared | 0..7 |
0 |
Transform: Decimal value of the 3-bit state [FlipY][FlipX][SwapXY]. |
| rt | Shared | 0|90|180|270 |
0 |
Rotate: CCW rotation of the source (degrees). |
| f | Shared | n|v|h|vh|hv |
n |
Flip: n = none, v = vertical, h = horizontal. |
| a | Shared | [l|c|r][t|m|b] |
cm |
Align: 2D alignment within the Clipping Box and the W x H area. (l = left, c = center, r = right, t = top, m = middle, b = bottom). |
| o | Shared | 0|1 |
0 |
Ontop: 0 = under text, 1 = over text. |
| gc | Unique | string |
ASCII Space (0x20) " " |
Grapheme cluster to write to cells (will be scaled to a 1x1 cell size). |
| W, H | Unique | 0..65535 |
0 |
Grid Container: Physical footprint in cells. If 0, nothing is rendered (registration only). |
| r, c | Unique | 0..65535 |
0 |
Row, column 1-based slicing index for target cell slice. (0 = full height/width, 1..n = specific cell/slice). |
Rendering & Interaction
- Normalized Source Viewport: The source document is first projected onto a virtual canvas of size
1.0by1.0. A rectangular fragment (crop) is then extracted from this canvas using normalized coordinatesu,v(top-left) anduw,vh(size), where1.0equals the full canvas dimension. Negative values foruworvhcause the extracted fragment to be flipped along the respective axis. - Target Rectangular Area: The grid footprint is explicitly defined by the unique attributes W and H. The range of affected cell indices starts at the current cursor position and spans
[0 .. W-1]horizontally and[0 .. H-1]vertically. IfWorHis0, no cells are modified, and the object is only registered in the cache. - Pixel-wise Precision:
- Content Positioning: The image fragment is scaled according to
fitand aligned within the Clipping Box (w x h) using theaattribute. - Box Positioning: This Clipping Box is then aligned within the Grid Container (
W x H) using the sameaattribute. - Offsets: Shared
xandyvalues are applied as final pixel offsets from the resulting position. - Final Cut: The Grid Container acts as a strict physical mask; any pixels falling outside the
W x Hcell area are not rendered.
- Content Positioning: The image fragment is scaled according to
- Persistence: Metadata (Object Reference + Unique attributes) is stored per-cell to survive scrollback and ensure logical linking for rectangular reflow, using only an implementation-defined minimum of data to minimize memory overhead.
- Cursor Position: Anchored at the top-left; moves to the cell immediately following the bottom-right corner of the Grid Container (
W x H) after output. - Destructivity:
- If the
gcattribute is not empty, the provided grapheme cluster is written to every cell in the target area, replacing existing text and SGR attributes. - If
gcis empty, the output is non-destructive; existing text and SGR attributes remain visually intact. - Subsequent text written over the area does not destroy the underlying object. Metadata remains in the cell until explicitly replaced.
- If the
- Selection & Highlighting: When a cell is selected (e.g., mouse selection or SGR 7), the frontend applies a 0.5 opacity mask to the object's pixels within that specific cell to ensure the selection remains visible.
- Searchability: Any text contained within the document (e.g.,
<text>in SVG) is rendered as part of the graphic and is not indexed for terminal text search. - Layering & Transparency: Supports per-pixel alpha. The
o(ontop) attribute determines Z-order:0:[Cell BG] -> [Object] -> [Text]1:[Cell BG] -> [Text] -> [Object]- The cell's background color always remains at the bottom. The terminal cursor is always drawn on top. Alpha blending should be performed in linear color space.
- Foreground Color & Security: The underlying cell SGR foreground color maps to
currentColor(for SVG). All external references (e.g.,http://...) are ignored for security purposes.
Example
- https://commons.wikimedia.org/wiki/File:Ghostscript_Tiger.svg
anyplex_test.ps1:"`e[H`e]app; gc='' id=tiger w=20 h=20 W=50 H=12 $(cat Ghostscript_Tiger.svg) f=h`a" while ($true) { for ($i = 0; $i -lt 40; $i++) { "`e[H`e]app;gc='' id=tiger x={0:N3} uw=$i f=n`a" -f (($i - 40) / 30) Start-Sleep -Milliseconds 10 } for ($i = 39; $i -gt 0; $i--) { "`e[H`e]app;gc='' id=tiger x={0:N3} uw=$i f=h`a" -f ($i / 30) Start-Sleep -Milliseconds 10 } for ($i = 0; $i -lt 40; $i++) { "`e[H`e]app;gc='' id=tiger x={0:N3} uw=0 f=n`a" -f ((-$i) / 30) Start-Sleep -Milliseconds 10 } }
v2026.04.11
Changes
- This release is not compatible with previous releases.
- AnyPlex Protocol, (tracked in #902):
- Implement image multiplexing.
- Re-rasterize when cell metrics change.
- Allow
<></>to be used as an empty document.

v2026.04.10
Changes
- AnyPlex:
- Fix crash on empty SVG canvas.
- Make
gc=' '(whitespace) by default. - Fix updating SVG document for the same id.
- Allow viewport clearing by printing
\e[H\e]app\a(or\e[H\e]app;id=non_registered_id\aif id="" is registered)."`e[H`e]app`a"
Animation Example
Use vtm -r term pwsh to test on Windows (multiplexing is not implemented yet).
- https://commons.wikimedia.org/wiki/File:Ghostscript_Tiger.svg
anyplex_test.ps1:"`e[H`e]app; gc='' id=tiger align=left width=80 height=20 $(cat Ghostscript_Tiger.svg) flip=h`a" while ($true) { for ($i = -160; $i -lt 160; $i++) { "`e[H`e]app;gc='' align=left id=tiger flip=h dx={0:N3}`a" -f ($i / 10) Start-Sleep -Milliseconds 15 } for ($i = 320; $i -gt 0; $i--) { "`e[H`e]app;gc='' align=left id=tiger dx={0:N3}`a" -f ($i / 10) Start-Sleep -Milliseconds 15 } }


