关于 tui-validate
tui-validate 是用于测试终端用户界面的技能,通过捕获终端输出并借助 LLM 进行语义或视觉判断。它为应用开发和测试流程提供预设及自定义标准。
主要功能
- 01捕获文件、命令、tmux 或缓冲区输出
- 02支持语义、严格和视觉验证模式
- 03内置 Ralph 和通用 TUI 验证标准
- 04保存为 SVG、PNG 或文本
适用场景
- 01检查代码变更后的 TUI 布局
- 02验证交互后的界面状态
- 03生成经过验证的终端截图
- 04对终端应用执行视觉回归检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mikeyobrien/ ralph-orchestrator --skill tui-validate安装后在 Claude Code 中输入/tui-validate确认已加载。
详细介绍
TUI Validate
概述
此技能通过捕获 TUI 应用的输出,并使用 LLM-as-judge 进行语义验证,来验证终端用户界面(TUI)应用。它借助 Charmbracelet 的 freeze 生成高保真终端截图,并提供结构化的验证标准。
理念:此技能不采用脆弱的字符串匹配,而是利用语义理解来验证 TUI 输出是否“看起来正确”——检查布局、内容是否存在以及视觉层级,避免因细微的格式变化而失败。
适用场景
- 更改后验证 TUI 渲染效果
- 检查 UI 组件是否正确显示
- 对终端应用进行视觉回归测试
- 验证特定交互后的 TUI 状态
- 创建带验证的文档截图
先决条件
必需:
- 已安装
freezeCLI 工具(brew install charmbracelet/tap/freeze) - 用于交互式 TUI 捕获的
tmux(可选,适用于实时应用)
验证:
# Check freeze is installed
freeze --version
# Check tmux is installed (for interactive capture)
tmux -V
参数
-
target(必需):要验证的目标。可以是以下之一:
file:<path>- 要验证的 ANSI 输出文件command:<cmd>- 要执行并捕获输出的命令tmux:<session>- 要捕获的实时 tmux 会话buffer:<text>- 要验证的原始文本/ANSI
-
criteria(必需):验证标准。可以是:
- 预定义的标准名称(参见内置标准)
- 描述检查内容的自定义标准字符串
-
output_format(可选,默认值:"svg"):截图格式
svg- 矢量格式,最适合文档png- 光栅格式,最适合视觉差异比较text- 仅提取文本,速度最快
-
save_screenshot(可选,默认值:false):是否保存截图
- 如果为 true,则在当前目录中保存为
{target_name}.{format}
- 如果为 true,则在当前目录中保存为
-
judge_mode(可选,默认值:"semantic"):验证方式
semantic- LLM 根据含义和布局进行判断strict- 同时检查确切内容是否存在visual- 要求使用 PNG,并检查视觉效果
内置标准
ralph-header
验证 Ralph TUI 页眉组件:
- 迭代计数器,格式为
[iter N]或[iter N/M] MM:SS格式的已用时间- 带表情符号和名称的帽子指示器
- 模式指示器(
▶ auto或⏸ paused) - 可选的滚动模式指示器
[SCROLL] - 可选的空闲倒计时
idle: Ns
ralph-footer
验证 Ralph TUI 页脚组件:
- 活动指示器(
◉ active、◯ idle或■ done) - 最近事件主题显示
- 激活时显示搜索模式
ralph-full
验证完整的 Ralph TUI 布局:
- 顶部的页眉区域(3 行)
- 终端内容区域(高度可变)
- 底部的页脚区域(3 行)
- 适当的视觉层级和边框
tui-basic
通用 TUI 验证:
- 存在可见内容(非空白)
- 没有渲染瑕疵或乱码字符
- 终端尺寸适当
执行流程
1. 捕获阶段
根据目标类型捕获 TUI 输出:
对于文件目标:
freeze {file_path} -o /tmp/tui-capture.{format}
对于命令目标:
freeze --execute "{command}" -o /tmp/tui-capture.{format}
对于 tmux 目标:
tmux capture-pane -pet {session} | freeze -o /tmp/tui-capture.{format}
对于缓冲区目标:
echo "{buffer}" | freeze -o /tmp/tui-capture.{format}
约束:
- 在尝试捕获之前,必须确认已安装 freeze
- 必须妥善处理捕获失败并报告错误
- 必须根据输出格式使用合适的 freeze 标志
- 应使用
--theme base16以确保渲染一致 - 应使用
--width和--height设置合理的尺寸
2. 提取阶段
提取内容以供 LLM 分析:
对于文本/语义验证:
- 如果格式为
text,直接使用捕获的文本 - 如果格式为
svg或png,还要捕获文本版本以供内容分析
对于视觉验证:
- 必须使用 PNG 格式
- 将直接使用视觉能力分析图像
约束:
- 当 judge_mode 为
visual时,必须同时提取视觉和文本表示 - 相关情况下,必须保留 ANSI 转义序列以验证颜色
3. 验证阶段
使用 LLM-as-judge,并采用适当的标准:
语义验证提示词模板:
Analyze this terminal UI output and determine if it meets the following criteria:
CRITERIA:
{criteria_description}
TERMINAL OUTPUT:
{captured_text}
Evaluate each criterion and provide:
1. PASS or FAIL for each requirement
2. Brief explanation for any failures
3. Overall verdict: PASS or FAIL
Be lenient on exact formatting but strict on:
- Required content presence
- Logical layout and hierarchy
- No rendering errors or artifacts
视觉验证提示词模板(含图像):
Examine this terminal screenshot and validate:
CRITERIA:
{criteria_description}
Check for:
1. Visual hierarchy and layout
2. Color coding correctness
3. No rendering artifacts or broken characters
4. Proper alignment and spacing
Verdict: PASS or FAIL with explanation
约束:
- 必须给出明确的 PASS 或 FAIL 判定
- 失败时必须提供具体反馈
- 对空白字符/格式差异必须宽容
- 对内容是否齐全及语义是否正确必须严格
- 即使判定为 PASS,也应指出任何警告
4. 报告阶段
报告验证结果:
PASS 时:
✅ TUI Validation PASSED
Criteria: {criteria_name}
Target: {target}
Mode: {judge_mode}
All requirements satisfied.
{optional_notes}
FAIL 时:
❌ TUI Validation FAILED
Criteria: {criteria_name}
Target: {target}
Mode: {judge_mode}
Issues found:
- {issue_1}
- {issue_2}
Screenshot saved: {path_if_saved}
约束:
- 必须始终给出明确判定
- 失败时必须列出具体问题
- 如果已保存截图,必须提供截图路径
- 应针对常见问题提出修复建议
示例
示例 1:从文件验证 Ralph Header
输入:
/tui-validate file:test_output.txt criteria:ralph-header
流程:
- 读取包含 ANSI 输出的
test_output.txt - 使用 freeze 截图:
freeze test_output.txt -o /tmp/capture.svg - 提取文本内容
- 通过 LLM judge 应用
ralph-header标准 - 报告 PASS/FAIL 及详情
示例 2:在 tmux 中验证实时 TUI
输入:
/tui-validate tmux:ralph-session criteria:ralph-full save_screenshot:true
流程:
- 截取 tmux 窗格:
tmux capture-pane -pet ralph-session | freeze -o ralph-session.svg - 同时截取文本:
tmux capture-pane -pet ralph-session > /tmp/text.txt - 应用
ralph-full标准,检查标题、内容和页脚 - 将截图保存到
ralph-session.svg - 报告验证结果
示例 3:自定义标准验证
输入:
/tui-validate command:"cargo run --example tui_demo" criteria:"Shows a bordered box with 'Hello World' text centered inside" output_format:png judge_mode:visual
流程:
- 执行命令并截图:
freeze --execute "cargo run --example tui_demo" -o /tmp/capture.png - 使用视觉模型分析 PNG
- 检查是否存在带边框的框和居中文字
- 报告视觉验证结果
示例 4:快速文本验证
输入:
/tui-validate buffer:"[iter 3/10] 04:32 | 🔨 Builder | ▶ auto" criteria:ralph-header output_format:text
流程:
- 直接分析文本(使用缓冲区的文本模式无需 freeze)
- 检查迭代格式、已用时间、提示帽和模式指示器
- 报告验证结果
标准定义
ralph-header(完整定义)
name: ralph-header
description: Ralph TUI header component validation
requirements:
- name: iteration_counter
description: Shows iteration in [iter N] or [iter N/M] format
required: true
pattern: '\[iter \d+(/\d+)?\]'
- name: elapsed_time
description: Shows elapsed time in MM:SS format
required: true
pattern: '\d{2}:\d{2}'
- name: hat_indicator
description: Shows current hat with emoji prefix
required: true
examples: ["🔨 Builder", "📋 Planner", "🎯 Executor"]
- name: mode_indicator
description: Shows loop mode status
required: true
values: ["▶ auto", "⏸ paused"]
- name: scroll_indicator
description: Shows [SCROLL] when in scroll mode
required: false
pattern: '\[SCROLL\]'
- name: idle_countdown
description: Shows idle timeout when present
required: false
pattern: 'idle: \d+s'
ralph-footer(完整定义)
name: ralph-footer
description: Ralph TUI footer component validation
requirements:
- name: activity_indicator
description: Shows current activity state
required: true
values: ["◉ active", "◯ idle", "■ done"]
- name: event_topic
description: Shows last event topic
required: false
examples: ["task.start", "build.done", "loop.terminate"]
- name: search_display
description: Shows search query and match count when searching
required: false
pattern: 'Search: .+ \d+/\d+'
ralph-full(完整定义)
name: ralph-full
description: Complete Ralph TUI layout validation
requirements:
- name: header_section
description: Header at top with iteration, time, hat, and mode
required: true
references: ralph-header
- name: content_section
description: Main terminal content area
required: true
checks:
- Has visible content or is ready for content
- Properly bounded between header and footer
- name: footer_section
description: Footer at bottom with activity status
required: true
references: ralph-footer
- name: visual_hierarchy
description: Clear visual separation between sections
required: true
checks:
- Borders or spacing between sections
- Consistent width across sections
故障排除
找不到 freeze
# macOS
brew install charmbracelet/tap/freeze
# Linux (via Go)
go install github.com/charmbracelet/freeze@latest
# Verify installation
freeze --version
tmux 截取失败
- 确认 tmux 会话存在:
tmux list-sessions - 检查窗格编号:
tmux list-panes -t {session} - 尝试截取指定窗格:
tmux capture-pane -pet {session}:{pane}
截图中出现渲染异常
- 尝试在 freeze 中使用不同的终端模拟器设置
- 使用
--theme标志统一颜色 - 确保终端尺寸符合 TUI 的预期
LLM judge 过于严格/宽松
- 调整标准,使其更加具体
- 对精确匹配要求使用
strict模式 - 对布局/内容存在性检查使用
semantic模式
与测试集成
此技能可以集成到测试套件中:
// In tests/tui_validation.rs
#[test]
#[ignore] // Run with: cargo test -- --ignored
fn validate_header_rendering() {
// 1. Render header to buffer
let output = render_header_to_string(&test_state);
// 2. Save to temp file
std::fs::write("/tmp/header_test.txt", &output).unwrap();
// 3. Run tui-validate skill (via CLI or programmatic)
// /tui-validate file:/tmp/header_test.txt criteria:ralph-header
// 4. Assert validation passed
}
最佳实践
- 使用语义验证检查布局 - 不要因细微的格式差异而失败
- 使用严格验证检查内容要求 - 确保包含关键信息
- 失败时保存截图 - 有助于调试
- 使用不同的终端尺寸进行测试 - TUI 应具备响应能力
- 结合单元测试使用 - 使用此技能进行集成/视觉验证,使用单元测试检查逻辑
评论
支持 Markdown