Roxid
A Terminal User Interface (TUI) application built with Ratatui for managing and executing YAML-based pipelines.
Table of Contents
- Features
- Quick Start
- Installation
- Usage
- Architecture
- Pipeline System
- TUI Guide
- Extending the Application
- Project Structure
- Resources
Features
TUI Features
- Pipeline Discovery: Automatically discovers pipeline YAML files in the current directory
- Interactive Selection: Navigate through available pipelines with keyboard controls
- Real-time Execution: Execute pipelines with live progress tracking
- Progress Visualization: Visual progress bar showing current step
- Live Output: Real-time output display during pipeline execution
- Error Handling: Uses color-eyre for better error reporting
- Cross-platform: Works on Linux, macOS, and Windows
Pipeline Features
- YAML-based pipeline definitions: Simple, declarative syntax
- Command and shell script execution: Run single commands or multi-line scripts
- Environment variable support: Pipeline-level and step-level env vars
- Real-time progress reporting: Live updates via async channels
- Error handling: Continue on error support for non-critical steps
Quick Start
1. Build the Project
2. Run the TUI
3. Navigate and Execute
- Use ↑ and ↓ arrow keys (or k/j) to select a pipeline
- Press Enter to execute the selected pipeline
- Watch the progress bar and live output
- Press q or Esc to return to the list after completion
Installation
Option 1: From crates.io (Recommended)
Option 2: Pre-built Binary
Download from Releases:
- Linux x86_64:
roxid-linux-x86_64.tar.gz - macOS Intel:
roxid-macos-x86_64.tar.gz - macOS Apple Silicon:
roxid-macos-aarch64.tar.gz - Windows:
roxid-windows-x86_64.exe.zip
Linux/macOS:
Windows: Extract ZIP and add to PATH.
Option 3: From Git
Option 4: Build from Source
Verify
Uninstall
# If installed via cargo:
# If installed manually:
Usage
Interactive TUI
Run the TUI application to browse and execute pipelines:
The TUI will discover all .yaml and .yml files in the current directory and display them as available pipelines.
Keyboard Controls
Pipeline List Screen:
↑ork- Move selection up↓orj- Move selection downEnter- Execute selected pipelineqorEsc- Quit application
Pipeline Execution Screen:
qorEsc- Return to pipeline list (only after completion)
Pipeline Execution
You can also execute pipelines directly via CLI:
# Run example pipeline
# Run Rust build pipeline
Architecture
Workspace Structure
This workspace follows a typical Rust project structure with separation of concerns:
roxid/
├── Cargo.toml # Workspace manifest
├── roxid-tui/ # Terminal UI application (binary)
│ ├── Cargo.toml
│ └── src/
│ ├── main.rs # Entry point
│ ├── app.rs # Application state and logic
│ ├── events.rs # Event handling (keyboard, mouse)
│ └── ui/ # UI rendering modules
│ ├── mod.rs
│ ├── components.rs # Reusable UI components
│ └── layout.rs # Layout definitions
├── pipeline-service/ # Business logic layer (library)
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs # Library entry point
│ ├── error.rs # Error types
│ ├── models/ # Data models
│ ├── pipeline/ # Pipeline execution system
│ └── services/ # Business logic
├── pipeline-rpc/ # RPC API layer (library)
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs # Library entry point
│ ├── api.rs # RPC server setup
│ └── handlers/ # RPC request handlers
└── roxid-cli/ # CLI application (binary)
├── Cargo.toml
└── src/
└── main.rs # CLI entry point
Architecture Layers
1. Service Package (pipeline-service/)
- Purpose: Core business logic
- Type: Library crate
- Dependencies: None (pure business logic)
- Structure:
models/: Data structures and domain modelspipeline/: Pipeline execution systemservices/: Business logic implementationserror.rs: Domain-specific error types
2. RPC Package (pipeline-rpc/)
- Purpose: Remote procedure call API layer
- Type: Library crate
- Dependencies: Depends on
pipeline-service - Structure:
api.rs: RPC server setuphandlers/: Request handlers that call service layer (PipelineHandler, UserHandler)error.rs: RPC-specific error handling
- Responsibilities: Provides the API interface that clients use to interact with the service layer
3. TUI Package (roxid-tui/)
- Purpose: Terminal user interface
- Type: Binary crate (executable)
- Dependencies: Depends only on
pipeline-rpc - Structure:
main.rs: Application entry pointapp.rs: Application state managementevents.rs: User input handlingui/: All rendering logic separated by concern
4. CLI Package (roxid-cli/)
- Purpose: Command-line interface
- Type: Binary crate (executable)
- Dependencies: Depends only on
pipeline-rpc - Structure:
main.rs: CLI entry point with command parsing
Dependency Direction
roxid-tui → pipeline-rpc → pipeline-service
roxid-cli → pipeline-rpc → pipeline-service
Key Architectural Principle: Both client applications (TUI and CLI) communicate with the service layer exclusively through the RPC API. This ensures:
- Clean separation between presentation and business logic
- Consistent API interface for all clients
- Easy addition of new clients (web, mobile, etc.) without modifying service code
- Centralized API logic in the RPC layer
TUI Application Flow
-
Pipeline List State:
- Discovers and displays available pipeline YAML files
- User navigates with arrow keys and selects with Enter
-
Pipeline Execution State:
- Executes selected pipeline asynchronously via RPC handler
- Displays real-time progress bar (current step / total steps)
- Streams output to the terminal as it's generated
- Shows completion status (success/failure)
-
Event Loop: The main loop continuously:
- Draws the UI based on current state
- Handles keyboard events with non-blocking polling
- Updates state based on execution events
-
RPC Communication:
- TUI uses
PipelineHandlerfrom pipeline-rpc to interact with pipelines - All service operations go through the RPC layer
- Uses async channels for progress updates and output streaming
- No direct dependency on pipeline-service
- TUI uses
State Machine
┌─────────────────┐
│ PipelineList │
│ - Discover YAML │
│ - Navigate │
│ - Select │
└────────┬────────┘
│ Enter
▼
┌─────────────────┐
│ ExecutingPipe │
│ - Run pipeline │
│ - Show progress │
│ - Stream output │
└────────┬────────┘
│ Complete
▼
┌─────────────────┐
│ PipelineList │
│ (return) │
└─────────────────┘
Components
- App State Machine: Manages transitions between PipelineList and ExecutingPipeline states
- Event Handler: Non-blocking event processing with state-aware key bindings
- UI Rendering: Modular components for pipeline list, progress bar, and output display
- Pipeline Executor: Async execution with progress events streamed via channels
Pipeline System
Pipeline YAML Format
name: my-pipeline
description: Optional description
env:
GLOBAL_VAR: value
steps:
- name: Step name
command: echo "Hello World"
- name: Multi-line script
shell:
script: |
echo "Line 1"
echo "Line 2"
env:
STEP_VAR: value
continue_on_error: true
Creating a Pipeline
Create a file ending in .yaml or .yml:
name: my-first-pipeline
description: My first custom pipeline
steps:
- name: Hello World
command: echo "Hello from my pipeline!"
- name: Show Date
command: date
- name: List Files
command: ls -la
Basic Usage Example
use ;
use Result;
async
With Progress Reporting
use ;
// Create event channel
let = create_event_channel;
// Create handler and parse pipeline
let handler = new;
let pipeline = handler.parse_from_file?;
let working_dir = current_dir?.to_string_lossy.to_string;
// Spawn executor
let handle = spawn;
// Monitor progress
while let Some = rx.recv.await
let result = handle.await?;
Example Pipelines
Simple Test Pipeline
name: quick-test
steps:
- name: Check version
command: rustc --version
- name: Run tests
command: cargo test
Build Pipeline
name: build-pipeline
env:
RUST_BACKTRACE: "1"
steps:
- name: Format check
command: cargo fmt --check
continue_on_error: true
- name: Build
command: cargo build --all
- name: Test
command: cargo test --all
Pipeline Architecture
The pipeline system consists of:
- Parser (
pipeline/parser.rs) - Parses YAML into Rust structs - Executor (
pipeline/executor.rs) - Orchestrates step execution - Runners (
pipeline/runners/) - Execute different step typesshell.rs- Runs shell commands and scripts
- Models (
pipeline/models.rs) - Data structures for pipelines, steps, results
TUI Guide
Interface Overview
Pipeline List Screen
┌─────────────────────────────────────────────┐
│ Pipeline Runner │
└─────────────────────────────────────────────┘
┌─ Available Pipelines ──────────────────────┐
│ → example-pipeline - A simple example │
│ rust-build-pipeline - Build Rust project│
│ advanced-pipeline - Complex workflow │
└─────────────────────────────────────────────┘
┌─ Help ──────────────────────────────────────┐
│ ↑/↓: Navigate | Enter: Execute | q: Quit │
└─────────────────────────────────────────────┘
Pipeline Execution Screen
┌─────────────────────────────────────────────┐
│ Executing: example-pipeline │
└─────────────────────────────────────────────┘
┌─ Progress ──────────────────────────────────┐
│ ████████████░░░░░░░░ Step 3/5 │
└─────────────────────────────────────────────┘
┌─ Output ────────────────────────────────────┐
│ [Step 1/5] Check Rust version │
│ rustc 1.70.0 (90c541806 2023-05-31) │
│ ✓ Completed in 0.05s │
│ │
│ [Step 2/5] List files │
│ ✓ Completed in 0.02s │
│ │
│ [Step 3/5] Multi-line script │
│ Starting multi-line script │
└─────────────────────────────────────────────┘
Features:
- Real-time progress bar showing current step
- Live output streaming as commands execute
- Color-coded status indicators:
- ✓ Green for successful steps
- ✗ Red for failed steps
- Yellow for step headers
- Auto-scrolling output (shows most recent lines)
- Execution time per step
Execution Flow
- Select Pipeline: Use arrow keys to highlight a pipeline
- Start Execution: Press Enter to begin execution
- Watch Progress: View real-time progress and output
- Completion: Pipeline shows success or failure status
- Return to List: Press q or Esc to select another pipeline
Troubleshooting
No Pipelines Found
- Ensure you're in a directory with
.yamlor.ymlfiles - Check that files are valid pipeline YAML format
- Verify files have the required
nameandstepsfields
Pipeline Fails to Execute
- Check the output panel for error messages
- Verify commands are available on your system
- Check file permissions and working directory
- Review pipeline YAML syntax
TUI Doesn't Respond
- Ensure terminal supports TUI applications
- Check terminal size is adequate (minimum 80x24)
- Try resizing terminal window
Extending the Application
Adding a New Tab System
// Add to App struct:
// Handle tab switching:
Char => self.current_tab = Counter,
Char => self.current_tab = Items,
Char => self.current_tab = Settings,
Adding Scrolling to Lists
use ListState;
// Handle scrolling:
Up =>
Down =>
// Render with state:
frame.render_stateful_widget;
Adding Input Fields
// Handle input mode:
Char if !self.input_mode =>
Esc if self.input_mode =>
Char if self.input_mode =>
Backspace if self.input_mode =>
Enter if self.input_mode =>
Adding Mouse Support
use ;
// In handle_events:
Mouse => self.handle_mouse_event,
// Handler:
Adding Async Operations
// Add to Cargo.toml:
// tokio = { version = "1", features = ["full"] }
use mpsc;
use Duration;
async
Custom Pipeline Steps
To extend the pipeline system:
- Add new pipeline steps: Update pipeline YAML files with new commands or shell scripts
- Custom step runners: Implement new runners in
pipeline-service/src/pipeline/runners/ - RPC handlers: Add new RPC handlers in
pipeline-rpc/src/handlers/to expose new functionality - Update RPC API: Export new handlers and types in
pipeline-rpc/src/lib.rs - Client updates: Use new RPC handlers in CLI/TUI applications
- UI screens: Create new app states and corresponding UI components in TUI
- Pipeline filters: Add filtering/searching capabilities to the pipeline list
Remember: All client functionality must go through the RPC layer. Never import pipeline-service directly in CLI or TUI.
Best Practices
- Keep render functions pure - Don't modify state during rendering
- Handle errors gracefully - Use Result types and proper error handling
- Test rendering logic - Ratatui supports testing with Buffer
- Profile performance - TUI apps should render at 60fps
- Use proper terminal cleanup - Always restore terminal state on exit
Project Structure
Building and Running
# Build entire workspace
# Build specific package
# Run the TUI application
# Run the CLI application
# Run tests for all packages
# Run tests for specific package
# Check code without building
Benefits of This Structure
- Separation of Concerns: Each package has a single responsibility
- Reusability: Service logic can be used by multiple clients through RPC layer
- Testability: Each layer can be tested independently
- Maintainability: Clear boundaries make code easier to understand
- Scalability: Easy to add new interfaces (web, mobile, desktop) without touching core logic
- API Consistency: All clients use the same RPC interface, ensuring consistent behavior
- Security: RPC layer can add authentication, rate limiting, and validation before reaching service
- Flexibility: RPC layer can be made into a network service without changing clients
Resources
- Ratatui Documentation
- Ratatui Website
- Ratatui Examples
- Ratatui Book
- Crossterm Documentation
- Example Projects
License
This skeleton application is provided as-is for educational and development purposes.