Ralph-orchestrator tui-validate
Validates Terminal User Interface (TUI) output using freeze for screenshot capture and LLM-as-judge for semantic validation. Supports both visual (PNG/SVG) and text-based validation modes.
git clone https://github.com/mikeyobrien/ralph-orchestrator
T=$(mktemp -d) && git clone --depth=1 https://github.com/mikeyobrien/ralph-orchestrator "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/tui-validate" ~/.claude/skills/mikeyobrien-ralph-orchestrator-tui-validate && rm -rf "$T"
.claude/skills/tui-validate/SKILL.mdTUI 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:
CLI tool installed (freeze
)brew install charmbracelet/tap/freeze
for interactive TUI capture (optional, for live applications)tmux
Verification:
# Check freeze is installed freeze --version # Check tmux is installed (for interactive capture) tmux -V
Parameters
-
target (required): What to validate. One of:
- ANSI output file to validatefile:<path>
- Command to execute and capturecommand:<cmd>
- Live tmux session to capturetmux:<session>
- Raw text/ANSI to validatebuffer:<text>
-
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
- Vector format, best for documentationsvg
- Raster format, best for visual diffpng
- Text-only extraction, fastesttext
-
save_screenshot (optional, default: false): Whether to save the screenshot
- If true, saves to
in current directory{target_name}.{format}
- If true, saves to
-
judge_mode (optional, default: "semantic"): Validation approach
- LLM judges based on meaning and layoutsemantic
- Also checks exact content presencestrict
- Requires PNG, checks visual appearancevisual
Built-in Criteria
ralph-header
ralph-headerValidates Ralph TUI header component:
- Iteration counter in
or[iter N]
format[iter N/M] - Elapsed time in
formatMM:SS - Hat indicator with emoji and name
- Mode indicator (
or▶ auto
)⏸ paused - Optional scroll mode indicator
[SCROLL] - Optional idle countdown
idle: Ns
ralph-footer
ralph-footerValidates Ralph TUI footer component:
- Activity indicator (
,◉ active
, or◯ idle
)■ done - Last event topic display
- Search mode display when active
ralph-full
ralph-fullValidates 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
tui-basicGeneric TUI validation:
- Has visible content (not blank)
- No rendering artifacts or broken characters
- Proper terminal dimensions
Execution Flow
1. 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
for consistent rendering--theme base16 - You SHOULD set reasonable dimensions with
and--width--height
2. Extraction Phase
Extract content for LLM analysis:
For text/semantic validation:
- If format is
, use the captured text directlytext - If format is
orsvg
, also capture text version for content analysispng
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
3. 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: 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
Visual Validation Prompt Template (with image):
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
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
4. 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
containing ANSI outputtest_output.txt - Capture with freeze:
freeze test_output.txt -o /tmp/capture.svg - Extract text content
- Apply
criteria via LLM judgeralph-header - 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
criteria checking header, content, and footerralph-full - 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
flag for consistent colors--theme - Ensure terminal dimensions match TUI expectations
LLM judge too strict/lenient
- Adjust criteria to be more specific
- Use
mode for exact matching requirementsstrict - Use
mode for layout/presence checkingsemantic
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