
---
title: Terminal Rendering System
description: Complete terminal rendering architecture with message formatting, status display, and visual effects
category: core-systems
status: review
last_updated: 2025-01-15
version: 1.0.0
tags:
  - level: advanced
  - component: rendering
  - status: stable
related:
  - ../architecture/system-architecture.md
  - ../reference/buffer-transition-and-render-state.md
  - ./input-handling.md
---

# Terminal Rendering System

## Overview

The Terminal Rendering System manages all visual output for the Kollabor CLI application, coordinating message display, status bar rendering, visual effects, and terminal state management. It provides a unified rendering framework with caching, dirty region tracking, and optimized terminal I/O.

## Purpose

This document explains:
- TerminalRenderer architecture and responsibilities
- Message formatting and display flow
- Status bar management and layout
- Visual effects system (gradients, shimmer, colors)
- Render caching and dirty region optimization
- Terminal state management

## Scope

**Covered**:
- TerminalRenderer main component
- MessageRenderer (formatting, symbols, colors)
- MessageCoordinator (atomic message sequencing)
- StatusRenderer (status bar management)
- LayoutManager (terminal layout calculations)
- VisualEffects (gradients, shimmer, effects)
- TerminalState (terminal state management)

**Not Covered**:
- Modal rendering system (see: [Modal System](../reference/modal-system-guide.md))
- Input rendering (see: [Input Handling](./input-handling.md))
- Fullscreen plugins (see: [Fullscreen Plugin System](../reference/fullscreen-plugin-system.md))

## Prerequisites

- Understanding of terminal control sequences (ANSI escape codes)
- Familiarity with event system (see: [Event System Architecture](../architecture/event-system.md))
- Knowledge of raw terminal mode vs. cooked mode

## Table of Contents

