record-tui

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Record TUI - Terminal Demo Recording with VHS

录制TUI - 使用VHS完成终端演示录制

Overview

概述

Record polished terminal demos using Charmbracelet VHS. VHS turns
.tape
scripts into GIFs, MP4s, and WebMs — reproducible, version-controlled, and CI-friendly.
Core principle: Write tape files as code, not as screen captures. Every demo should be reproducible from a single
.tape
file.
使用 Charmbracelet VHS 录制精美的终端演示内容。VHS可以将
.tape
脚本转换为GIF、MP4、WebM格式文件——可复现、支持版本控制,且适配CI环境。
核心理念: 将tape文件作为代码编写,而非直接录屏。每一份演示都应当可以通过单个
.tape
文件复现。

When to Use

适用场景

Use this skill when:
  • Recording a demo GIF for a README or docs
  • Creating video walkthroughs of CLI/TUI applications
  • Setting up automated demo recording in CI/CD
  • Writing
    .tape
    files for VHS
  • Troubleshooting VHS output quality (choppy GIFs, wrong dimensions, timing issues)
Avoid when:
  • Recording non-terminal content (use screen capture tools instead)
  • One-off manual recordings where reproducibility doesn't matter (use
    asciinema
    )
  • The app has no terminal interface
以下场景可使用本技能:
  • 为README或文档录制演示GIF
  • 制作CLI/TUI应用的视频演示教程
  • 在CI/CD中配置自动化演示录制
  • 为VHS编写
    .tape
    文件
  • 排查VHS输出质量问题(GIF卡顿、尺寸错误、时序问题)
