# Termshow Guide


# Overview

The **termshow** is Great Docs' built-in terminal recording player. It renders pre-recorded terminal sessions as interactive, frame-accurate SVG animations directly in your documentation pages -- no JavaScript framework dependencies, no external services.

Key capabilities:

- Frame-accurate SVG rendering of terminal output
- Chapter-based navigation with labeled markers
- Contextual annotations that appear at specific timestamps
- Keyboard shortcuts for power users
- Adjustable playback speed (0.5× to 3×)
- Works offline and with `file://` protocol (all data embedded inline)
- Responsive layout that scales to any viewport width
- Light/dark theme support (follows the site theme)


## Live Demo

Here's a recording of real Great Docs CLI commands -- `scan`, `lint`, and `term render` -- running against this very package:


<img src="../termshow/great-docs-cli/frame-000.svg" class="gd-termshow-poster" loading="lazy" alt="Terminal recording: great-docs-cli" />

Terminal recording: great-docs-cli (requires JavaScript for playback)


# The Recording Format

Termshow uses a two-file system for each recording:


## The `.termshow` File

This is the raw terminal recording in NDJSON format. Each line is a JSON array with `[delay, event_type, data]`:

``` json
{"version": 1, "format": "termshow", "term": {"cols": 80, "rows": 20}}
[0.5, "o", "$ "]
[0.1, "o", "echo hello"]
[0.6, "o", "\r\nhello\r\n"]
[1.0, "m", "Command executed"]
```

Event types:

| Type  | Meaning                                        |
|-------|------------------------------------------------|
| `"o"` | Output -- terminal data written to stdout       |
| `"i"` | Input -- user keystrokes (for display purposes) |
| `"m"` | Marker -- internal marker used for chapter sync |

The header line sets terminal dimensions and metadata.


## The `.termshow.yml` Script File

This companion file defines chapters, annotations, timing adjustments, and visual settings:

``` yaml
source: demos/my-recording.termshow

settings:
  window_chrome: colorful   # Window decoration style
  theme: monokai            # Terminal color scheme
  font_size: 14             # Font size in pixels

chapters:
  - at: 0.0
    label: Introduction
  - at: 5.0
    label: Configuration
  - at: 12.0
    label: Running Tests

annotations:
  - at: 1.0
    duration: 3.0
    text: This installs all required dependencies
    position: top-right
    style: callout
  - at: 6.0
    duration: 2.5
    text: Configuration is auto-detected
    position: bottom-right
    style: subtle

cuts:
  - from: 8.0
    to: 11.0
    type: ellipsis   # Shows '…' for the cut section

snippets:
  - at: 0.0
    duration: 5.0
    text: pip install my-package
    label: Install
  - at: 12.0
    duration: 4.0
    match: "\\$ (.+)"   # Regex: captures command after $ prompt
    label: Run
```


# Snippets

Snippets add a **copy button** to the player that appears during a time range. Readers can click it to copy text to their clipboard without manual retyping.


## Literal Text

Use `text` when you know the exact string to copy:

``` yaml
snippets:
  - at: 0.5
    duration: 7.0
    text: pip install my-tool
    label: Install
```


## Regex Match

Use `match` to extract text dynamically from the terminal buffer:

``` yaml
snippets:
  - at: 0.5
    duration: 7.0
    match: "\\$ (.+)"
    label: Copy Command
```

The regex runs against the visible terminal text when the reader clicks the copy button. If it has a capture group, group 1 is copied; otherwise the full match is used. This is useful when the terminal shows a typed command and you want to extract it without hardcoding.


## Snippet Fields

| Field      | Default      | Description                                 |
|------------|--------------|---------------------------------------------|
| `at`       | *(required)* | Time in seconds when the button appears     |
| `duration` | `5.0`        | How long the button stays visible           |
| `text`     | `""`         | Literal text copied on click                |
| `match`    | `""`         | Regex matched against visible terminal text |
| `label`    | `"Copy"`     | Button label shown alongside the copy icon  |

At least one of `text` or `match` must be provided. If both are set, `match` takes priority (with `text` as fallback).


# Settings Reference

| Setting         | Default    | Description                                    |
|-----------------|------------|------------------------------------------------|
| `window_chrome` | `colorful` | Window decoration: `colorful`, `plain`, `none` |
| `theme`         | (auto)     | Terminal color scheme                          |
| `font_size`     | `14`       | Font size in rendered SVG (px)                 |
| `line_height`   | `1.2`      | Line height multiplier                         |
| `padding`       | `12`       | Inner padding of the terminal area (px)        |


# Annotation Styles

Annotations appear as overlays on the terminal at specified times. Three styles are available:

| Style       | Appearance                                      |
|-------------|-------------------------------------------------|
| `callout`   | Semi-opaque dark card with accent border        |
| `subtle`    | Lighter, smaller text -- less intrusive          |
| `highlight` | Amber-tinted with warm border -- draws attention |

Positions: `top-left`, `top`, `top-right`, `left`, `right`, `bottom-left`, `bottom`, `bottom-right`.

Widths: `small` (25%), `medium` (50%, default), `large` (75%).


# Embedding in Pages

Use the `termshow` Quarto shortcode in any `.qmd` file:

``` markdown
## Basic usage


## With chapter pausing


## Autoplay with custom speed
```


## Shortcode Options

