# WZRDClaw TUI Integration Skill
## OpenCode-Style Terminal UI Integration Patterns

### Overview
Provides specialized instructions for integrating WZRDClaw with OpenCode-style terminal user interfaces. Covers API client integration, TUI component patterns, and real-time backend communication.

### Core Integration Patterns

#### Pattern 1: API Client Integration
**File:** `wzrdclaw-api-client.js` / `.ts`
```javascript
// Basic usage
import { wzrdClawClient } from './wzrdclaw-api-client';

// Check backend status
const status = await wzrdClawClient.getStatus();
if (!status.reachable) {
  // Show error in TUI
  console.error('Backend not reachable');
}

// Execute tools
const result = await wzrdClawClient.bash('ls -la');
const files = await wzrdClawClient.glob('*.js');
const matches = await wzrdClawClient.grep('function');
```

**Key Methods:**
- `getStatus()` - Backend health check
- `listTools()` - Available tools
- `executeTool()` - Generic tool execution
- Tool-specific methods (`bash()`, `readFile()`, etc.)
- `chat()` - Simple chat interface

#### Pattern 2: TUI Component Structure
**Based on OpenCode patterns:**

```typescript
// OpenCode-style component structure
function SessionView() {
  const [messages, setMessages] = useState([]);
  const [tools, setTools] = useState([]);
  const client = useRef(new WZRDClawClient());
  
  useEffect(() => {
    // Load available tools
    client.current.listTools().then(setTools);
  }, []);
  
  // Render message like OpenCode
  const renderMessage = (msg, index) => (
    <box x={0} y={index * 3} width={width} height={3}>
      <text x={2} y={1}>{msg.role}: {msg.content}</text>
    </box>
  );
  
  // Execute tool and display result
  const executeAndDisplay = async (tool, params) => {
    const result = await client.current.executeTool(tool, params);
    
    // Add to messages
    setMessages(prev => [...prev, {
      role: 'tool',
      content: `Tool ${tool} executed: ${result.success ? '✅' : '❌'}`
    }]);
    
    return result;
  };
}
```

#### Pattern 3: Real-Time Tool Execution Display
```typescript
// Real-time output display pattern
class ToolOutputDisplay {
  constructor(client) {
    this.client = client;
    this.outputBuffer = [];
    this.isRunning = false;
  }
  
  async executeWithLiveOutput(tool, params) {
    this.isRunning = true;
    this.outputBuffer = [];
    
    // For long-running operations, show progress
    this.showProgress(`Executing ${tool}...`);
    
    try {
      const result = await this.client.executeTool(tool, params);
      
      if (result.success && result.output) {
        // Display output in chunks
        this.displayOutputChunks(result.output);
      }
      
      return result;
    } finally {
      this.isRunning = false;
      this.hideProgress();
    }
  }
  
  displayOutputChunks(output) {
    const lines = output.split('\n');
    lines.forEach((line, index) => {
      // Simulate typing effect
      setTimeout(() => {
        this.outputBuffer.push(line);
        this.renderOutput();
      }, index * 10);
    });
  }
}
```

### OpenCode Component Patterns

#### Dialog System Pattern
```typescript
// OpenCode-style dialog components
const DialogSystem = {
  alert: (title, message) => {
    // Render alert dialog
    return new Promise(resolve => {
      renderDialog({
        type: 'alert',
        title,
        message,
        buttons: [{ label: 'OK', action: resolve }]
      });
    });
  },
  
  confirm: (title, message) => {
    // Render confirmation dialog
    return new Promise(resolve => {
      renderDialog({
        type: 'confirm',
        title,
        message,
        buttons: [
          { label: 'Yes', action: () => resolve(true) },
          { label: 'No', action: () => resolve(false) }
        ]
      });
    });
  },
  
  prompt: (title, defaultValue = '') => {
    // Render input prompt
    return new Promise(resolve => {
      renderDialog({
        type: 'prompt',
        title,
        defaultValue,
        buttons: [
          { label: 'OK', action: (value) => resolve(value) },
          { label: 'Cancel', action: () => resolve(null) }
        ]
      });
    });
  }
};
```

