Files
headquarter/docs/features/terminal.md
T
alex a01e6252f5 docs: add responsive terminal documentation
- Add docs/features/terminal.md with user guide, connection states,
  keyboard shortcuts, protocol details, and troubleshooting
- Update docs/architecture/frontend.md with terminal component stack,
  connection hook behavior, and data flow diagrams
- Update docs/architecture/backend.md with terminal system architecture,
  protocol reference, message batching, and reconnect behavior
- Update docs/README.md to include terminal in feature list
2026-05-27 21:46:57 +02:00

8.5 KiB
Raw Blame History

Web Terminal

Overview

The web terminal provides an interactive shell session inside running tool instances directly from your browser. It uses xterm.js to render a full terminal emulator connected via WebSocket to a PTY-backed docker exec session.

The terminal is designed to feel as close to a local terminal as possible, with features for network resilience, low-latency typing, and session continuity.

How to Use

Opening a Terminal

  1. Navigate to a project and select a repository
  2. Go to the repository workspace
  3. Start or select a tool instance that supports the terminal interface
  4. Click the "Open Terminal" button

The terminal opens in full-page mode with a status bar at the top.

Terminal Layout

┌─────────────────────────────────────────────┐
│  ● Connected                [Reconnect] [×] │
├─────────────────────────────────────────────┤
│                                             │
│  user@container:~$ ls -la                   │
│  total 128                                  │
│  drwxr-xr-x  5 user user 4096 May 27 10:00 │
│  ...                                        │
│                                             │
└─────────────────────────────────────────────┘

Status bar (top):

  • Connection dot — color indicates connection health
  • Status text — shows current state and latency
  • Reconnect button — appears when disconnected
  • Close button — returns to the previous page

Connection States

Indicator Meaning Action
🟡 Yellow dot + "Connecting..." Opening WebSocket Wait or check network
🟢 Green dot + "Connected" Healthy connection (<100ms) Ready to use
🟡 Yellow dot + "Slow (150ms)" Elevated latency Connection usable but laggy
🟡 Yellow dot + "Reconnecting (2)" Connection lost, retrying Wait for auto-reconnect
Gray dot + "Disconnected" Max retries exceeded Click Reconnect or refresh

Hover the status dot to see the current round-trip latency in milliseconds.

Typing

Type normally as you would in a local terminal. The terminal supports:

  • Printable characters appear instantly (local echo)
  • Special keys (Tab, Enter, Ctrl+C, arrow keys) are sent to the server
  • Password prompts automatically suppress local echo
  • Unicode input and output

Reconnecting

The terminal automatically reconnects if the WebSocket drops:

  • Brief disconnects (WiFi hiccups, proxy timeouts) are recovered within 15 seconds
  • Up to 10 reconnection attempts with exponential backoff
  • Scrollback is preserved across reconnects
  • A visual divider (--- Reconnected ---) separates old and new output

Manual reconnect:

  • Click the Reconnect button in the status bar
  • Or press Ctrl+Shift+R anywhere in the terminal page

Session Ended

When the container process exits (e.g., you run exit or the container stops), the terminal shows an overlay:

┌─────────────────────────┐
│    Session Ended        │
│ The container process   │
│ has exited.             │
│                         │
│ [Reconnect]  [Go Back]  │
└─────────────────────────┘
  • Reconnect — spawns a new shell session in the same container
  • Go Back — returns to the workspace page

Keyboard Shortcuts

Shortcut Action
Ctrl+Shift+R Force reconnect (bypasses backoff)
Standard terminal shortcuts Ctrl+C, Ctrl+D, Ctrl+L, Tab completion, etc.

Technical Details

WebSocket Protocol

The terminal communicates over a binary WebSocket with mixed JSON control messages.

Connection:

ws://api.example.com/ws/tool-instances/{instance_id}/terminal

Binary frames carry raw terminal I/O. Text (JSON) frames carry control messages:

Client → Server:

  • {"type":"ping","id":n} — heartbeat ping
  • {"type":"resize","cols":120,"rows":40} — terminal resize
  • Raw bytes — keystroke input

Server → Client:

  • {"type":"pong","id":n} — heartbeat response
  • {"type":"status","status":"connected"} — session ready
  • {"type":"set_echo_state","enabled":false} — disable local echo
  • {"type":"session_ended","reason":"process_exit"} — session ended
  • Raw bytes — terminal output

Architecture

Browser                          Backend
┌──────────────────────┐         ┌─────────────────────────────┐
│ TerminalComponent    │         │ terminal.py (WS endpoint)   │
│ ├─ xterm.js          │◄───────►│ ├─ auth + session mgmt      │
│ ├─ FitAddon          │  WS     │ └─ echo state detection     │
│ ├─ SerializeAddon    │         │                             │
│ └─ useTerminalConn.  │         │ TerminalManager             │
│    ├─ heartbeat      │         │ ├─ read_loop (batching)     │
│    ├─ reconnect      │         │ ├─ write_loop               │
│    ├─ local echo     │         │ └─ heartbeat_loop           │
│    └─ resize throttle│         │                             │
│                      │         │ TerminalSession             │
│ sessionStorage       │         │ ├─ PTY + docker exec        │
│ (scrollback backup)  │         │ └─ termios echo detection   │
└──────────────────────┘         └─────────────────────────────┘

Reconnect Behavior

On disconnect:

  1. The client serializes terminal scrollback to sessionStorage
  2. Backoff timer starts (1s, 2s, 4s, 8s, 16s, then caps at 30s)
  3. On reconnect, scrollback is restored + divider line
  4. A new docker exec session is spawned transparently

Note: The underlying docker exec PTY is not resumable. Reconnect creates a new shell, but scrollback continuity makes this transparent.

Performance

  • Local echo makes printable characters appear in <1ms
  • Message batching on the backend reduces WebSocket frame overhead
  • Resize debouncing (200ms) + throttling (500ms) prevents server spam
  • Heartbeat interval is 15s to balance detection speed with server load

Troubleshooting

"Connecting..." stays yellow

Issue: WebSocket cannot open Check:

  1. Is the API server running?
  2. Is the tool instance in "running" status?
  3. Check browser console for connection errors
  4. Verify the VITE_API_BASE_URL points to the correct API

"Reconnecting" loops forever

Issue: Max reconnection attempts exceeded Check:

  1. Is the container still running? (docker ps)
  2. Did the container crash or get stopped?
  3. Check server logs for Terminal session error

Typing feels slow

Issue: High latency or no local echo Check:

  1. Hover the status dot — latency >100ms is shown as "Slow"
  2. Local echo only works for printable ASCII characters
  3. Password prompts intentionally disable echo
  4. Very high latency may indicate a congested network

Terminal is blank after reconnect

Issue: Scrollback not restored Check:

  1. sessionStorage may have been cleared (new browser session)
  2. The scrollback cap is 10,000 lines — very long sessions may truncate
  3. Browser privacy settings may block sessionStorage

"Session Ended" immediately

Issue: Container process exits right away Check:

  1. The container's default command may have finished
  2. Check the tool type's Docker Compose template
  3. Some tools (like one-off scripts) are not meant for persistent terminal sessions

Configuration

No additional configuration is required. The terminal adapts automatically to:

  • Browser window size (via ResizeObserver)
  • System light/dark theme preference
  • Network conditions (reconnect backoff)
  • Workspace — Open the terminal from the repository workspace
  • Tool Types — Configure which tools expose a terminal interface
  • SSH Keys — Manage SSH keys for repository access from within the terminal