- [Architecture Overview](#architecture-overview)
- [TerminalRenderer](#terminalrenderer)
- [MessageRenderer](#messagerenderer)
- [MessageCoordinator](#messagecoordinator)
- [StatusRenderer](#statusrenderer)
- [LayoutManager](#layoutmanager)
- [VisualEffects](#visualeffects)
- [TerminalState](#terminalstate)
- [Render Flow](#render-flow)
- [Caching Strategy](#caching-strategy)
- [Examples](#examples)
- [Troubleshooting](#troubleshooting)
- [Related Documents](#related-documents)
- [References](#references)

---

## Architecture Overview

```mermaid
graph TB
    subgraph "Rendering System Components"
        TR[TerminalRenderer]
        MR[MessageRenderer]
        MC[MessageCoordinator]
        SR[StatusRenderer]
        LM[LayoutManager]
        VE[VisualEffects]
        TS[TerminalState]
    end
    
    subgraph "Rendering Process"
        E1[Event: INPUT_RENDER]
        E2[Event: STATUS_VIEW_CHANGED]
        E3[Render Frame Trigger]
    end
    
    subgraph "Output"
        T[Terminal Display]
        S[Status Bar]
        M[Message Area]
    end
    
    E1 --> TR
    E2 --> SR
    E3 --> TR
    
    TR --> LM
    TR --> MR
    TR --> VE
    TR --> TS
    
    MC --> MR
    
    TR --> T
    MR --> M
    SR --> S
```

**Component Responsibilities**:

| Component | File | Responsibilities |
|-----------|-------|-----------------|
| TerminalRenderer | `kollabor/io/terminal_renderer.py` | Main rendering coordinator, render loop, caching |
| MessageRenderer | `kollabor/io/message_renderer.py` | Message formatting, symbols, colors, gradients |
| MessageCoordinator | `kollabor/io/message_coordinator.py` | Atomic message sequencing, display coordination |
| StatusRenderer | `kollabor/io/status_renderer.py` | Status bar management, view switching |
| LayoutManager | `kollabor/io/layout.py` | Terminal layout calculations, area sizing |
| VisualEffects | `kollabor/io/visual_effects.py` | Gradients, shimmer, color management |
| TerminalState | `kollabor/io/terminal_state.py` | Terminal state management, mode switching |

---

## TerminalRenderer

**File**: `kollabor/io/terminal_renderer.py`

The main rendering coordinator that manages the render loop, caching, and coordinates between all rendering components.

### Key Responsibilities

```python
class TerminalRenderer:
    """Main rendering coordinator."""
    
    def __init__(self, config: ConfigManager):
        """Initialize renderer with configuration."""
        self.config = config
        self.render_cache = {}           # Render cache for optimization
        self.dirty_regions = set()        # Tracks regions needing redraw
        self.last_frame_time = 0
        self.target_fps = config.get('terminal.render_fps', 20)
        self.resize_debounce_timer = None
        
        # Initialize sub-components
        self.message_renderer = MessageRenderer(config)
        self.status_renderer = StatusRenderer(config)
        self.layout_manager = LayoutManager(config)
        self.visual_effects = VisualEffects(config)
        self.terminal_state = TerminalState()
```

### Render Loop

```mermaid
sequenceDiagram
    participant Loop as Render Loop
    participant TR as TerminalRenderer
    participant Cache as Render Cache
    participant MR as MessageRenderer
    participant SR as StatusRenderer
    participant T as Terminal
    
    Loop->>TR: Render Frame Trigger
    TR->>Cache: Check dirty regions
    alt Dirty regions exist
        TR->>MR: Render messages
        MR->>TR: Formatted lines
        TR->>SR: Render status
        SR->>TR: Status lines
        TR->>T: Write to terminal
        TR->>Cache: Update cache
    else
        TR->>TR: Skip frame (cached)
    end
    TR->>TR: Schedule next frame
```

### Render Caching

```python
async def render_frame(self, force_render: bool = False) -> None:
    """Render a single frame with caching."""
    current_time = time.time()
    
    # Skip if not enough time elapsed
    if not force_render:
        elapsed = current_time - self.last_frame_time
        if elapsed < 1.0 / self.target_fps:
            return  # Skip frame
    
    # Check if anything needs rendering
    if not self.dirty_regions and not force_render:
        return  # Nothing to do
    
    # Clear and render
    self._clear_active_area()
    
    # Render components
    self._render_messages()
    self._render_status()
    self._render_input()
    
    # Update cache and timing
    self.dirty_regions.clear()
    self.last_frame_time = current_time
```

### Resize Handling

```python
def handle_resize(self, width: int, height: int) -> None:
    """Handle terminal resize with debouncing."""
    # Clear debounce timer if exists
    if self.resize_debounce_timer:
        self.resize_debounce_timer.cancel()
    
    # Schedule new resize handling
    self.resize_debounce_timer = asyncio.create_task(
        self._debounced_resize(width, height)
    )

async def _debounced_resize(self, width: int, height: int) -> None:
    """Handle resize after debounce period."""
    await asyncio.sleep(0.9)  # 900ms debounce
    
    # Check if terminal width reduced significantly
    old_width = self.layout_manager.terminal_width
    if width < old_width * 0.9:
        # Aggressive clearing on width reduction
        self._aggressive_clear()
    
    # Update layout
    self.layout_manager.update_dimensions(width, height)
    self.dirty_regions.add('layout')  # Mark layout dirty
```

---

## MessageRenderer

**File**: `kollabor/io/message_renderer.py`

Handles message formatting, symbols, colors, and gradient effects for displayed messages.

### Message Formatting

```python
class MessageRenderer:
    """Handles message formatting and display."""
    
    MESSAGE_SYMBOLS = {
        MessageType.USER: ">",       # User message symbol
        MessageType.ASSISTANT: "∴",  # Assistant message symbol
        MessageType.SYSTEM: "⏺",     # System/tool symbol
        MessageType.ERROR: "⚠",      # Error message symbol
        MessageType.DEBUG: "○"        # Debug message symbol
    }
    
    def format_message(
        self,
        content: str,
        message_type: MessageType,
        format_style: FormatStyle = FormatStyle.STANDARD
    ) -> List[str]:
        """Format message for display.
        
        Args:
            content: Message content to format
            message_type: Type of message (user, assistant, etc.)
            format_style: Formatting style (standard, dimmed, highlighted)
            
        Returns:
            List of formatted lines ready for display
        """
        # Get symbol
        symbol = self.MESSAGE_SYMBOLS.get(message_type, "")
        
        # Get colors
        if format_style == FormatStyle.GRADIENT:
            colors = self.visual_effects.get_gradient_color(
                GradientType.MESSAGE
            )
        else:
            colors = self._get_colors_for_type(message_type, format_style)
        
        # Format lines
        lines = content.split('\n')
        formatted_lines = []
        
        for i, line in enumerate(lines):
            if i == 0:
                # First line with symbol
                formatted_line = f"{symbol} {line}"
            else:
                # Continuation lines
                formatted_line = f"  {line}"
            
            # Apply colors
            colored_line = self._apply_colors(formatted_line, colors)
            formatted_lines.append(colored_line)
        
        return formatted_lines
```

### Color Application

```python
def _apply_colors(self, text: str, colors: Dict[str, str]) -> str:
    """Apply ANSI color codes to text.
    
    Args:
        text: Text to color
        colors: Dict with 'fg', 'bg', 'style' keys
        
    Returns:
        Colorized text with ANSI codes
    """
    fg = colors.get('fg', '')
    bg = colors.get('bg', '')
    style = colors.get('style', '')
    
    # Build ANSI sequence
    codes = []
    if style == 'dimmed':
        codes.append('2')
    if style == 'highlighted':
        codes.append('1')
    if fg:
        codes.append(f'38;5;{fg}')
    if bg:
        codes.append(f'48;5;{bg}')
    
    if codes:
        sequence = '\033[' + ';'.join(codes) + 'm'
        return f'{sequence}{text}\033[0m'
    else:
        return text
```

### Gradient Effects

```python
def apply_gradient_text(
    self,
    text: str,
    gradient_type: GradientType
) -> str:
    """Apply gradient color to text.
    
    Args:
        text: Text to gradient
        gradient_type: Type of gradient (message, header, etc.)
        
    Returns:
        Text with gradient color applied
    """
    colors = self.visual_effects.get_gradient_color(gradient_type)
    
    # For simple text, use start color
    return self._apply_colors(text, {'fg': colors['start'], 'style': 'bold'})
```

---

## MessageCoordinator

**File**: `kollabor/io/message_coordinator.py`

Coordinates atomic message display, ensuring messages appear as complete units without partial rendering.

### Message Sequencing

```python
class MessageCoordinator:
    """Coordinates atomic message display."""
    
    def __init__(self, renderer: TerminalRenderer):
        self.renderer = renderer
        self.message_queue = []
        self.writing_messages = False
        self.display_lock = asyncio.Lock()
    
    async def display_message_sequence(
        self,
        messages: List[Tuple[str, str, Dict]]
    ) -> None:
        """Display sequence of messages atomically.
        
        Args:
            messages: List of (type, content, kwargs) tuples
                     type: 'user', 'assistant', 'system', 'error'
                     content: Message content
                     kwargs: Additional metadata
        """
        async with self.display_lock:
            # Queue all messages
            for msg_type, content, kwargs in messages:
                self.queue_message(msg_type, content, kwargs)
            
            # Display all at once
            await self.display_queued_messages()
```

### Atomic Display

```python
async def display_queued_messages(self) -> None:
    """Display all queued messages atomically."""
    if not self.message_queue:
        return
    
    self.writing_messages = True
    
    try:
        # Clear active area for new messages
        self.renderer.clear_active_area()
        
        # Display each message
        for msg_type, content, kwargs in self.message_queue:
            await self._display_single_message(msg_type, content, kwargs)
        
        # Reset render state
        self.renderer.reset_render_state()
        
    finally:
        self.writing_messages = False
        self.message_queue.clear()

async def _display_single_message(
    self,
    message_type: str,
    content: str,
    kwargs: Dict
) -> None:
    """Display a single message.
    
    Args:
        message_type: Type of message
        content: Message content
        kwargs: Additional metadata (format_style, etc.)
    """
    # Map type to MessageType enum
    msg_type_enum = MessageType(message_type.lower())
    
    # Get format style
    format_style = kwargs.get(
        'format_style',
        FormatStyle.STANDARD
    )
    
    # Format message
    formatted_lines = self.renderer.message_renderer.format_message(
        content=content,
        message_type=msg_type_enum,
        format_style=format_style
    )
    
    # Display immediately
    self._display_message_immediately(
        '\n'.join(formatted_lines),
        msg_type_enum,
        format_style
    )
```

---

## StatusRenderer

**File**: `kollabor/io/status_renderer.py`

Manages status bar display, view switching, and status content updates.

### Status Areas

```python
class StatusRenderer:
    """Manages status bar rendering."""
    
    # Status bar has 3 areas:
    # [A] Core System      [B] Plugin Metrics    [C] Detailed Info
    
    STATUS_AREAS = {
        'A': (0, 0.3),      # Left 30%
        'B': (0.3, 0.7),     # Middle 40%
        'C': (0.7, 1.0)      # Right 30%
    }
    
    def __init__(self, config: ConfigManager):
        self.config = config
        self.active_view = "default"
        self.status_views = {}  # View registry
        self.register_core_views()
    
    def register_core_views(self) -> None:
        """Register core status views."""
        self.register_status_view(
            "default",
            DefaultStatusView(self.config)
        )
        self.register_status_view(
            "config",
            ConfigStatusView(self.config)
        )
```

### Status Line Rendering

```python
def render_status_bar(self, terminal_width: int) -> List[str]:
    """Render complete status bar.
    
    Args:
        terminal_width: Width of terminal
        
    Returns:
        List of status lines
    """
    active_view = self.status_views.get(self.active_view)
    if not active_view:
        return []
    
    # Get status lines for each area
    area_a = active_view.get_area_lines('A')
    area_b = active_view.get_area_lines('B')
    area_c = active_view.get_area_lines('C')
    
    # Calculate area widths
    width_a = int(terminal_width * 0.3)
    width_b = int(terminal_width * 0.4)
    width_c = terminal_width - width_a - width_b
    
    # Build status lines
    status_lines = []
    
    # Combine areas
    for i in range(max(len(area_a), len(area_b), len(area_c))):
        line_a = area_a[i] if i < len(area_a) else ""
        line_b = area_b[i] if i < len(area_b) else ""
        line_c = area_c[i] if i < len(area_c) else ""
        
        # Pad to area widths
        line_a = line_a.ljust(width_a)
        line_b = line_b.ljust(width_b)
        line_c = line_c.ljust(width_c)
        
        # Combine with separators
        status_line = f"{line_a}│{line_b}│{line_c}"
        status_lines.append(status_line)
    
    return status_lines
```

### View Switching

```python
async def switch_view(self, view_name: str) -> None:
    """Switch to different status view.
    
    Args:
        view_name: Name of view to switch to
    """
    if view_name not in self.status_views:
        logger.warning(f"Status view not found: {view_name}")
        return
    
    old_view = self.active_view
    self.active_view = view_name
    
    # Emit event for plugins
    await self.event_bus.emit_with_hooks(
        EventType.STATUS_VIEW_CHANGED,
        {
            'view_name': view_name,
            'previous_view': old_view
        },
        source="status_renderer"
    )
```

---

## LayoutManager

**File**: `kollabor/io/layout.py`

Calculates terminal layout, sizing for message area, status bar, and input box.

### Layout Calculations

```python
class LayoutManager:
    """Manages terminal layout calculations."""
    
    def __init__(self, config: ConfigManager):
        self.config = config
        self.terminal_width = 80
        self.terminal_height = 24
        
        # Layout configuration
        self.status_lines = config.get('terminal.status_lines', 3)
        self.input_lines = 3
        self.margin = 2
    
    def calculate_layout(self) -> Dict[str, Any]:
        """Calculate layout for all areas.
        
        Returns:
            Dict with layout info for each area
        """
        total_height = self.terminal_height
        
        # Calculate area heights
        status_height = self.status_lines
        input_height = self.input_lines
        message_height = total_height - status_height - input_height - self.margin
        
        return {
            'terminal': {
                'width': self.terminal_width,
                'height': self.terminal_height
            },
            'status': {
                'row': 0,
                'col': 0,
                'width': self.terminal_width,
                'height': status_height
            },
            'message': {
                'row': status_height + 1,
                'col': 0,
                'width': self.terminal_width,
                'height': message_height
            },
            'input': {
                'row': total_height - input_height - 1,
                'col': 0,
                'width': self.terminal_width,
                'height': input_height
            }
        }
    
    def update_dimensions(self, width: int, height: int) -> None:
        """Update terminal dimensions.
        
        Args:
            width: New terminal width
            height: New terminal height
        """
        self.terminal_width = width
        self.terminal_height = height
```

---

## VisualEffects

**File**: `kollabor/io/visual_effects.py`

Manages gradients, shimmer effects, color management, and theme support.

### Gradient Generation

```python
class VisualEffects:
    """Manages visual effects and styling."""
    
    # Gradient color palettes
    GRADIENTS = {
        GradientType.MESSAGE: {
            'start': '#7c3aed',  # Purple
            'end': '#2563eb',   # Blue
            'steps': 10
        },
        GradientType.HEADER: {
            'start': '#dc2626',  # Red
            'end': '#9333ea',   # Purple
            'steps': 8
        },
        GradientType.TOOL: {
            'start': '#059669',  # Emerald
            'end': '#0891b2',   # Cyan
            'steps': 5
        }
    }
    
    def get_gradient_color(
        self,
        gradient_type: GradientType,
        position: float = 0.5
    ) -> Dict[str, str]:
        """Get gradient color at position.
        
        Args:
            gradient_type: Type of gradient
            position: Position along gradient (0.0 to 1.0)
            
        Returns:
            Dict with 'start', 'end', and interpolated colors
        """
        palette = self.GRADIENTS.get(gradient_type)
        if not palette:
            return {'start': '0', 'end': '0'}
        
        start_color = self._hex_to_ansi(palette['start'])
        end_color = self._hex_to_ansi(palette['end'])
        
        return {
            'start': start_color,
            'end': end_color
        }
    
    def _hex_to_ansi(self, hex_color: str) -> str:
        """Convert hex color to ANSI 256-color.
        
        Args:
            hex_color: Hex color string (e.g., '#7c3aed')
            
        Returns:
            ANSI color number (0-255)
        """
        hex_color = hex_color.lstrip('#')
        r = int(hex_color[0:2], 16)
        g = int(hex_color[2:4], 16)
        b = int(hex_color[4:6], 16)
        
        # Simple conversion to 256-color space
        # This is a simplified version
        ansi = 16 + (36 * (r // 51)) + (6 * (g // 51)) + (b // 51)
        return str(ansi)
```

### Shimmer Effects

```python
def get_shimmer_char(self, frame: int) -> str:
    """Get shimmer character for animation frame.
    
    Args:
        frame: Animation frame number
        
    Returns:
        Shimmer character
    """
    shimmer_chars = ['░', '▒', '▓', '█', '▓', '▒']
    return shimmer_chars[frame % len(shimmer_chars)]

async def animate_shimmer(
    self,
    duration: float,
    speed: float = 5.0
) -> AsyncIterator[str]:
    """Animate shimmer effect.
    
    Args:
        duration: Animation duration in seconds
        speed: Animation speed (characters per second)
        
    Yields:
        Shimmer characters
    """
    total_frames = int(duration * speed)
    for i in range(total_frames):
        yield self.get_shimmer_char(i)
        await asyncio.sleep(1.0 / speed)
```

---

## TerminalState

**File**: `kollabor/io/terminal_state.py`

Manages terminal state, raw mode vs. cooked mode, and terminal initialization.

### Mode Switching

```python
class TerminalState:
    """Manages terminal state."""
    
    def __init__(self):
        self.in_raw_mode = False
        self.original_settings = None
    
    def enter_raw_mode(self) -> None:
        """Enter raw terminal mode.
        
        Raw mode allows character-by-character input
        without echo or line buffering.
        """
        if self.in_raw_mode:
            return  # Already in raw mode
        
        import termios
        import sys
        
        # Save original settings
        self.original_settings = termios.tcgetattr(sys.stdin)
        
        # Set raw mode
        new_settings = termios.tcgetattr(sys.stdin)
        new_settings[3] &= ~(termios.ICANON | termios.ECHO)
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, new_settings)
        
        self.in_raw_mode = True
    
    def exit_raw_mode(self) -> None:
        """Exit raw terminal mode."""
        if not self.in_raw_mode:
            return  # Not in raw mode
        
        import termios
        import sys
        
        # Restore original settings
        if self.original_settings:
            termios.tcsetattr(
                sys.stdin,
                termios.TCSADRAIN,
                self.original_settings
            )
        
        self.in_raw_mode = False
    
    def temporarily_exit_raw_mode(self) -> ContextManager:
        """Context manager to temporarily exit raw mode.
        
        Usage:
            with terminal_state.temporarily_exit_raw_mode():
                print("This prints immediately")
        """
        return TemporaryRawModeExit(self)
```

### Terminal Initialization

```python
def initialize_terminal(self) -> None:
    """Initialize terminal for rendering.
    
    Sets up alternate buffer, hides cursor,
    configures terminal settings.
    """
    import sys
    
    # Enter alternate buffer (preserves previous terminal content)
    sys.stdout.write('\033[?1049h')
    sys.stdout.flush()
    
    # Hide cursor
    sys.stdout.write('\033[?25l')
    sys.stdout.flush()
    
    # Enable alternate screen
    sys.stdout.write('\033[?47h')
    sys.stdout.flush()
    
    # Enter raw mode
    self.enter_raw_mode()

def restore_terminal(self) -> None:
    """Restore terminal to original state.
    
    Exits alternate buffer, shows cursor,
    restores original settings.
    """
    import sys
    
    # Exit raw mode
    self.exit_raw_mode()
    
    # Show cursor
    sys.stdout.write('\033[?25h')
    sys.stdout.flush()
    
    # Exit alternate buffer (restores previous content)
    sys.stdout.write('\033[?1049l')
    sys.stdout.flush()
```

---

## Render Flow

### Complete Render Flow Diagram

```mermaid
sequenceDiagram
    participant App as Application
    participant IH as InputHandler
    participant MC as MessageCoordinator
    participant TR as TerminalRenderer
    participant MR as MessageRenderer
    participant SR as StatusRenderer
    participant T as Terminal
    
    App->>IH: User submits message
    IH->>MC: display_user_message()
    MC->>MC: queue_message()
    MC->>MC: display_queued_messages()
    
    MC->>TR: clear_active_area()
    TR->>T: Clear screen
    
    MC->>TR: _display_single_message()
    TR->>MR: format_message()
    MR->>MR: format_message() (symbols, colors)
    MR-->>TR: formatted_lines
    
    TR->>T: print(formatted_lines)
    TR->>T: print("")  # blank line
    
    TR->>SR: render_status_bar()
    SR->>SR: get_area_lines() A, B, C
    SR-->>TR: status_lines
    
    TR->>T: print(status_lines)
    
    TR->>TR: update_dirty_regions()
    TR->>T: cursor to input position
```

### Event-Driven Rendering

```python
# INPUT_RENDER event triggers
await event_bus.emit_with_hooks(
    EventType.INPUT_RENDER,
    {"input_buffer": current_input},
    source="input_handler"
)

# Hook provides formatted input lines
formatted_lines = event.result.get('fancy_input_lines', [])
```

---

## Caching Strategy

### Render Cache

```python
class TerminalRenderer:
    """Render caching for performance."""
    
    def __init__(self, config: ConfigManager):
        self.render_cache = {}
        self.cache_enabled = config.get(
            'terminal.render_cache_enabled',
            True
        )
    
    def _get_cached_render(
        self,
        cache_key: str
    ) -> Optional[List[str]]:
        """Get cached render if available.
        
        Args:
            cache_key: Unique cache key
            
        Returns:
            Cached render lines or None
        """
        if not self.cache_enabled:
            return None
        
        return self.render_cache.get(cache_key)
    
    def _cache_render(
        self,
        cache_key: str,
        lines: List[str]
    ) -> None:
        """Cache render result.
        
        Args:
            cache_key: Unique cache key
            lines: Rendered lines
        """
        if not self.cache_enabled:
            return
        
        self.render_cache[cache_key] = lines
    
    def invalidate_cache(self, pattern: str = None) -> None:
        """Invalidate cache entries.
        
        Args:
            pattern: Optional pattern to match keys
                     (if None, clears all)
        """
        if pattern is None:
            self.render_cache.clear()
        else:
            # Remove keys matching pattern
            keys_to_remove = [
                k for k in self.render_cache.keys()
                if pattern in k
            ]
            for k in keys_to_remove:
                del self.render_cache[k]
```

### Dirty Region Tracking

```python
# Mark region as needing redraw
self.dirty_regions.add('messages')
self.dirty_regions.add('status')
self.dirty_regions.add('input')

# Check if rendering needed
if not self.dirty_regions:
    return  # Nothing to render

# Render and clear
self._render_messages()    # Renders messages
self._render_status()      # Renders status
self._render_input()       # Renders input
self.dirty_regions.clear()   # All rendered
```

---

## Examples

### Example 1: Displaying a User Message

```python
from kollabor.io.message_coordinator import MessageCoordinator

async def display_user_message_example():
    """Example of displaying a user message."""
    
    coordinator = MessageCoordinator(renderer)
    
    # Display user message
    await coordinator.display_message_sequence([
        ("user", "Hello, Claude!", {})
    ])
    
    # Output:
    # > Hello, Claude!
    #
```

### Example 2: Displaying Assistant Response with Tool Output

```python
async def display_response_with_tools_example():
    """Example of displaying assistant response with tool output."""
    
    coordinator = MessageCoordinator(renderer)
    
    # Display assistant response with tool execution
    await coordinator.display_message_sequence([
        ("assistant", "Let me check the file...", {}),
        ("system", "⏺ file_read(README.md)\n...content...", {}),
        ("system", "⏺ terminal(ls -la)\n✓ Done", {})
    ])
    
    # Output:
    # ∴ Let me check the file...
    # ⏺ file_read(README.md)
    # ...content...
    # ⏺ terminal(ls -la)
    # ✓ Done
```

### Example 3: Custom Status View

```python
from kollabor.io.status_renderer import StatusViewConfig, BlockConfig

async def create_custom_status_view():
    """Example of creating custom status view."""
    
    class CustomStatusView:
        def __init__(self, config):
            self.config = config
            self.count = 0
        
        def get_area_lines(self, area: str) -> List[str]:
            if area == 'A':
                return ["Custom View"]
            elif area == 'B':
                self.count += 1
                return [f"Count: {self.count}"]
            elif area == 'C':
                return ["Active"]
            return []
        
        def get_name(self) -> str:
            return "custom"
    
    # Register custom view
    renderer.status_renderer.register_status_view(
        "custom",
        CustomStatusView(config)
    )
    
    # Switch to custom view
    await renderer.status_renderer.switch_view("custom")
```

### Example 4: Custom Gradient

```python
from kollabor.io.visual_effects import GradientType

async def use_custom_gradient():
    """Example of using custom gradient."""
    
    # Register custom gradient
    renderer.visual_effects.GRADIENTS['custom'] = {
        'start': '#ff0000',  # Red
        'end': '#0000ff',   # Blue
        'steps': 10
    }
    
    # Use custom gradient
    colors = renderer.visual_effects.get_gradient_color(
        GradientType.MESSAGE  # Or create new type
    )
    
    # Apply to message
    formatted = renderer.message_renderer._apply_colors(
        "Hello with gradient!",
        {'fg': colors['start'], 'style': 'bold'}
    )
    print(formatted)
```

---

## Troubleshooting

### Issue: Garbled Terminal Output

**Symptoms**: Text overlapping, incorrect colors, artifacts

**Diagnosis**:
```python
# Check terminal capabilities
import os
term_type = os.environ.get('TERM', 'unknown')
print(f"TERM: {term_type}")

# Check color support
import subprocess
colors = subprocess.check_output(['tput', 'colors'])
print(f"Colors: {colors.decode().strip()}")
```

**Solutions**:
1. Ensure correct TERM type: `export TERM=xterm-256color`
2. Disable render cache: Set `terminal.render_cache_enabled: false`
3. Force color mode: `KOLLABOR_COLOR_MODE=truecolor`

### Issue: Slow Rendering Performance

**Symptoms**: Laggy response, low FPS

**Diagnosis**:
```python
# Check render time
import time
start = time.time()
await renderer.render_frame(force_render=True)
elapsed = (time.time() - start) * 1000
print(f"Render time: {elapsed:.1f}ms")

# Check dirty regions
print(f"Dirty regions: {renderer.dirty_regions}")
```

**Solutions**:
1. Enable render cache: Set `terminal.render_cache_enabled: true`
2. Increase target FPS: Set `terminal.render_fps: 15` (lower is faster)
3. Disable visual effects: Set `terminal.thinking_effect: none`

### Issue: Status Bar Not Updating

**Symptoms**: Status shows old data, view switch doesn't work

**Diagnosis**:
```python
# Check active view
print(f"Active view: {renderer.status_renderer.active_view}")

# Check registered views
print(f"Views: {list(renderer.status_renderer.status_views.keys())}")

# Check plugin status lines
plugin_status = plugin.get_status_lines()
print(f"Plugin status: {plugin_status}")
```

**Solutions**:
1. Ensure plugin returns status: Implement `get_status_lines()` method
2. Check plugin enabled: Verify `config.get('plugins.myplugin.enabled')`
3. Force status refresh: Emit `STATUS_CONTENT_UPDATE` event

### Issue: Messages Not Appearing

**Symptoms**: User or assistant messages not displayed

**Diagnosis**:
```python
# Check message queue
print(f"Message queue: {coordinator.message_queue}")

# Check display lock
print(f"Writing messages: {coordinator.writing_messages}")

# Check message format
lines = renderer.message_renderer.format_message(
    content="Test",
    message_type=MessageType.USER,
    format_style=FormatStyle.STANDARD
)
print(f"Formatted lines: {lines}")
```

**Solutions**:
1. Check coordinator lock: Ensure `display_lock` isn't held
2. Verify message format: Check `MessageType` enum values
3. Clear render cache: Call `renderer.invalidate_cache('messages')`

---

## Related Documents

- **[Architecture Overview](../architecture/system-architecture.md)** - System architecture and component relationships
- **[Event System Architecture](../architecture/event-system.md)** - Event-driven architecture for rendering
- **[Input Handling System](./input-handling.md)** - Input processing and command mode
- **[Buffer Transition and Render State](../reference/buffer-transition-and-render-state.md)** - Detailed render state documentation
- **[Modal System Guide](../reference/modal-system-guide.md)** - Modal rendering system

---

## References

**Source Files**:
- `kollabor/io/terminal_renderer.py` - Main rendering coordinator
- `kollabor/io/message_renderer.py` - Message formatting and colors
- `kollabor/io/message_coordinator.py` - Atomic message sequencing
- `kollabor/io/status_renderer.py` - Status bar management
- `kollabor/io/layout.py` - Layout calculations
- `kollabor/io/visual_effects.py` - Gradients and effects
- `kollabor/io/terminal_state.py` - Terminal state management

**Related Specifications**:
- `docs/specs/documentation-overhaul-spec.md` - Documentation specification
- `docs/reference/quick-start.md` - User-facing quick start guide

**External Resources**:
- [ANSI Escape Codes](https://en.wikipedia.org/wiki/ANSI_escape_code) - Terminal control sequences
- [Terminal Color Codes](https://misc.flogisoft.com/bash/tip_colors_and_formatting) - Color reference

---

*Last Updated: 2025-01-15*  
*Status: Review - Ready for technical review*  
*Version: 1.0.0*
