Skip to content

[Architecture] oclite: Scroll region layout with fixed bottom panel #72

Description

@randomm

Description

Implement ANSI scroll region architecture for oclite — scrollable conversation area with fixed bottom panel.

Problem

After removing alt screen buffer (#66), oclite writes everything append-only to the main terminal buffer. This means:

  • ❌ Cannot rewrite tool status lines once scrolled
  • ❌ Cannot have a persistent status bar
  • ❌ Cannot show live metrics during streaming
  • ❌ Cannot have a fixed input area

Solution: ANSI Scroll Regions

Use \x1b[{top};{bottom}r to define a scroll region that covers most of the terminal, with 2-3 fixed lines at the bottom.

Layout:

┌─────────────────────────────────────┐
│ Scrollable conversation area        │ ← Scroll region (rows 1 to N-3)
│ User messages, agent responses      │
│ Tool output, markdown text          │
│ ...scrolls naturally...             │
│                                     │
├─────────────────────────────────────┤
│ ◆ Thinking · 5s · 3/5 tools        │ ← Fixed status line (row N-2)
│ project-manager ❯ █                │ ← Fixed input line (row N-1)
│ Esc cancel · Shift+Tab agents      │ ← Fixed hint bar (row N)
└─────────────────────────────────────┘

Requirements

Scroll Region Setup

  • On startup: query terminal size, set scroll region \x1b[1;{rows-3}r
  • Handle SIGWINCH (terminal resize) — recalculate and reset scroll region
  • On cleanup: reset scroll region to full terminal \x1b[r

Fixed Bottom Panel (3 lines)

  • Status line: During streaming shows spinner + elapsed time + tool count + token count. During idle shows nothing or session info.
  • Input line: Prompt + user input (project-manager ❯ █)
  • Hint bar: Context-sensitive keyboard shortcuts (Esc cancel · Shift+Tab agents · /help)

Writing to Scroll Region

  • All conversation output (text, tool display, errors) writes to scroll region
  • Scroll region scrolls naturally — old content preserved in scroll buffer
  • New content appends at bottom of scroll region, pushing old content up

Writing to Fixed Panel

  • Use \x1b[s (save cursor) before updating fixed lines
  • Move to fixed line with \x1b[{row};1H (absolute position)
  • Write content + clear to end of line
  • Use \x1b[u (restore cursor) to return to scroll region
  • Update fixed panel without disturbing scroll region content

Terminal Resize Handling

  • Listen for SIGWINCH signal
  • Recalculate scroll region boundaries
  • Redraw fixed bottom panel
  • Preserve scroll position in conversation area

Implementation Plan

  1. Create src/cli/lite/layout.ts — scroll region manager
  2. Modify index.ts — use layout manager for all writes
  3. Modify spinner.ts — render in status line instead of scroll region
  4. Modify bottombar.ts — render in fixed input/hint lines

Depends On

  • None (foundational)

Blocks

Technical Reference

  • ANSI scroll region: \x1b[{top};{bottom}r (DEC origin mode)
  • Terminal size: process.stdout.rows, process.stdout.columns
  • Resize signal: process.on('SIGWINCH', handler)
  • Save/restore cursor: \x1b[s / \x1b[u
  • Absolute position: \x1b[{row};{col}H

Files

  • New: packages/opencode/src/cli/lite/layout.ts
  • Modified: packages/opencode/src/cli/lite/index.ts
  • Modified: packages/opencode/src/cli/lite/spinner.ts
  • Modified: packages/opencode/src/cli/lite/bottombar.ts

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions