Terminal UI (oxidize-tui)
Relevant source files
The following files were used as context for generating this wiki page:
Terminal UI (oxidize-tui) is a full-screen console interface for the oxidize inference engine. It provides a visual environment to chat with LLMs, browse models, monitor server metrics, and view real-time logs.
The TUI operates as a standalone client. It does not link directly to the inference engine; instead, it manages an oxidize serve instance as a child process or connects to an existing server via an OpenAI-compatible HTTP API. This architecture ensures the UI remains a pure TypeScript application powered by Bun and OpenTUI, independent of the Rust core's heavy compute logic.
Sources: oxidize-tui/AGENTS.md:5-10, README.md:135-140
Architecture and Design
The application follows a decoupled architecture where the UI layer communicates exclusively through an API.
This diagram illustrates the separation between the TUI frontend, the immutable state store, and the underlying inference server.
Core Architectural Invariants
- Side Effect Ownership: The
actions.tsmodule owns all side effects. Components never spawn processes or initiate fetches directly. - State Management: The system uses an immutable snapshot store with
useSyncExternalStore. Selectors must remain referentially stable to prevent unnecessary re-renders. - Performance Optimization: Token deltas coalesce into a single store write every 40 ms. This prevents high-speed models from overwhelming the renderer.
- Model Browser: A pure-TypeScript GGUF header reader parses file metadata (architecture, quantization, parameters) in milliseconds without loading the entire model file.
Sources: oxidize-tui/AGENTS.md:10-15, oxidize-tui/AGENTS.md:30-45
Functional Components and Views
The TUI organizes functionality into four primary views, accessible via a global command palette (ctrl+k).
| View | Description |
|---|---|
| Chat | Interactive chat interface supporting SSE streaming and Markdown rendering. |
| Models | Local model browser that scans directories and collapses split shards. |
| Monitor | Real-time performance dashboard using Prometheus metrics. |
| Logs | Streamed server logs from the underlying inference engine. |
Sources: oxidize-tui/AGENTS.md:12-15, README.md:135-145
Markdown Rendering
The Markdown component utilizes a custom lightweight parser rather than a full specification parser. It handles the subset of Markdown typical of LLM outputs to maintain high performance in the terminal environment.
Supported Markdown Blocks:
- Paragraphs (
p) - Headers (
h1throughh6) - Lists (
li) with automatic indentation - Blockquotes (
quote) - Code blocks (
code) with language labeling - Horizontal rules (
rule)
Sources: oxidize-tui/src/components/Markdown.tsx:8-55
Process Integration
The TUI manages the inference lifecycle by wrapping the oxidize-cli and oxidize-server commands.
The sequence diagram shows how the TUI bootstraps the engine and communicates via internal API rewrites.
Command Mapping
When the TUI spawns the engine, it internally rewrites the serve subcommand to include --serve-api and --api-only. This ensures the Rust engine focuses solely on providing the HTTP API without its own local CLI interface.
Sources: oxidize-tui/AGENTS.md:55-60, oxidize-cli/src/main.rs:185-200
Configuration and Environment
The TUI is built using Bun and React 19.
Dependency Stack
- Runtime: Bun
- UI Framework: React 19
- TUI Primitives:
@opentui/core,@opentui/react - Language: TypeScript
Sources: oxidize-tui/package.json:15-25
Execution Commands
- Launch:
bun run start - Custom API:
bun run start -- --api http://127.0.0.1:8080 - Build:
bun run build(compiles to a single-file binary indist/oxidize-tui) - Testing:
bun test(includes rendered-frame tests using@opentui/react/test-utils)
Sources: oxidize-tui/package.json:8-14, oxidize-tui/AGENTS.md:47-55
Technical Constraints and Invariants
- Layout Safety: The TUI budgets width for all rows to prevent wrapping. Frame tests in
src/ui.test.tsxassert that no line exceeds the terminal width (standardized at 76 columns for testing). - Memory Management: Large GGUF arrays (e.g., tokenizer vocabularies) are walked and summarized if they exceed 512 elements to avoid excessive memory usage during model scanning.
- Keyboard Routing: The
App.tsxcomponent uses a singleuseKeyboardhook for routing. Global bindings (e.g.,ctrl+k) take precedence, while single-key bindings are view-local and typically disabled when the Chat input is focused.
Sources: oxidize-tui/AGENTS.md:35-45, oxidize-tui/AGENTS.md:65-70