TUI Validate
Overview
This skill validates Terminal User Interface (TUI) applications by capturing their output and using LLM-as-judge for semantic validation. It leverages freeze from Charmbracelet for high-fidelity terminal screenshots and provides structured validation criteria.
Philosophy: Rather than brittle string matching, this skill uses semantic understanding to validate that TUI output "looks right" - checking layout, content presence, and visual hierarchy without breaking on minor formatting changes.
When to Use
-
Validating TUI rendering after changes
-
Checking that UI components display correctly
-
Visual regression testing for terminal applications
-
Verifying TUI state after specific interactions
-
Creating documentation screenshots with validation
Prerequisites
Required:
-
freeze CLI tool installed (brew install charmbracelet/tap/freeze )
-
tmux for interactive TUI capture (optional, for live applications)
Verification:
Check freeze is installed
freeze --version
Check tmux is installed (for interactive capture)
tmux -V
Parameters
target (required): What to validate. One of:
-
file:<path>
-
ANSI output file to validate
-
command:<cmd>
-
Command to execute and capture
-
tmux:<session>
-
Live tmux session to capture
-
buffer:<text>
-
Raw text/ANSI to validate
criteria (required): Validation criteria. Can be:
-
A predefined criteria name (see Built-in Criteria)
-
A custom criteria string describing what to check
output_format (optional, default: "svg"): Screenshot format
-
svg
-
Vector format, best for documentation
-
png
-
Raster format, best for visual diff
-
text
-
Text-only extraction, fastest
save_screenshot (optional, default: false): Whether to save the screenshot
-
If true, saves to {target_name}.{format} in current directory
judge_mode (optional, default: "semantic"): Validation approach
-
semantic
-
LLM judges based on meaning and layout
-
strict
-
Also checks exact content presence
-
visual
-
Requires PNG, checks visual appearance
Built-in Criteria
ralph-header
Validates Ralph TUI header component:
-
Iteration counter in [iter N] or [iter N/M] format
-
Elapsed time in MM:SS format
-
Hat indicator with emoji and name
-
Mode indicator (▶ auto or ⏸ paused )
-
Optional scroll mode indicator [SCROLL]
-
Optional idle countdown idle: Ns
ralph-footer
Validates Ralph TUI footer component:
-
Activity indicator (◉ active , ◯ idle , or ■ done )
-
Last event topic display
-
Search mode display when active
ralph-full
Validates complete Ralph TUI layout:
-
Header section at top (3 lines)
-
Terminal content area (variable height)
-
Footer section at bottom (3 lines)
-
Proper visual hierarchy and borders
tui-basic
Generic TUI validation:
-
Has visible content (not blank)
-
No rendering artifacts or broken characters
-
Proper terminal dimensions
Execution Flow
- Capture Phase
Capture TUI output based on target type:
For file targets:
freeze {file_path} -o /tmp/tui-capture.{format}
For command targets:
freeze --execute "{command}" -o /tmp/tui-capture.{format}
For tmux targets:
tmux capture-pane -pet {session} | freeze -o /tmp/tui-capture.{format}
For buffer targets:
echo "{buffer}" | freeze -o /tmp/tui-capture.{format}
Constraints:
-
You MUST verify freeze is installed before attempting capture
-
You MUST handle capture failures gracefully and report the error
-
You MUST use appropriate freeze flags for the output format
-
You SHOULD use --theme base16 for consistent rendering
-
You SHOULD set reasonable dimensions with --width and --height
- Extraction Phase
Extract content for LLM analysis:
For text/semantic validation:
-
If format is text , use the captured text directly
-
If format is svg or png , also capture text version for content analysis
For visual validation:
-
Requires PNG format
-
Will analyze the image directly using vision capabilities
Constraints:
-
You MUST extract both visual and text representations when judge_mode is visual
-
You MUST preserve ANSI escape sequences for color validation when relevant
- Validation Phase
Apply LLM-as-judge with the appropriate criteria:
Semantic Validation Prompt Template:
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:
- PASS or FAIL for each requirement
- Brief explanation for any failures
- 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
Visual Validation Prompt Template (with image):
Examine this terminal screenshot and validate:
CRITERIA: {criteria_description}
Check for:
- Visual hierarchy and layout
- Color coding correctness
- No rendering artifacts or broken characters
- Proper alignment and spacing
Verdict: PASS or FAIL with explanation
Constraints:
-
You MUST return a clear PASS or FAIL verdict
-
You MUST provide specific feedback on failures
-
You MUST be lenient on whitespace/formatting differences
-
You MUST be strict on content presence and semantic correctness
-
You SHOULD note any warnings even on PASS results
- Reporting Phase
Report validation results:
On PASS:
✅ TUI Validation PASSED
Criteria: {criteria_name} Target: {target} Mode: {judge_mode}
All requirements satisfied. {optional_notes}
On FAIL:
❌ TUI Validation FAILED
Criteria: {criteria_name} Target: {target} Mode: {judge_mode}
Issues found:
- {issue_1}
- {issue_2}
Screenshot saved: {path_if_saved}
Constraints:
-
You MUST always provide a clear verdict
-
You MUST list specific issues on failure
-
You MUST offer the screenshot path if saved
-
You SHOULD suggest fixes for common issues
Examples
Example 1: Validate Ralph Header from File
Input:
/tui-validate file:test_output.txt criteria:ralph-header
Process:
-
Read test_output.txt containing ANSI output
-
Capture with freeze: freeze test_output.txt -o /tmp/capture.svg
-
Extract text content
-
Apply ralph-header criteria via LLM judge
-
Report PASS/FAIL with details
Example 2: Validate Live TUI in tmux
Input:
/tui-validate tmux:ralph-session criteria:ralph-full save_screenshot:true
Process:
-
Capture tmux pane: tmux capture-pane -pet ralph-session | freeze -o ralph-session.svg
-
Also capture text: tmux capture-pane -pet ralph-session > /tmp/text.txt
-
Apply ralph-full criteria checking header, content, and footer
-
Save screenshot to ralph-session.svg
-
Report validation result
Example 3: Custom Criteria Validation
Input:
/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
Process:
-
Execute command and capture: freeze --execute "cargo run --example tui_demo" -o /tmp/capture.png
-
Use vision model to analyze PNG
-
Check for bordered box and centered text
-
Report visual validation result
Example 4: Quick Text Validation
Input:
/tui-validate buffer:"[iter 3/10] 04:32 | 🔨 Builder | ▶ auto" criteria:ralph-header output_format:text
Process:
-
Analyze text directly (no freeze needed for text mode with buffer)
-
Check for iteration format, elapsed time, hat, and mode indicator
-
Report validation result
Criteria Definitions
ralph-header (Full Definition)
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 (Full Definition)
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 (Full Definition)
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
Troubleshooting
freeze not found
macOS
brew install charmbracelet/tap/freeze
Linux (via Go)
go install github.com/charmbracelet/freeze@latest
Verify installation
freeze --version
tmux capture fails
-
Ensure the tmux session exists: tmux list-sessions
-
Verify pane number: tmux list-panes -t {session}
-
Try capturing specific pane: tmux capture-pane -pet {session}:{pane}
Rendering artifacts in capture
-
Try different terminal emulator settings in freeze
-
Use --theme flag for consistent colors
-
Ensure terminal dimensions match TUI expectations
LLM judge too strict/lenient
-
Adjust criteria to be more specific
-
Use strict mode for exact matching requirements
-
Use semantic mode for layout/presence checking
Integration with Tests
This skill can be integrated into test suites:
// 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
}
Best Practices
-
Use semantic validation for layout checks - Don't break on minor formatting
-
Use strict validation for content requirements - Ensure critical info is present
-
Save screenshots on failure - Aids debugging
-
Test with various terminal sizes - TUIs should be responsive
-
Combine with unit tests - Use this for integration/visual validation, unit tests for logic