#### Command Palette Pattern (Ctrl+P)
```typescript
// OpenCode-style command palette
class CommandPalette {
  constructor(client) {
    this.client = client;
    this.commands = [
      { label: 'List Tools', action: () => this.listTools() },
      { label: 'Execute Bash', action: () => this.promptBash() },
      { label: 'Search Files', action: () => this.promptSearch() },
      { label: 'Change Mode', action: () => this.selectMode() }
    ];
  }
  
  show() {
    // Render command palette overlay
    renderOverlay({
      title: 'Command Palette',
      items: this.commands,
      onSelect: (command) => command.action()
    });
  }
  
  async listTools() {
    const tools = await this.client.listTools();
    DialogSystem.alert('Available Tools', tools.join('\n'));
  }
}
```

#### Session Sidebar Pattern
```typescript
// OpenCode-style session sidebar
function SessionSidebar({ sessions, onSelectSession, onCreateSession }) {
  return (
    <box x={0} y={0} width={30} height={height} backgroundColor={theme.sidebarBg}>
      <text x={2} y={1} color={theme.sidebarFg}>Sessions</text>
      
      {/* Session list */}
      <For each={sessions}>
        {(session, index) => (
          <box 
            x={2} 
            y={3 + index * 2} 
            width={26} 
            height={2}
            backgroundColor={session.active ? theme.accent : theme.sidebarBg}
            onClick={() => onSelectSession(session.id)}
          >
            <text x={2} y={1}>{session.name}</text>
          </box>
        )}
      </For>
      
      {/* New session button */}
      <box 
        x={2} 
        y={height - 3} 
        width={26} 
        height={2}
        backgroundColor={theme.accent}
        onClick={onCreateSession}
      >
        <text x={2} y={1}>+ New Session</text>
      </box>
    </box>
  );
}
```

### Integration Implementation Guide

#### Step 1: Backend Connectivity
1. **Check health on startup**
   ```javascript
   const status = await wzrdClawClient.getStatus();
   if (!status.reachable) showBackendError();
   ```

2. **Load available tools**
   ```javascript
   const tools = await wzrdClawClient.listTools();
   updateToolPalette(tools);
   ```

3. **Monitor connection**
   ```javascript
   // Periodic health checks
   setInterval(async () => {
     const healthy = await wzrdClawClient.isReachable();
     updateConnectionStatus(healthy);
   }, 30000);
   ```

#### Step 2: Tool Execution UI
1. **Show tool selection**
   ```javascript
   const selectedTool = await DialogSystem.select(
     'Select Tool',
     tools.map(t => ({ label: t, value: t }))
   );
   ```

2. **Gather tool parameters**
   ```javascript
   const params = {};
   if (selectedTool === 'bash') {
     params.command = await DialogSystem.prompt('Enter command');
   } else if (selectedTool === 'read') {
     params.filePath = await DialogSystem.prompt('File path');
   }
   ```

3. **Execute and display**
   ```javascript
   const result = await wzrdClawClient.executeTool(selectedTool, params);
   displayToolResult(result);
   ```

#### Step 3: Error Handling & Fallbacks
1. **Connection errors**
   ```javascript
   try {
     await wzrdClawClient.executeTool(tool, params);
   } catch (error) {
     if (error.code === 'ECONNREFUSED') {
       showReconnectionDialog();
     } else {
       showErrorDialog(`Tool failed: ${error.message}`);
     }
   }
   ```

2. **Tool failures**
   ```javascript
   const result = await wzrdClawClient.executeTool(tool, params);
   if (!result.success) {
     showToolError(result.error || 'Tool execution failed');
   }
   ```

3. **Fallback modes**
   ```javascript
   // If backend unavailable, use local simulation
   if (!backendAvailable) {
     const simulated = simulateToolLocally(tool, params);
     displayResult(simulated, { simulated: true });
   }
   ```

### Example: Complete TUI Integration

