Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 50 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ continues to build only the Alacritty backend and does not require Zig.
| --------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `state` | cwd, size, cursor, window title, last command + exit code, effective timeouts, text snapshot. |
| `text [--full]` | Plain text of the viewport (or scrollback). |
| `screenshot [-o file.svg] [--full]` | Terminal text to stdout, or a crisp full-color SVG image (svg-term-style window) to a file. |
| `screenshot [-o file.svg] [--full] [--zoom N]` | Terminal text to stdout, or a full-color SVG scaled without changing its terminal cells. |
| `cells X Y [W H]` | Per-cell attributes (char, fg, bg, flags). |
| `get command\|output\|exit-code\|cwd\|cursor\|size\|title` | Structured getters. |

Expand Down Expand Up @@ -312,7 +312,13 @@ Colors accept ANSI-256 (`9`), hex (`#ff0000`), or rgb (`255,0,0`).

### Screenshots

Screenshots render a snapshot of the session in the current terminal by default, but can render an SVG using the `-o` output flag. Nerd Font icons are embedded as vector paths, so SVGs remain self-contained without changing the font stack for regular text.
Screenshots render a snapshot of the session in the current terminal by
default, but can render an SVG using the `-o` output flag. `--zoom 0.5`
halves the image dimensions while preserving the same rows and columns. Nerd
Font icons are embedded as vector paths, so SVGs remain self-contained without
changing the font stack for regular text.
Rendered screenshots and recordings append `COLSxROWS` to the program title;
when the terminal has no title they use `tui-test capture - COLSxROWS`.

<p align="center">
<img alt="full-color SVG screenshot of a TUI rendered by tui-test" src="static/screen.svg" width="400">
Expand All @@ -326,25 +332,27 @@ Record a selected part of a session directly to animated APNG (primary), GIF

| Command | Description |
| --- | --- |
| `record start OUT [--format apng\|gif\|mp4\|cast] [--fps N] [--speed N] [--idle-time-limit SEC]` | Start recording. Format is inferred from `.png`/`.apng`, `.gif`, `.mp4`, or `.cast`. |
| `record start OUT [--format apng\|gif\|mp4\|cast] [--fps N] [--speed N] [--idle-time-limit SEC] [--zoom N]` | Start recording. Format is inferred from `.png`/`.apng`, `.gif`, `.mp4`, or `.cast`. |
| `record stop` | Stop recording and finish the output file. |
| `get-recording [session]` | Print the separate, always-on session cast to stdout. |

```sh
tui-test open
tui-test record start demo.png # lossless animated PNG
tui-test record start demo.png --zoom 0.5
tui-test submit "echo hello"
tui-test wait command
tui-test record stop
```

APNG keeps full 24/32-bit color. APNG, GIF, and MP4 render at 2x pixel density
for sharper text; GIF additionally uses palette quantization for viewers that
cannot display APNG. MP4 export streams rendered frames to `ffmpeg` using H.264,
and starting an MP4 recording fails immediately unless `ffmpeg` is available on
`PATH`. Defaults are 30 fps, 1x speed, a 5-second idle-gap limit, and a 3-second
final hold. If a process exits before `record stop`, APNG/GIF/MP4 capture remains
beside the target as `OUT.tui-test.cast`.
for sharper text; `--zoom` multiplies those dimensions, so `--zoom 0.5`
produces a 1x-size export with the same terminal cells. GIF additionally uses
palette quantization for viewers that cannot display APNG. MP4 export streams
rendered frames to `ffmpeg` using H.264, and starting an MP4 recording fails
immediately unless `ffmpeg` is available on `PATH`. Defaults are 30 fps, 1x
speed, 1x zoom, a 5-second idle-gap limit, and a 3-second final hold. Zoom does
not apply to cast output. If a process exits before `record stop`, APNG/GIF/MP4
capture remains beside the target as `OUT.tui-test.cast`.

Raster export uses the selected JetBrains Mono bundle tier, when enabled, plus
installed system fonts for Unicode fallbacks. The CLI and language bindings
Expand All @@ -357,6 +365,38 @@ silently substituting unsupported glyphs.
<img alt="animated APNG terminal recording produced by tui-test" src="static/recording.png" width="400">
</p>

The same 48x10-cell recording rendered at native 100%, 50%, and 25% zoom:

<p align="center">
<strong>100%</strong><br>
<img alt="terminal recording rendered at 100 percent zoom" src="static/recording-zoom-100.png">
</p>

<p align="center">
<strong>50%</strong><br>
<img alt="terminal recording rendered at 50 percent zoom" src="static/recording-zoom-50.png">
</p>

<p align="center">
<strong>25%</strong><br>
<img alt="terminal recording rendered at 25 percent zoom" src="static/recording-zoom-25.png">
</p>

Resize events keep the encoded canvas stable while existing terminal content
reflows as the window grows and shrinks in place:

<p align="center">
<img alt="animated GIF showing a centered terminal window resizing" src="static/resize-demo.gif" width="600">
</p>

Regenerate the checked-in SVG, APNG, GIF, Nerd Font, and resize examples with:

```sh
bash scripts/regenerate-static-media.sh
```

