Files
opencode-krates-connector/design/shell-logs.md
Hermes Agent 89bc5e8c15 docs: Finalize all design documents
Signed-off-by: Hermes Agent <hermes@nosuchhost>
2026-06-16 09:00:33 -04:00

5.1 KiB

Design Document: Shell & Logs Feature Specification

Overview

Shell and Logs are real-time terminal and streaming views for Kubernetes resources. These features enable users to interact with running pods and monitor application behavior.

Shell Terminal (kubectl exec)

Requirements

  • Implementation: xterm.js on client
  • Backend: WebSocket → kubectl exec
  • Protocol: Bidirectional terminal protocol

Terminal Configuration

{
  rows: 24,
  cols: 80,
  fontFamily: 'IBM Plex Mono',
  fontSize: 12,
  lineHeight: 1.5,
  cursorBlink: true,
  theme: {
    background: '#1a1e26',
    foreground: '#b9c6d8',
  }
}

Connection Flow

  1. User opens shell view
  2. Extract pod name and namespace
  3. Connect WebSocket to /ws/shell?pod=X&ns=Y
  4. Backend:
    • Extract query params
    • Connect to k8s exec API
    • Create execstream
    • Proxy bidirectionally
  5. Frontend:
    • Initialize xterm
    • Attach to WebSocket
    • Handle resize events
    • Route keypresses

Key Routing

  • Shell focused + type: Route to terminal
  • Canvas shortcuts disabled when shell has focus
  • Space key: Goes to terminal (not spotlight)
  • Ctrl/⌘+scroll: Zoom canvas (not terminal zoom)

Resize Handling

  • Client: term.resize(cols, rows)
  • Server: Send resize message via WebSocket
  • Backend: Update k8s exec term size
  • Debounce: 100ms for resize events

State Management

interface ShellState {
  connected: boolean;
  connectedAt: number;
  lastActive: number;
  buffer: string[];
  cols: number;
  rows: number;
}

Error States

  • Connection failed: Show error message
  • Disconnected: Show "Disconnected" + reconnect button
  • Permission denied: Show clear error
  • Pod not found: Show error message

Logs Viewer (kubectl logs)

Requirements

  • Implementation: WebSocket streaming
  • Auto-scroll: To bottom by default
  • Color coding: ERROR/WARN/INFO

Connection Flow

  1. User opens logs view
  2. Connect to /ws/logs?pod=X&ns=Y
  3. Backend:
    • Start kubectl logs stream
    • Forward to WebSocket
  4. Frontend:
    • Append lines to buffer
    • Auto-scroll if at bottom
    • Colorize based on level

Log Parsing

Each log line should include:

  • Timestamp
  • Log level (ERROR/WARN/INFO/DEBUG)
  • Message

Format:

interface LogLine {
  timestamp: string;  // ISO 8601
  level: 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';
  message: string;
}

Color Coding

  • ERROR: #ef6f6f
  • WARN: #e8b54a
  • INFO: #b9c6d8
  • DEBUG: #6b7280

Auto-Scroll Logic

  • Track scroll position: Store scrollTop
  • At bottom: Auto-scroll on new log
  • Scrolled up: Don't auto-scroll
  • Threshold: Within 20px of bottom = "at bottom"

User Controls

  • Click auto-scroll toggle: Switch between auto and manual scroll
  • Clear logs: Button to clear buffer
  • Copy log line: Right-click menu
  • Filter: Simple filtering (show/hide levels)

State Management

interface LogsState {
  connected: boolean;
  autoScroll: boolean;
  logLines: LogLine[];
  scrollPosition: number;
  filterLevels: Set<LogLevel>;
}

Streaming Considerations

  • Backpressure: Buffer if client slow
  • Rate limiting: Server can throttle logs
  • Keep-alive: Ping every 30s
  • Reconnect: Exponential backoff on disconnect

Performance Optimization

  • Virtualization: Only render visible lines
  • Batching: Flush logs in batches if high volume
  • Throttling: 16ms throttle for updates
  • Cleanup: Remove old logs (keep last 1000 lines)

Shared Features

View State

  • Both views persist state in krate.window.state
  • reconnect: Auto reconnect on disconnect
  • timestamps: Show/hide timestamps
  • wrap: Word wrap toggle

Tab Switching

  • Shell tab: Enabled for pods only
  • Logs tab: Enabled for pods/workloads
  • Empty state: Show helpful message for unsupported resources

Close Behavior

  • Shell: Keep buffer, show "Disconnnected"
  • Logs: Stop streaming, keep buffer
  • Cleanup: Close WebSocket, cancel watchers

WebSocket Protocol

Shell

// Client → Server
{
  type: 'shell:input',
  data: string  // Key press data
}

{
  type: 'shell:resize',
  cols: number,
  rows: number
}

// Server → Client
{
  type: 'shell:output',
  data: string  // stdout/stderr
}

{
  type: 'shell:status',
  connected: boolean,
  message?: string
}

Logs

// Client → Server
{
  type: 'logs:subscribe',
  pod: string,
  namespace: string,
  follow: boolean,
  timestamps: boolean
}

{
  type: 'logs:filter',
  levels: string[]
}

// Server → Client
{
  type: 'log',
  log: LogLine
}

{
  type: 'status',
  connected: boolean,
  message?: string
}

Gotchas

  1. Space key: Must distinguish between canvas pan and shell input
  2. Focus routing: Route keys based on hovered window
  3. Scroll management: Track scroll position for logs
  4. Terminal resize: Debounce resize events
  5. Reconnection: Handle WebSocket disconnects gracefully
  6. Memory: Clean up old logs/shell buffers
  7. Authentication: Validate user on WebSocket upgrade
  8. Permissions: Enforce namespace RBAC on backend