| Option | Default | Description |
|----|----|----|
| `file` | (required) | Path to `.termshow` file (without extension) |
| `autoplay` | `false` | Start playing automatically on page load |
| `loop` | `false` | Loop playback when reaching the end |
| `speed` | `1` | Initial playback speed multiplier |
| `pause_on_chapters` | `false` | Auto-pause at each chapter boundary |
| `controls` | `true` | Show the control bar |
| `theme` | `auto` | Player theme: `auto`, `dark`, or `light` |


# Player Controls

The player provides a full set of interactive controls:


## Control Bar

From left to right:

1.  **Play/Pause button** -- Toggles playback. Shows ↺ (replay) at the end.
2.  **Current time** -- Elapsed time counter.
3.  **Timeline scrub bar** -- Click anywhere to seek. Chapter markers appear as gold ticks with wider hit targets for easy clicking.
4.  **Remaining time** -- Counts down to zero during playback.
5.  **Speed button** -- Cycles through 0.5×, 1×, 1.5×, 2×, 3×.


## Chapter Bar

A thin overlay at the top of the player shows the name of the current chapter, updating as playback progresses.


## Center Overlay

A semi-transparent button in the center of the viewport:

- **Before playback** -- Shows ▶ as a call-to-action.
- **After playback ends** -- Shows ↺ to indicate replay. Clicking returns the player to its initial state (frame 0, ready to play).
- **During chapter pauses** -- Hidden, so the terminal content remains fully visible.


## Keyboard Shortcuts

Click the player viewport first to give it focus, then use:

| Key     | Action                                   |
|---------|------------------------------------------|
| `Space` | Play / Pause (or reset from ended state) |
| `→`     | Seek forward 5 seconds                   |
| `←`     | Seek backward 5 seconds                  |
| `.`     | Jump to next chapter                     |
| `,`     | Jump to previous chapter                 |


# Workflow

The full termshow workflow from recording to rendered page:

``` text
1. Record          great-docs termshow record demos/my-demo.termshow
2. Edit script     Create/edit demos/my-demo.termshow.yml
3. Preview         great-docs termshow play demos/my-demo.termshow
4. Embed           Add  to your .qmd
5. Build           great-docs build (renders SVG frames automatically)
```


## Step 1: Record

``` bash
great-docs termshow record demos/install-guide.termshow
```

This launches a recording session. Everything you type and see in the terminal is captured with precise timing. Press `Ctrl+D` or type `exit` to end the recording.


## Step 2: Create the Script

Create `demos/install-guide.termshow.yml` alongside the recording. Define chapters at logical breakpoints in your workflow, and add annotations to explain what's happening:

``` yaml
source: demos/install-guide.termshow

settings:
  window_chrome: colorful

chapters:
  - at: 0.0
    label: Setup
  - at: 8.0
    label: Install
  - at: 15.0
    label: Verify

annotations:
  - at: 1.0
    duration: 3.0
    text: Start by activating the virtual environment
    position: top-right
    style: callout
```


## Step 3: Preview

``` bash
great-docs termshow play demos/install-guide.termshow
```

This plays the recording in your terminal so you can verify timing and check that chapter boundaries feel natural.


## Step 4: Embed

Add the shortcode to any user guide or documentation page:

``` markdown
```


## Step 5: Build

``` bash
great-docs build
```

During the build, Great Docs:

1.  Finds all `.termshow` files in your project
2.  Renders each recording into a series of SVG keyframes
3.  Generates a `manifest.json` with timing, chapters, and annotations
4.  The Lua shortcode filter embeds the manifest and all SVG frames inline in the HTML -- no runtime fetches needed


# Importing Existing Recordings

Already have terminal recordings from asciinema? Import them:

``` bash
# From asciinema (.cast files)
great-docs termshow import-cast recording.cast demos/my-demo
```

The import preserves timing and terminal dimensions. You'll still want to create a `.termshow.yml` script to add chapters and annotations.


# Tips & Best Practices

- **Keep recordings short** -- 15-30 seconds is ideal. Split longer workflows into multiple recordings. waiting through your thinking time.
- **Place chapters at logical transitions** -- Each chapter should represent one distinct step in the workflow.
- **Use `pause_on_chapters`** for tutorials -- Gives readers time to absorb each step before the next one plays.
- **Annotations are brief** -- One sentence max. They complement the terminal output, not replace it.
- **Test at different speeds** -- Make sure annotations are still readable at 1.5× and 2× speed.
- **80 columns, 20 rows** works well for most CLI recordings. Use 60 columns for narrower TUI demos.


# Architecture

Under the hood, termshow works in two phases:

**Build time** (Python + Lua):

1.  `core.py` discovers `.termshow` files and calls the renderer
2.  The renderer parses the NDJSON recording + YAML script
3.  It produces SVG keyframes at each visual change point
4.  A `manifest.json` captures timing, chapters, and annotation data
5.  The Lua shortcode embeds everything inline as `<script>` JSON blocks

**Page load** (JavaScript):

1.  `termshow.js` finds `.gd-termshow` containers
2.  Reads inline manifest and SVG frame data from `<script>` elements
3.  Builds the player UI (viewport, controls, chapter bar, overlays)
4.  On play: advances time via `requestAnimationFrame`, swaps SVG frames at the correct timestamps

This architecture means:

- Zero network requests at runtime
- Works with `file://` protocol (offline docs)
- No CORS or fetch issues
- SVGs scale perfectly at any zoom level