#### File: `wzrdclaw-tui-integrated.tsx`
```typescript
import { render, useKeyboard, useTerminalDimensions } from "@opentui/solid";
import { createSignal, onMount } from "solid-js";
import { wzrdClawClient, WZRDClawClient } from "./wzrdclaw-api-client";

function WZRDClawTUI() {
  const [messages, setMessages] = createSignal([]);
  const [tools, setTools] = createSignal([]);
  const [connected, setConnected] = createSignal(false);
  const [mode, setMode] = createSignal('CHAT');
  const client = new WZRDClawClient();
  
  onMount(async () => {
    // Check connection
    const status = await client.getStatus();
    setConnected(status.reachable);
    
    if (status.reachable) {
      // Load tools
      const availableTools = await client.listTools();
      setTools(availableTools);
      
      // Add welcome message
      setMessages([{
        role: 'system',
        content: `Connected to WZRDClaw with ${availableTools.length} tools`
      }]);
    }
  });
  
  const handleCommand = async (input) => {
    // Detect mode from input
    const detectedMode = detectMode(input);
    setMode(detectedMode);
    
    // Add user message
    setMessages(prev => [...prev, { role: 'user', content: input }]);
    
    // Process based on mode
    switch (detectedMode) {
      case 'CODER':
        // Handle code generation/execution
        await handleCoderCommand(input);
        break;
      case 'THINKER':
        // Handle architectural questions
        await handleThinkerCommand(input);
        break;
      default:
        // Default chat response
        const response = await client.chat(input);
        setMessages(prev => [...prev, { 
          role: 'assistant', 
          content: response.response 
        }]);
    }
  };
  
  const handleCoderCommand = async (input) => {
    // Extract tool and parameters
    const { tool, params } = parseToolCommand(input);
    
    if (tool && tools().includes(tool)) {
      // Execute tool
      const result = await client.executeTool(tool, params);
      
      setMessages(prev => [...prev, {
        role: 'tool',
        content: `Tool ${tool} executed: ${result.success ? '✅' : '❌'}`
      }]);
      
      if (result.success && result.output) {
        setMessages(prev => [...prev, {
          role: 'output',
          content: result.output.substring(0, 500) // Limit output
        }]);
      }
    } else {
      // Generic code response
      const response = await client.chat(input);
      setMessages(prev => [...prev, {
        role: 'assistant',
        content: response.response
      }]);
    }
  };
  
  return (
    <MainLayout>
      <Header>
        <text>WZRD.dev TUI - Mode: {mode()} - Tools: {tools().length}</text>
        <text>{connected() ? '✅ Connected' : '❌ Disconnected'}</text>
      </Header>
      
      <MessageArea>
        <For each={messages()}>
          {(msg, index) => (
            <MessageBubble message={msg} index={index()} />
          )}
        </For>
      </MessageArea>
      
      <InputArea onSend={handleCommand} />
      
      <Toolbar tools={tools()} onSelectTool={handleToolSelection} />
    </MainLayout>
  );
}
```

### Testing Patterns

#### 1. Backend Connectivity Test
```javascript
// test-backend-connectivity.js
async function testBackendConnectivity() {
  console.log('Testing WZRDClaw backend connectivity...');
  
  const client = new WZRDClawClient();
  const status = await client.getStatus();
  
  if (!status.reachable) {
    console.error('❌ Backend not reachable');
    return false;
  }
  
  console.log(`✅ Backend reachable with ${status.toolCount} tools`);
  
  // Test each tool
  for (const tool of status.tools) {
    try {
      let testParams = {};
      if (tool === 'bash') testParams = { command: 'echo test' };
      if (tool === 'read') testParams = { filePath: __filename };
      
      const result = await client.executeTool(tool, testParams);
      console.log(`  ${tool}: ${result.success ? '✅' : '❌'}`);
    } catch (error) {
      console.log(`  ${tool}: ❌ ${error.message}`);
    }
  }
  
  return true;
}
```

