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:
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]:
{"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:
source: demos/my-recording.termshow
settings:
idle_time_limit: 2.0 # Cap any idle gap to 2 seconds
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 sectionSettings Reference
| Setting | Default | Description |
|---|---|---|
idle_time_limit |
3.0 |
Maximum seconds for any idle gap |
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-right, bottom-left, bottom-right.
Embedding in Pages
Use the termshow Quarto shortcode in any .qmd file:
## 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:
- Play/Pause button — Toggles playback. Shows ↺ (replay) at the end.
- Current time — Elapsed time counter.
- Timeline scrub bar — Click anywhere to seek. Chapter markers appear as gold ticks with wider hit targets for easy clicking.
- Remaining time — Counts down to zero during playback.
- 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:
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
great-docs termshow record demos/install-guide.termshowThis 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:
source: demos/install-guide.termshow
settings:
idle_time_limit: 1.5
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: calloutStep 3: Preview
great-docs termshow play demos/install-guide.termshowThis 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:
Step 5: Build
great-docs buildDuring the build, Great Docs:
- Finds all
.termshowfiles in your project - Renders each recording into a series of SVG keyframes
- Generates a
manifest.jsonwith timing, chapters, and annotations - 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 other tools? Import them:
# From asciinema (.cast files)
great-docs termshow import-cast recording.cast demos/my-demo
# From VHS (.tape files)
great-docs termshow import-tape demo.tape demos/my-demoThe 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.
- Use
idle_time_limit— Caps long pauses so viewers aren’t waiting through your thinking time. - Place chapters at logical transitions — Each chapter should represent one distinct step in the workflow.
- Use
pause_on_chaptersfor 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):
core.pydiscovers.termshowfiles and calls the renderer- The renderer parses the NDJSON recording + YAML script
- It produces SVG keyframes at each visual change point
- A
manifest.jsoncaptures timing, chapters, and annotation data - The Lua shortcode embeds everything inline as
<script>JSON blocks
Page load (JavaScript):
termshow.jsfinds.gd-termshowcontainers- Reads inline manifest and SVG frame data from
<script>elements - Builds the player UI (viewport, controls, chapter bar, overlays)
- 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