jackin'
Behind jackin' — InternalsArchitecture Decision Records

ADR-003: Ratatui as the TUI rendering library

Why jackin' uses ratatui and not tui-rs, crossterm-raw, or another terminal rendering approach.

Status: Accepted Current state: ratatui 0.30 used across all three TUI surfaces. SocketBackend custom backend in jackin-capsule for attach-socket rendering (see ADR-004). Date: 2026-05-30 Deciders: Operator + agent

Context

jackin' needs to render full-screen terminal UIs on three surfaces: the host workspace console (jackin-console), the launch progress cockpit (jackin-launch), and the in-container multiplexer (jackin-capsule). The choices at the time of evaluation were:

  • tui-rs — the original Rust immediate-mode TUI library. Archived/abandoned in 2023.
  • ratatui — a community fork of tui-rs, actively maintained as its de-facto successor.
  • Raw ANSI/crossterm — write escape sequences directly; maximum control, no widget abstraction.
  • cursive — retained-mode widget library; richer widget tree but heavier, less composable.

Decision

Use ratatui as the primary TUI rendering library across all three surfaces.

ratatui is pinned at 0.30 per-crate in each consuming crate — crates/jackin-tui/Cargo.toml, crates/jackin-capsule/Cargo.toml, crates/jackin-console/Cargo.toml, crates/jackin-launch/Cargo.toml, and crates/jackin-tui-lookbook/Cargo.toml:

ratatui = "0.30"

Why ratatui over tui-rs: tui-rs is archived. ratatui is the fork that the tui-rs maintainer and the broader community adopted as the continuation. All active development, bug fixes, and new widget work happens in ratatui. Using tui-rs would mean no upstream fixes.

Why ratatui over raw ANSI everywhere: Raw ANSI gives byte-level control but requires hand-rolling layout, clipping, UTF-8 display-width, scrollbar geometry, and double-buffered diffing. ratatui handles all of that through its Buffer/Rect/Widget model, which is composable and testable via TestBackend. The capsule now renders pane body content from jackin-term snapshots through PaneBodyWidget (see ADR-004), while chrome, dialogs, and overlays also use ratatui.

Why ratatui over cursive: cursive is retained-mode (a widget tree you mutate) versus ratatui's immediate-mode (render from state every frame). Immediate-mode pairs directly with the Elm Architecture adopted across all jackin' TUI surfaces: state → render, no widget identity to track. ratatui also has a much larger and more active ecosystem of third-party widgets and examples.

Consequences

  • All three surfaces share the same rendering primitives, Rect/Layout/Block/Paragraph/Widget model, and TestBackend for snapshot tests.
  • The shared jackin-tui crate owns cross-surface components; ratatui types flow through its public API, making ratatui an intentional public dependency.
  • The capsule uses a custom SocketBackend that serialises Buffer::diff output over the attach socket (see ADR-004); this is possible because ratatui's backend trait is open.
  • Major ratatui version bumps require auditing widget API changes across all three surfaces. The matching per-crate 0.30 pins keep every crate on the same version.
  • ratatui is pre-1.0 but is the canonical active successor to tui-rs with broad ecosystem adoption; the pre-1.0 API instability is acceptable given the lack of maintained alternatives.

On this page