#### 2. TUI Component Test
```javascript
// test-tui-components.js
function testTUIComponents() {
  console.log('Testing TUI component patterns...');
  
  // Test dialog system
  const DialogSystem = require('./dialog-system');
  console.assert(DialogSystem.alert, 'DialogSystem.alert exists');
  console.assert(DialogSystem.confirm, 'DialogSystem.confirm exists');
  console.assert(DialogSystem.prompt, 'DialogSystem.prompt exists');
  
  // Test command palette
  const CommandPalette = require('./command-palette');
  const palette = new CommandPalette();
  console.assert(palette.commands.length > 0, 'Command palette has commands');
  
  console.log('✅ All TUI component tests passed');
}
```

### Performance Optimization

#### 1. Lazy Loading
```typescript
// Load tools only when needed
const ToolLoader = {
  toolsCache: null,
  
  async getTools() {
    if (this.toolsCache) return this.toolsCache;
    
    this.toolsCache = await wzrdClawClient.listTools();
    return this.toolsCache;
  }
};
```

#### 2. Output Chunking
```typescript
// Process large outputs in chunks
function processLargeOutput(output, chunkSize = 1000) {
  const chunks = [];
  for (let i = 0; i < output.length; i += chunkSize) {
    chunks.push(output.substring(i, i + chunkSize));
  }
  return chunks;
}
```

#### 3. Connection Pooling
```javascript
// Reuse client connections
class ConnectionPool {
  constructor(maxConnections = 3) {
    this.pool = [];
    this.maxConnections = maxConnections;
  }
  
  async getClient() {
    if (this.pool.length > 0) {
      return this.pool.pop();
    }
    
    if (this.pool.length < this.maxConnections) {
      const client = new WZRDClawClient();
      await client.getStatus(); // Test connection
      return client;
    }
    
    // Wait for available client
    return new Promise(resolve => {
      const interval = setInterval(() => {
        if (this.pool.length > 0) {
          clearInterval(interval);
          resolve(this.pool.pop());
        }
      }, 100);
    });
  }
  
  releaseClient(client) {
    this.pool.push(client);
  }
}
```

### Common Issues & Solutions

#### Issue: TUI freezes during tool execution
**Solution:** Use background threads/web workers for long-running tools
```javascript
// Execute tool in background
const worker = new Worker('tool-worker.js');
worker.postMessage({ tool, params });
worker.onmessage = (event) => {
  displayResult(event.data);
};
```

#### Issue: Backend disconnects mid-session
**Solution:** Implement reconnection with exponential backoff
```javascript
class ReconnectionManager {
  constructor(client) {
    this.client = client;
    this.retryCount = 0;
    this.maxRetries = 5;
  }
  
  async ensureConnection() {
    while (this.retryCount < this.maxRetries) {
      if (await this.client.isReachable()) {
        this.retryCount = 0;
        return true;
      }
      
      // Exponential backoff
      const delay = Math.pow(2, this.retryCount) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
      this.retryCount++;
    }
    
    return false;
  }
}
```

#### Issue: Tool output too large for TUI
**Solution:** Implement pagination and filtering
```typescript
class OutputPagination {
  constructor(output, pageSize = 50) {
    this.output = output;
    this.pageSize = pageSize;
    this.currentPage = 0;
    this.totalPages = Math.ceil(output.length / pageSize);
  }
  
  getCurrentPage() {
    const start = this.currentPage * this.pageSize;
    const end = start + this.pageSize;
    return this.output.slice(start, end);
  }
  
  nextPage() {
    if (this.currentPage < this.totalPages - 1) {
      this.currentPage++;
      return this.getCurrentPage();
    }
    return null;
  }
  
  prevPage() {
    if (this.currentPage > 0) {
      this.currentPage--;
      return this.getCurrentPage();
    }
    return null;
  }
}
```

### Related Skills
- `opentui` - Core OpenTUI framework
- `wzrdclaw-patterns` - WZRDClaw architecture patterns
- `api` - HTTP/REST client patterns
- `cli` - Command-line interface patterns
- `ui-ux-master` - UI/UX design principles

### Version
1.0.0 - Initial TUI integration skill