以下场景不建议使用:
  • 录制非终端内容(请使用屏幕录制工具)
  • 不需要复现的一次性手动录制(请使用
    asciinema
  • 应用没有终端交互界面

Prerequisites

前置要求

VHS requires two dependencies:
bash
undefined
VHS需要以下两个依赖:
bash
undefined

macOS

macOS

brew install charmbracelet/tap/vhs ffmpeg ttyd
brew install charmbracelet/tap/vhs ffmpeg ttyd

Debian/Ubuntu

Debian/Ubuntu

sudo apt install ffmpeg && sudo snap install ttyd --classic go install github.com/charmbracelet/vhs@latest

**Verify:** `vhs --version && ffmpeg -version && ttyd --version`
sudo apt install ffmpeg && sudo snap install ttyd --classic go install github.com/charmbracelet/vhs@latest

**验证安装:** `vhs --version && ffmpeg -version && ttyd --version`

Phase 1: Plan the Recording

阶段1:规划录制内容

Before writing a tape file, answer these questions:
  1. What are you recording? — The exact command to launch the app
  2. What interactions to show? — Key presses, navigation, typing sequences
  3. What's the target format? — GIF (README), MP4 (docs site), WebM (web)
  4. What dimensions? — Match your app's ideal viewport
Recommended dimensions by use case:
Use CaseWidthHeightFontSize
README GIF120060020
Docs/tutorial140080018
Social media120063022
Full TUI app160090016
Compact CLI demo80040020
编写tape文件前,请先明确以下问题:
  1. 你要录制的内容是什么? —— 启动应用的精确命令
  2. 需要展示哪些交互? —— 按键、导航、输入序列
  3. 目标输出格式是什么? —— GIF(适用于README)、MP4(适用于文档站点)、WebM(适用于网页)
  4. 输出尺寸是多少? —— 匹配应用的理想视口大小
不同场景推荐尺寸:
场景宽度高度字号
README GIF120060020
文档/教程140080018
社交媒体120063022
完整TUI应用160090016
紧凑型CLI演示80040020

Phase 2: Write the Tape File

阶段2:编写Tape文件

Tape File Structure

Tape文件结构

Every tape file follows this order:
tape
undefined
所有tape文件都遵循以下顺序:
tape
undefined

1. Output declaration

1. 声明输出路径

Output demo.gif
Output demo.gif

2. Requirements (optional)

2. 依赖声明(可选)

Require my-app
Require my-app

3. Settings (MUST come before commands)

3. 配置设置(必须放在命令之前)

Set Shell "bash" Set FontSize 20 Set Width 1200 Set Height 600 Set Theme "Catppuccin Frappe" Set WindowBar Colorful Set Padding 20 Set TypingSpeed 75ms
Set Shell "bash" Set FontSize 20 Set Width 1200 Set Height 600 Set Theme "Catppuccin Frappe" Set WindowBar Colorful Set Padding 20 Set TypingSpeed 75ms

4. Hidden setup (optional)

4. 隐藏的前置配置(可选)

Hide Type "export TERM=xterm-256color" Enter Sleep 500ms Ctrl+L Show
Hide Type "export TERM=xterm-256color" Enter Sleep 500ms Ctrl+L Show

5. Visible interactions

5. 可见的交互操作

Type "my-app --demo" Sleep 500ms Enter Sleep 2s
Type "my-app --demo" Sleep 500ms Enter Sleep 2s

6. App interactions

6. 应用内交互

Down Down Down Enter Sleep 1s Type "hello world" Enter Sleep 3s
Down Down Down Enter Sleep 1s Type "hello world" Enter Sleep 3s

7. Hidden cleanup (optional)

7. 隐藏的清理操作(可选)

Hide Ctrl+c Sleep 500ms
undefined
Hide Ctrl+c Sleep 500ms
undefined

Essential Commands

核心命令

CommandExamplePurpose
Output
Output demo.gif
Set output (gif/mp4/webm/ascii)
Set
Set FontSize 20
Configure settings
Type
Type "hello"
Emulate typing
Type@Nms
Type@100ms "slow"
Type at specific speed
Enter
/
Tab
/
Space
Enter
Key presses
Up
/
Down
/
Left
/
Right
Down 3
Navigation (with repeat)
Ctrl+key
Ctrl+c
Modifier combos
Sleep
Sleep 2s
Pause (ms or s)
Wait+Screen
Wait+Screen /ready/
Wait for screen content
Hide
/
Show
Hide
Control recording visibility
Screenshot
Screenshot step1.png
Capture current frame
Env
Env TERM "xterm-256color"
Set env variable
Source
Source setup.tape
Include another tape
Require
Require node
Fail if not in PATH
For complete command details, settings, and timing guidelines, see Command Reference.
命令示例用途
Output
Output demo.gif
设置输出(gif/mp4/webm/ascii)
Set
Set FontSize 20
配置设置项
Type
Type "hello"
模拟输入
Type@Nms
Type@100ms "slow"
按指定速度输入
Enter
/
Tab
/
Space
Enter
模拟按键
Up
/
Down
/
Left
/
Right
Down 3
导航操作(支持重复次数)
Ctrl+key
Ctrl+c
组合快捷键
Sleep
Sleep 2s
暂停(单位ms或s)
Wait+Screen
Wait+Screen /ready/
等待屏幕出现指定内容
Hide
/
Show
Hide
控制录制可见性
Screenshot
Screenshot step1.png
捕获当前帧
Env
Env TERM "xterm-256color"
设置环境变量
Source
Source setup.tape
引入其他tape文件
Require
Require node
依赖不存在时终止执行
完整的命令说明、配置项、时序指南请参考 命令参考

Phase 3: Smart Tape Generation

阶段3:智能生成Tape文件

When asked to generate a tape file for a specific app, follow this process:
当需要为特定应用生成tape文件时,遵循以下流程:

Step 1: Analyze the App

步骤1:分析应用

Read the app's code or help output to understand:
  • How it launches (command, flags, arguments)
  • Key interactions (what keys it responds to)
  • Visual states worth showing (menus, forms, results)
阅读应用代码或帮助输出,明确以下内容:
  • 启动方式(命令、参数、标志位)
  • 核心交互(支持哪些按键)
  • 值得展示的视觉状态(菜单、表单、运行结果)

Step 2: Generate the Tape

步骤2:生成Tape文件

Build the tape file showing the app's key features:
bash
undefined
构建tape文件以展示应用的核心功能:
bash
undefined

Generate and preview

生成并预览

vhs validate demo.tape # Check syntax vhs demo.tape # Record
undefined
vhs validate demo.tape # 检查语法 vhs demo.tape # 录制
undefined

Step 3: Iterate

步骤3:迭代优化

Run the tape, review the output, adjust timing and interactions.
Useful iteration commands:
bash
undefined
运行tape文件,检查输出效果,调整时序和交互逻辑。
实用迭代命令:
bash
undefined

Quick preview without saving

快速预览不保存输出

vhs demo.tape --output /dev/null
vhs demo.tape --output /dev/null

Test specific section — use Source to split tapes

测试特定片段 —— 使用Source拆分tape文件

vhs section-test.tape
undefined
vhs section-test.tape
undefined

Available Templates

可用模板

Use these as starting points — copy and customize:
  • Basic CLI Demo — Simple command + output recording
  • Interactive TUI Demo — Navigation, forms, keyboard interaction
  • Build-and-Run Demo — Hidden compilation, visible app usage
  • Multi-Panel TUI — Complex apps like lazygit, k9s
  • CI Golden File — ASCII output for regression testing
  • Composable Tapes — DRY settings with
    Source
For complete copy-paste templates, see Templates.
你可以使用以下模板作为起点,复制后自定义即可:
  • 基础CLI演示 —— 简单命令+输出录制
  • 交互式TUI演示 —— 导航、表单、键盘交互
  • 构建并运行演示 —— 隐藏编译过程,展示应用使用
  • 多面板TUI —— 复杂应用如lazygit、k9s
  • CI基准文件 —— 用于回归测试的ASCII输出
  • 可组合Tape —— 通过
    Source
    复用配置
完整的可复制模板请参考 模板库

Phase 4: Optimize Output

阶段4:优化输出效果

GIF Optimization

GIF优化

GIFs can get large. Reduce size with:
tape
Set Framerate 15          # Lower framerate (default 30)
Set PlaybackSpeed 1.5     # Speed up slow parts
Set Width 800             # Smaller dimensions
Post-processing with gifsicle (optional):
bash
gifsicle -O3 --lossy=80 demo.gif -o demo-optimized.gif
Target sizes:
  • README GIF: < 5 MB (GitHub renders inline)
  • Docs GIF: < 10 MB
  • If over 10 MB, consider MP4 or WebM instead
GIF文件体积容易过大,可以通过以下方式压缩:
tape
Set Framerate 15          # 降低帧率(默认30)
Set PlaybackSpeed 1.5     # 加快慢动作片段
Set Width 800             # 缩小尺寸
使用gifsicle后处理(可选):
bash
gifsicle -O3 --lossy=80 demo.gif -o demo-optimized.gif
目标体积:
  • README GIF:< 5 MB(支持GitHub内联渲染)
  • 文档GIF:< 10 MB
  • 如果超过10 MB,建议改用MP4或WebM格式

Timing Tips

时序优化技巧

  • Sleep 500ms
    after typing a command — lets the viewer read it
  • Sleep 2-3s
    after Enter — lets the viewer see the output
  • Sleep 3-5s
    on the final frame — prevents abrupt loop restart
  • Set LoopOffset 0%
    smoother GIF looping
  • Use
    Type@100ms
    for important text the viewer should follow
  • Use
    Type@30ms
    for boilerplate the viewer doesn't need to read
  • 输入命令后加
    Sleep 500ms
    —— 方便观众阅读输入内容
  • 按Enter后加
    Sleep 2-3s
    —— 方便观众查看输出结果
  • 最后一帧加
    Sleep 3-5s
    —— 避免循环重启过于突兀
  • Set LoopOffset 0%
    让GIF循环更流畅
  • 重要内容使用
    Type@100ms
    输入 —— 方便观众跟随阅读
  • 不需要阅读的样板内容使用
    Type@30ms
    快速输入

Phase 5: CI/CD Integration

阶段5:CI/CD集成

GitHub Actions

GitHub Actions

yaml
name: Record Demo
on:
  push:
    branches: [main]
    paths:
      - "demo.tape"
      - "src/**"

jobs:
  record:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Record demo
        uses: charmbracelet/vhs-action@v2
        with:
          path: "demo.tape"

      - name: Commit updated GIF
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "docs: update demo recording"
          file_pattern: "*.gif"
yaml
name: Record Demo
on:
  push:
    branches: [main]
    paths:
      - "demo.tape"
      - "src/**"

jobs:
  record:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Record demo
        uses: charmbracelet/vhs-action@v2
        with:
          path: "demo.tape"

      - name: Commit updated GIF
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "docs: update demo recording"
          file_pattern: "*.gif"

Golden File Testing

基准文件测试

Use ASCII output to detect visual regressions:
tape
Output demo.ascii
使用ASCII输出检测视觉回归:
tape
Output demo.ascii

... your interactions ...

... 你的交互逻辑 ...


```bash

```bash

In CI: compare against committed golden file

在CI中:与提交的基准文件对比

vhs demo.tape diff demo.ascii demo.ascii.golden
undefined
vhs demo.tape diff demo.ascii demo.ascii.golden
undefined

Examples

示例

Good: Well-Structured Tape File

正面示例:结构规范的Tape文件

<Good>
tape
undefined
<Good>
tape
undefined

Clear output declaration

清晰的输出声明

Output demo.gif
Output demo.gif

Explicit dependency

显式声明依赖

Require gum
Require gum

All settings grouped at top

所有配置项集中放在顶部

Set Shell "bash" Set FontSize 20 Set Width 1200 Set Height 600 Set Theme "Catppuccin Frappe" Set WindowBar Colorful Set TypingSpeed 75ms Set Padding 20
Set Shell "bash" Set FontSize 20 Set Width 1200 Set Height 600 Set Theme "Catppuccin Frappe" Set WindowBar Colorful Set TypingSpeed 75ms Set Padding 20

Hidden setup — always Ctrl+L before Show to clear the screen

隐藏的前置配置 —— Show前始终执行Ctrl+L清屏

Hide Type "export GLAMOUR_STYLE=dark" Enter Sleep 500ms Ctrl+L Show
Hide Type "export GLAMOUR_STYLE=dark" Enter Sleep 500ms Ctrl+L Show

Deliberate pacing — viewer can follow

合理的节奏 —— 方便观众跟随

Type "gum choose 'Option A' 'Option B' 'Option C'" Sleep 500ms Enter Sleep 1s
Type "gum choose 'Option A' 'Option B' 'Option C'" Sleep 500ms Enter Sleep 1s

Navigate with visible pauses

导航操作带可见停顿

Down Sleep 300ms Down Sleep 300ms Enter Sleep 2s
Down Sleep 300ms Down Sleep 300ms Enter Sleep 2s

Generous final pause for loop

足够的最终停顿保证循环效果

Sleep 3s

</Good>
Sleep 3s

</Good>

Bad: Common Mistakes

负面示例:常见错误

<Bad>
tape
undefined
<Bad>
tape
undefined

Missing Output declaration — VHS won't know where to save

缺少Output声明 —— VHS不知道保存路径

Settings scattered throughout (will error or be ignored)

配置项分散在各处(会报错或被忽略)

Type "my-app" Set FontSize 20 Enter Set Theme "Dracula"
Type "my-app" Set FontSize 20 Enter Set Theme "Dracula"

No Sleep after Enter — output flashes by

Enter后没有Sleep —— 输出一闪而过

Type "my-app run" Enter Type "my-app status" Enter
Type "my-app run" Enter Type "my-app status" Enter

No final Sleep — GIF loops abruptly

没有最终Sleep —— GIF循环非常突兀

No Require — silently fails if app missing

没有Require声明 —— 应用缺失时会静默失败


</Bad>

</Bad>

Bad: TUI Recording Anti-Patterns

负面示例:TUI录制反模式

<Bad>
tape
Output demo.gif
Set Width 600
Set Height 300
<Bad>
tape
Output demo.gif
Set Width 600
Set Height 300

Too small — TUI elements will be cramped and unreadable

尺寸过小 —— TUI元素会拥挤难以阅读

Type "lazygit" Enter
Type "lazygit" Enter

No Sleep — app hasn't loaded yet, next keys arrive too early

没有Sleep —— 应用还未加载,后续按键会提前触发

Tab Tab Tab Tab Tab
Tab Tab Tab Tab Tab

Rapid-fire navigation — viewer can't follow what's happening

过快的导航操作 —— 观众无法跟上操作逻辑

Type "c" Type "feat: add feature" Enter
Type "c" Type "feat: add feature" Enter

No pauses between actions — looks like a blur

操作之间没有停顿 —— 整体效果模糊不清


</Bad>

For a complete well-structured TUI example (lazygit, k9s), see **[Templates](./reference/TEMPLATES.md)**.

</Bad>

完整的规范TUI示例(lazygit、k9s)请参考 **[模板库](./reference/TEMPLATES.md)**。

Troubleshooting

故障排查

Problem: GIF is choppy or laggy

问题:GIF卡顿或延迟

Cause: Framerate too high for GIF format, or file too large for viewer.
Solution:
tape
Set Framerate 15            # Lower from default 30
Set PlaybackSpeed 1.0       # Don't speed up
If still choppy, reduce dimensions or switch to MP4.
原因: GIF格式的帧率过高,或文件体积过大导致加载慢。
解决方案:
tape
Set Framerate 15            # 从默认30降低
Set PlaybackSpeed 1.0       # 不要加速播放
如果还是卡顿,降低尺寸或切换为MP4格式。

Problem: TUI doesn't render correctly

问题:TUI渲染异常

Cause: Missing TERM variable, wrong shell, or app needs specific setup.
Solution:
tape
Hide
Env TERM "xterm-256color"
Type "stty rows 50 cols 120"
Enter
Sleep 500ms
Ctrl+L
Show
原因: 缺少TERM变量、shell配置错误,或应用需要特定前置配置。
解决方案:
tape
Hide
Env TERM "xterm-256color"
Type "stty rows 50 cols 120"
Enter
Sleep 500ms
Ctrl+L
Show

Problem: Keys arrive before app is ready

问题:应用就绪前按键就已触发

Cause: No Sleep after launching the app — VHS sends keystrokes immediately.
Solution: Always add
Sleep 1-3s
after launching a TUI app:
tape
Type "my-tui"
Enter
Sleep 2s          # Wait for app to initialize
Down              # Now safe to interact
For apps with variable startup time, use
Wait
:
tape
Type "my-tui"
Enter
Wait+Screen /ready/    # Wait until "ready" appears on screen
Down
原因: 启动应用后没有Sleep —— VHS会立即发送按键指令。
解决方案: 启动TUI应用后始终添加
Sleep 1-3s
tape
Type "my-tui"
Enter
Sleep 2s          # 等待应用初始化
Down              # 此时再交互是安全的
对于启动时间不确定的应用,使用
Wait
tape
Type "my-tui"
Enter
Wait+Screen /ready/    # 等待屏幕出现"ready"字样
Down

Problem: VHS command not found

问题:找不到VHS命令

Cause: Missing VHS, ffmpeg, or ttyd.
Solution:
bash
undefined
原因: 缺少VHS、ffmpeg或ttyd依赖。
解决方案:
bash
undefined

macOS

macOS

brew install charmbracelet/tap/vhs ffmpeg ttyd
brew install charmbracelet/tap/vhs ffmpeg ttyd

Verify all three

验证三个依赖都已安装

vhs --version && ffmpeg -version && ttyd --version
undefined
vhs --version && ffmpeg -version && ttyd --version
undefined

Problem: GIF too large for GitHub

问题:GIF体积超过GitHub限制

Cause: High resolution, long recording, or high framerate.
Solution:
  1. Reduce dimensions:
    Set Width 800
    /
    Set Height 400
  2. Lower framerate:
    Set Framerate 15
  3. Speed up slow sections:
    Set PlaybackSpeed 1.5
  4. Post-process:
    gifsicle -O3 --lossy=80 demo.gif -o demo-small.gif
  5. If still too large, use MP4 and embed with
    <video>
    tag
原因: 分辨率过高、录制时长过长或帧率过高。
解决方案:
  1. 降低尺寸:
    Set Width 800
    /
    Set Height 400
  2. 降低帧率:
    Set Framerate 15
  3. 加快慢片段速度:
    Set PlaybackSpeed 1.5
  4. 后处理压缩:
    gifsicle -O3 --lossy=80 demo.gif -o demo-small.gif
  5. 如果还是太大,改用MP4格式并用
    <video>
    标签嵌入

Integration

集成搭配

This skill pairs with:
  • build-tui — Record demos of TUIs you build
  • git-worktree — Test recordings across branches
  • track-session — Track recording iteration progress
Useful alongside:
本技能可与以下技能搭配使用:
  • build-tui —— 为你开发的TUI录制演示
  • git-worktree —— 跨分支测试录制效果
  • track-session —— 跟踪录制迭代进度
配套工具推荐:

Quick Reference

快速参考

bash
vhs validate demo.tape            # Check syntax
vhs demo.tape                     # Record
vhs demo.tape --output custom.gif # Custom output path
vhs themes                        # List available themes
vhs new demo.tape                 # Create tape from template
Key commands cheat sheet:
CommandPurpose
Output file.gif
Set output file and format
Require app
Fail if dependency missing
Set Key Value
Configure terminal settings
Type "text"
Emulate typing
Type@100ms "text"
Type at specific speed
Enter
/
Tab
/
Space
Key presses
Up
/
Down
/
Left
/
Right
Navigation
Ctrl+c
Modifier key combos
Sleep 2s
Pause execution
Wait+Screen /regex/
Wait for screen content
Hide
/
Show
Control recording visibility
Screenshot file.png
Capture current frame
Env VAR "val"
Set environment variable
Source other.tape
Include another tape file
bash
vhs validate demo.tape            # 检查语法
vhs demo.tape                     # 执行录制
vhs demo.tape --output custom.gif # 自定义输出路径
vhs themes                        # 列出可用主题
vhs new demo.tape                 # 从模板创建tape文件
核心命令速查表:
命令用途
Output file.gif
设置输出文件和格式
Require app
依赖缺失时终止执行
Set Key Value
配置终端设置
Type "text"
模拟输入
Type@100ms "text"
按指定速度输入
Enter
/
Tab
/
Space
模拟按键
Up
/
Down
/
Left
/
Right
导航操作
Ctrl+c
组合快捷键
Sleep 2s
暂停执行
Wait+Screen /regex/
等待屏幕出现指定内容
Hide
/
Show
控制录制可见性
Screenshot file.png
捕获当前帧
Env VAR "val"
设置环境变量
Source other.tape
引入其他tape文件

Deep Reference

深度参考

For detailed guides, load these files when needed:
  • Command Reference — All VHS commands, settings, timing guidelines
  • Templates — Copy-paste tape file templates for common scenarios
Only load these when specifically needed to save context.
需要详细指南时可加载以下文件:
  • 命令参考 —— 所有VHS命令、配置项、时序指南
  • 模板库 —— 常见场景的可复制tape文件模板
仅在明确需要时加载这些文件以节省上下文空间。

References

参考链接