Skip to content

0.0.20 cohort: the intuiTUIve demo loop

Memo celebrating, trunk up, with confetti cells Published on 2026-10-19, every crate by one release run, with rs-rich 0.0.8 on PyPI (uploaded early on 2026-10-20, UTC). See Publication.

0.0.20 is the demo loop's release. Eleven well-known terminal apps were rebuilt on intuiTUIve from its components alone: Yazi, scope-tui, gitui, bottom, Slumber, rata-tetris, csvlens, diskonaut, termusic, taskwarrior-tui and a Doom-style raycaster. What each lacked was added to the framework as a generic core piece or a plugin, and each clone was rebuilt on it, in rounds 2 to 7. What the demos are missing tells the story round by round, and Eleven apps, rebuilt shows each clone.

  • Tables, trees and lists that follow state. Columns and options from signals, markers, a keyed cursor, scrolling across, width priorities and row heights; TableSource with view_of, which filters, sorts and finds on a worker thread; keyed and lazy trees; list ranges.
  • Completion, a command line and queries. Input completion with ghost text, input history (for the session, in the app's state or in a file), a command line with modes and confirmations, and a query language over records (status:pending +work due.before:eow).
  • Layout and focus from state. .auto() switches, layers that composite in one pass, keyed, shown_when and size_with, titles and borders from state, focus scopes and focus by direction, treemaps, App::min_size, and text that fits or is cut in the middle.
  • Games and pixels. Sprites on a stage, RGBA pixel buffers drawn in half blocks, quadrants or Braille, and pixel cells (put_rgb). The style table no longer piles up: a 160x50 frame of changing colours went from 224 ms to 8 ms in a release build.
  • Every key, held keys and timers you can steer. rs-rich-interact and intuiTUIve keep key state from the kitty keyboard protocol: held keys, key releases, a modifier on its own, and every key with App::all_keys. Key repeat runs at the app's own delay and rate (DAS/ARR); timers have a handle (pause, resume, a new period); fixed steps catch up; App::max_fps paces frames. Input is drained before every draw, so keys typed during a slow frame no longer spread out.
  • Dates and zones in rs-rich-interact. dates::parse reads now, tomorrow, eow, 3d, -2d, ISO dates and more (natural dates); datetime::Zone gives the local zone, fixed offsets, POSIX rules and TZif data, tested across a change of summer time (time zones). intuiTUIve adds a year view and an agenda.
  • Plugins, off by default. files (Miller columns, tabs, tasks, previews, a picker), pcm and audio (capture, output and a player on a core transport), viz (meter, sparkline, spectrogram, bar spectrum), art images (Kitty, Sixel, iTerm2) and big text, micro sprites, wav and watch. rs-rich-ext gains DSP bands and charts, file listing, opening, file operations, the trash, git and archives.
  • Recording a game as it plays. rich record follows Kitty, Sixel and iTerm2 images on the cell grid, keeps every settled frame up to a set rate (Set Framerate 35), holds keys (KeyDown, KeyUp, Hold) and sends them with the kitty keyboard protocol, and writes an animated PNG. See a game, played with held keys.
  • Core: Text::markup(), a port of upstream's Text.markup (back to markup), byte-checked against rich 15.0.0. It is why core moves to 0.0.10.
  • One run publishes the release. A release-<name> tag (here release-0.0.20) starts one release.yml run that checks the release once, runs CI once and publishes every crate not yet on crates.io; the crates' <crate>-vX.Y.Z tags are records. 0.0.20 is the first release published this way. See the release documentation.

A default build of rs-rich still renders exactly like upstream rich 15.0.0; Text::markup() is upstream behaviour newly ported.

Independent package versions

Package Version Release role
rs-rich 0.0.10 Text::markup()
rs-rich-macros 0.0.4 Manifest only: requires core 0.0.10
rs-rich-plugin-api 0.0.4 Manifest only: requires core 0.0.10
rs-rich-art 0.0.13 Manifest only: requires core 0.0.10
rs-rich-diagram 0.0.3 Manifest only: requires core 0.0.10
rs-rich-mermaid 0.0.6 Manifest only: requires the versions above
rs-rich-lumis 0.0.4 Manifest only: requires the versions above
rs-rich-ext 0.0.17 StyleTable compaction and put_rgb; DSP, chart grid lines and options; file listing, opening, file operations, the trash, git and archives; palette::style_from_color_name
rs-rich-micro 0.0.6 Manifest only: requires ext 0.0.17
rs-rich-record 0.0.8 Terminal graphics, every frame at a set rate, held keys and the kitty keyboard protocol, APNG; packed frames
rs-rich-interact 0.0.8 Key state and releases, KeyCode::Modifier, all keys; natural dates and time zones; input drained per frame
rs-rich-ratatui 0.0.5 Re-exports style_from_color_name from rs-rich-ext; requires ext 0.0.17 (and interact 0.0.8 behind its interact feature)
rs-rich-intuituive 0.0.5 Rounds 2 to 7: tables, trees and lists from state, completion, history, the command line, queries, calendars, layout and focus from state, treemaps, sprites and pixels, held keys, timers and frame pacing; the files, pcm, audio, viz, art, micro, wav and watch plugins
rs-rich-embed 0.0.3 The menu key and modifier keys in the terminal pane and the web view; requires intuituive 0.0.5
rs-rich-web 0.0.3 Manifest only: requires the versions above
rs-rich-data 0.0.4 Manifest only: requires the versions above
rs-rich-cli 0.0.20 rich record's graphics, frame rate, held keys and --format apng; requires the versions above

The Python package, rs-rich 0.0.8 on PyPI, builds against these crates; its bindings do not change.

Migration

Breaking changes in 0.0.x crates (the CHANGELOG has each):

  • rs-rich-record's Timeline::frames holds packed frames (screen::Packed).
  • intuiTUIve's TreeItem, Column and TableOptions, and the recorder's options, gained public fields: a struct literal needs ..Default::default(). rs-rich-record's Format::ALL has 7 entries.
  • intuiTUIve's breadcrumb takes parts, not a path. The path form is the files plugin's path_crumb; .home_tilde() left the core.
  • intuiTUIve's audio module needs a feature: audio::pcm, Format, deinterleave, Frame and Matrix are behind the new off-by-default pcm feature, which audio and wav turn on.
  • audio::input returns Signal<Option<Frame>>: None before the first buffer, then the newest numbered Frame.
  • The files plugin's Previewer is a struct (Previewer::new(f)), no longer an Arc alias; PreviewSettings has a binary field.
  • layers composite: a layer shows the ones below where it draws nothing. A layer that relied on covering everything under it gives itself a background or a fill.
  • A tape with no Output line writes an APNG beside the GIF (see known issues).

Release test

  • Rounds 5 and 6: every bug fix starts with a regression test that failed before the fix.
  • The full local gate on the demo loop's branch (#757), with round 7 merged (a9f66e8): fmt, cargo check --workspace --all-targets, intuiTUIve clippy --all-features -D warnings; intuiTUIve --all-features 1,691 tests and the 28 goldens, with no failures; and every clone suite (git 23, top 25, csv 14, disk 21, blocks 18, http 22, music 20, taskwarrior 27, scope 29, raycast 28, files 47). scripts/check_packages.py passed. Earlier, on round 6 (e4bc67c): interact 503, record 101 and the CLI 716 tests passed.
  • CI on #757's heads found failures, each fixed before merge: the site's links, the Windows build of rs-rich-interact, the disk clone's tests on macOS's and Windows' long temporary paths, a set TZ on Windows, the recorder's timing tests on macOS, a re-recorded tape, and the CLI reference's version.
  • The golden fixtures are unchanged but for the new Text.markup cases, captured from rich 15.0.0.
  • The release run for release-0.0.20 (run) checked the release, ran CI once and published the 17 crates; it succeeded.

Not yet done, and by whom

  • A real-terminal pass of the termion and termwiz backends (the mouse, resizes and Ctrl+Z, and termwiz in Windows Terminal), carried over from 0.0.18 (see the 0.0.19 notes): the maintainer's.
  • Real Doom (rs-rich-doom) is pinned to a commit before round 6; moving it onto pixel cells, held keys, fixed_step and the stats handle is 0.0.21 work.

Known limits

See Known issues, which applies to this release. Found in 0.0.20:

Carried over: Chrome's DevTools port can still be reached by other local users while a web view is open; the pipe that replaces it ships in 0.0.21 on Linux and macOS. The 0.0.21 plan takes up the macOS recorder, the four bugs, csv's filter and the APNG default.

Publication

  1. On 2026-10-19, on main at 56c6c97, the 17 record tags (rs-rich-v0.0.10, rs-rich-macros-v0.0.4, rs-rich-plugin-api-v0.0.4, rs-rich-art-v0.0.13, rs-rich-diagram-v0.0.3, rs-rich-mermaid-v0.0.6, rs-rich-lumis-v0.0.4, rs-rich-ext-v0.0.17, rs-rich-micro-v0.0.6, rs-rich-record-v0.0.8, rs-rich-interact-v0.0.8, rs-rich-ratatui-v0.0.5, rs-rich-intuituive-v0.0.5, rs-rich-embed-v0.0.3, rs-rich-web-v0.0.3, rs-rich-data-v0.0.4, rs-rich-cli-v0.0.20), then release-0.0.20 and python-v0.0.8, each with Release: 0.0.20 and Commit: lines.
  2. The one release.yml run for release-0.0.20 published every crate, in RELEASES.toml's order.
  3. The Python package, python-v0.0.8 on 56c6c97, through pypi-release.yml: built with the crates, then published to PyPI once the maintainer approved it (run).