The manually captured `static/tui-test-demo.mp4` is intentionally left unchanged.

Every session also records automatically from open in `.cast` format. Export it
with `tui-test get-recording > demo.cast` for the wider asciicast ecosystem.
This interoperability is implemented directly from the public asciicast v2
Expand Down
21 changes: 12 additions & 9 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ without parsing text:
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `state` | cwd, size, cursor, last command + exit code, timeouts, and a text snapshot. |
| `text [--full]` | Rendered viewport text, or full scrollback with `--full`. |
| `screenshot [PATH] [-o FILE] [--full]` | Terminal text to stdout, or a full-color SVG image (crisp at any zoom, svg-term-style window) when a path is given. |
| `screenshot [PATH] [-o FILE] [--full] [--zoom N]` | Terminal text to stdout, or a full-color SVG scaled without changing its terminal cells. |
| `cells X Y [W H]` | Per-cell attributes (char, fg, bg, flags) for a region. |
| `get command\|output\|exit-code\|cwd\|cursor\|size\|title` | One structured field. |

Expand Down Expand Up @@ -125,7 +125,7 @@ Colors accept ansi-256 (`9`), hex (`#ff0000`), or rgb (`255,0,0`).

| Command | Description |
| ----------------------------------- | ---------------------------------------------------------------------------- |
| `record start OUT [options]` | Start APNG, GIF, or asciicast recording (format inferred from extension). |
| `record start OUT [options]` | Start APNG, GIF, MP4, or asciicast recording; `--zoom N` scales image/video output. |
| `record stop` | Finish the active recording. |
| `get-recording [session]` | Print the always-on asciinema v2 cast (works even after the session stopped).|
| `monitor` | Watch the session live, full-color, in another terminal. |
Expand Down Expand Up @@ -213,20 +213,23 @@ tui-test get-recording > demo.cast # current session's recording to stdout
tui-test get-recording work > w.cast # a specific session by name (even if stopped)
```

Record a selected span directly to APNG (primary), GIF (fallback), or cast:
Record a selected span directly to APNG, GIF, MP4, or cast:

```sh
tui-test record start demo.png
tui-test record start demo.png --zoom 0.5
tui-test submit "echo hello"
tui-test wait command
tui-test record stop
```

APNG and GIF render at 2x pixel density. Use `--fps`, `--speed`, and
`--idle-time-limit` to tune playback. `.cast` output interoperates with the
asciicast ecosystem without adding any GPL dependency to tui-test. If a
process exits before `record stop`, an APNG/GIF capture remains beside the
target as `OUT.tui-test.cast`.
APNG, GIF, and MP4 render at 2x pixel density. `--zoom` multiplies the output
dimensions without changing the rows or columns; `--zoom 0.5` produces a 1x
export. Resize events change the terminal window size inside a centered,
opaque canvas sized for the recording's largest frame. Use `--fps`, `--speed`,
and `--idle-time-limit` to tune playback. `.cast` output does not use zoom and
interoperates with the asciicast ecosystem without adding any GPL dependency
to tui-test. If a process exits before `record stop`, an APNG/GIF/MP4 capture
remains beside the target as `OUT.tui-test.cast`.

## Live monitor

Expand Down
6 changes: 4 additions & 2 deletions bindings/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,17 @@ Cancelling a promise does not cancel the underlying Rust operation. Operations f
Closing a session removes it from `sessions()`, but keeps its recording. `getRecording()` can read that recording for the rest of the process. The 1024 most recently closed sessions have their recordings retained.

```js
await su.startRecording("demo.png", { fps: 30, speed: 1 });
await su.startRecording("demo.png", { fps: 30, speed: 1, zoom: 0.5 });
await su.submit("echo hello");
await su.waitCommand();
const path = await su.stopRecording();
```

`.png`/`.apng` selects lossless APNG, `.gif` selects GIF, `.mp4` selects MP4,
and `.cast` selects asciicast v2. The `format` option can override extension
inference. MP4 recording requires `ffmpeg` to be available on `PATH`.
inference. `zoom` scales SVG screenshots and image/video recordings without
changing terminal rows or columns. MP4 recording requires `ffmpeg` to be
available on `PATH`.

## Configuration

Expand Down
6 changes: 4 additions & 2 deletions bindings/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,17 @@ Cancelling a task does not cancel the underlying Rust operation. Operations for
Closing a session removes it from `sessions()`, but keeps its recording. `get_recording()` can read that recording for the rest of the process. The 1024 most recently closed sessions have their recordings retained.

```python
await su.start_recording("demo.png", fps=30, speed=1.0)
await su.start_recording("demo.png", fps=30, speed=1.0, zoom=0.5)
await su.submit("echo hello")
await su.wait_command()
path = await su.stop_recording()
```

`.png`/`.apng` selects lossless APNG, `.gif` selects GIF, `.mp4` selects MP4,
and `.cast` selects asciicast v2. Pass `format=` to override extension
inference. MP4 recording requires `ffmpeg` to be available on `PATH`.
inference. `zoom=` scales SVG screenshots and image/video recordings without
changing terminal rows or columns. MP4 recording requires `ffmpeg` to be
available on `PATH`.

## Configuration

Expand Down
Loading
Loading