Changelog
0.5.25 (2026-08-15)
-
The cursor trail actually works now. Five open issues traced to one pair of root causes: the animation's continuation flag was read before the trail advanced, so a trail could freeze mid-flight and stay painted until unrelated output arrived — the "trail covers the whole screen" screenshots (#1597) were that freeze photographing a scroll-sized jump — and the spring integration snapped to its destination whenever a frame gap exceeded the animation length, which at event-driven frame cadence was most of the time, the "feels like 15 FPS" choppiness of #1830. The motion model is now kitty's, verified line-by-line against its source: an exponential ease-out that composes exactly across irregular frames (no fixed-cadence render loop to depend on), with per-corner speed picked by direction alignment so the quad stretches into the smear. Around it, the behaviors the issue tracker asked for: the trail fades out when a program hides the cursor — yazi and lazygit redraws no longer animate a phantom (#1511) — jumps at or under a threshold of cells don't trail so typing stays trail-free, and four new
[effects]options:trail-cursor-color,trail-cursor-opacity(#1594),trail-cursor-decay = [fast_ms, slow_ms], andtrail-cursor-start-threshold(#1520). One invariant runs through the rework: layout is never travel — window resizes, font-size changes, display rescales, split-divider drags and tab-strip reflows snap the trail in place, and panel switches teleport it, so the smear only ever draws where the cursor actually went; and beam and underline trails converge onto the exact cursor geometry the grid draws, reusing its thickness and baseline math rather than approximating them (#1871). -
Rio launches on macOS 10.15 again. wgpu 30 references HDR color-space constants (
kCGColorSpaceExtendedDisplayP3, the BT.2100 pair) that only exist on macOS 11+; their use is runtime-gated, but the references linked as strong dyld imports, so the loader aborted the launch before a single line of Rio ran — theSymbol not foundcrash of #1873 and #1711, broken since the wgpu upgrade in 0.4.9. CoreGraphics is now weak-linked for the rio binary: the missing constants resolve to null instead of aborting, every CG symbol Rio actually calls has existed since 10.11, and an audit of the binary's import table found no other post-10.15 strong reference waiting behind this one. Upstream fixed the root cause on trunk a week after v30 shipped; gfx-rs/wgpu#10067 asks for a patch release, and the next wgpu upgrade retires the workaround. -
tmux new -ADXsno longer crashes Rio. The-Xflag SIGHUPs the shell of a background tab, and the close path only adjusted the focused-tab index when the dying tab was itself the focused one: removing a background tab shifted every index left while the focused index stayed put, and the very next tab lookup panicked out of bounds (#1848). The rewrite also closes two adjacent holes the crash exposed: a background tab's PTY exiting while the focused tab had splits used to leave a zombie tab that never closed, and a background tab that itself had splits could lose the whole tab, living splits included, when just one of its shells exited. The close path now searches every panel of every tab and removes exactly the panel that died. -
Hovering a link shows its target in a bottom-left pill, the way a browser status bar does. An OSC 8 link's display text is arbitrary, so its destination stayed invisible until you had already opened it; the pill shows the real URI, tail-elided so the scheme and host always survive truncation, and it never draws while a modal overlay (search, command palette, assistant, quit confirmation) would consume the click anyway (#1874, by @aymanbagabas).
-
librio: mouse reporting for embedders.
mouse_button()andmouse_motion()encode presses, releases and drags for programs that grab the mouse (X10 and DEC 1000/1002/1003), honoring shift-to-bypass so local selection stays reachable. Both return whether a report was written, telling the host when not to start its own selection. Exposed over the C ABI.
0.5.24 (2026-08-13)
-
tmux redraws are atomic in Rio now. Rio's terminfo has advertised the
Synccapability for years in the legacy iTerm2 DCS form (ESC P =1s ESC \), a form Rio's parser never implemented — the synchronized-update support that landed later spoke only the modernCSI ? 2026dialect and nobody went back to reconcile the two. tmux trusts the terminfo entry, so it dutifully bracketed every redraw with begin/end markers Rio swallowed and ignored: no tmux redraw was ever synchronized, and each frame painted as the bytes trickled in, visible as flicker and momentarily inconsistent screens during heavy TUI updates under tmux. Both sides are fixed: the parser honors the DCS bracketing form (including markers split across reads, which arrives constantly from a PTY), and the terminfo entry now advertises theCSI ? 2026form, so an updated terminfo gets atomic redraws from tmux and anything else that consultsSync. Upstream, tmux #5489 proposes Rio for tmux's default terminal-features so the capability set stops depending on which terminfo happens to be installed; until a tmux carrying it ships,set -as terminal-features 'rio*:sync'in tmux.conf does the same by hand. -
Legacy widths are pure wcwidth again. When grapheme clustering is off (
grapheme-clustering = false, or a program'sDECRST 2027), an emoji variation selector no longer flips the width of the cell before it — that behavior was a stopgap from before mode 2027 existed, and in legacy mode it is exactly wrong: applications that position text by wcwidth get a cell layout they cannot predict, and every full-screen redraw from tmux desyncs by one column at each flipped cell, leaving stray characters behind. Width changes from variation selectors now happen only inside the mode-2027 cluster path, where programs opt in knowingly. Alongside it, legacy mode stopped attaching selectors to cells that are not emoji bases: a selector after a plain letter is presentation noise, and storing it polluted copy, serialization and round-trips for zero render effect. -
librio: measure a grapheme cluster without printing it.
cluster_width()takes a UTF-32 buffer and returns how many codepoints its first grapheme cluster spans and how many terminal cells it occupies, applying exactly the rules the mode-2027 print path applies: VS16 widens and VS15 narrows a valid emoji base, any width-bearing continuation makes the cluster wide, invalid selectors are consumed without effect. It is the measurement half an embedder needs to shape and place text for cells without replaying bytes through a terminal, exposed ascluster_widthin Rust,rio_cluster_widthover the C ABI, andcluster_width(returning[len, width]) on the wasm class. The FFI edge is defined rather than assumed: values that are not Unicode scalars measure as one narrow codepoint when they lead and terminate the cluster when they follow, so untrusted input cannot wedge the walk. The parity claim is enforced, not aspirational — a differential test prints each measured cluster into a live mode-2027 grid and demands agreement on codepoint count and cell width, and a randomized 2,000-sequence soak over bases, joiners, selectors and modifiers holds cell width and cursor advance to the measured answer. One documented limit: a cluster led by a zero-width Prepend codepoint (Arabic number signs and kin) measures by pure segmentation while the print path drops the orphan lead — the same open limitation ghostty's measurement API carries. -
Modifier-click opens links even when the program owns the mouse. With mouse reporting on (vim, tmux with
mouse on), a hint-modifier click was forwarded to the program instead of opening the link under the pointer; it now bypasses mouse mode. The pointer icon and hint highlight also update the moment the modifier is pressed or released mid-hover rather than on the next mouse move (#1869, by @aymanbagabas). A pre-release adversarial review then hardened the whole click contract around a press-time latch: the press records which link it landed on, and the release opens exactly that link, only when it lands back on the same span — so a drag that ends over a different link opens nothing, a modifier change mid-click cannot swap which configured action runs, and a press swallowed by window chrome (tab strip, dialogs) can never open a highlight it never touched. The same latch keeps the bypass airtight for the application underneath: a mouse-mode program now sees a hint click as nothing at all — previously the press and release were hidden but drag motion still leaked through as button events with no press around them — and a highlight can no longer outlive its modifier via the window padding and hijack a later plain click. Links open on release rather than press now, the way buttons behave everywhere else. -
macOS: double-clicking the top of the window zooms it again when the tab strip is hidden. With
hide-if-singlehiding the strip, the reserved band at the top is window chrome for dragging, but the standard double-click-to-zoom gesture had been lost with it; the band now routes through one navigation predicate that keeps both behaviors (#1867, by @jxdones).
0.5.23 (2026-08-12)
-
Scrolling back through history no longer corrupts the view. The viewport's scrollback position is an offset counted from the live bottom, and any scroll that pushes rows into history grows it so the same content stays on screen. The bookkeeping had one wrong branch: scrolls that add nothing to history, an editor's insert/delete line, any scroll region that does not start at the top row, grew the offset anyway. Once it drifted past the rows that actually exist, the storage index arithmetic wrapped and the renderer was handed arbitrary rows, painting fragments of other lines at wrong positions until a full redraw washed them out. The offset now moves only when history does. Two neighbours came out of the same investigation: a viewport pinned at the scrollback cap slides when a region scroll evicts history, and that frame now takes full damage since every visible row changed; and growing the window while scrolled back adjusted the offset by the intended row count rather than the rows history could actually supply, with both resize paths now clamping against what remains.
-
Idle terminals stop rendering at PTY rate. Consuming a frame never recorded the cursor position it carried, so after the first cursor movement every damage check reported the cursor as moved, and every PTY read fired a redraw event, woke the renderer, and took the terminal lock even when nothing had changed. The consumed frame now marks its cursor as seen, and a drain that changed nothing fires nothing.
-
These came out of a new damage-pipeline test harness rather than staring at screenshots: it replicates the renderer's exact frame-consumption and row-rebuild decisions against a painted mirror, drives randomized editor-shaped traffic (region scrolls, insert/delete lines, alt-screen flips, resizes, viewport scrolling, racing redraws) across 200 seeds, and holds three invariants at every quiet point: the offset never exceeds available history, no content change is left without a wakeup to paint it, and what was painted equals what the grid holds. It found all of the above by itself, prints the exact operation trace when something diverges, and now runs in CI so the next damage bug fails a test instead of leaving glyph leftovers in someone's editor.
0.5.22 (2026-08-12)
- The release that actually shipped 0.5.21: identical fixes, plus the repair of the crates.io publish pipeline that burned the 0.5.21 tag. The new
rio-unicodecrate had its own frozen version number, and a fixed version can only be published once while the release pipeline republishes every workspace member per release; it now rides the shared workspace version like every other published crate, socargo publish --workspacegoes through cleanly on this and every future tag. Along the way the crate lost itsunicode-widthalias: manifests, imports, and the published metadata all sayrio-unicodenow, so the code and the crates.io dependency list finally tell the same story.
0.5.21 (2026-08-12, tag superseded by 0.5.22)
-
Stale glyphs no longer linger until you scroll. Attaching a combining mark, ZWJ continuation, or variation selector to an already-painted cell mutated the cell without recording damage, so the renderer was never told the row changed: in Emacs, NeoTree hover kept showing the previous directory name and stray characters survived until a scroll forced a full repaint. The gap had been latent in the legacy zero-width path for years and became hot when 0.5.20 turned grapheme clustering on by default, since TUI icon fonts lean on exactly those sequences and a chunked redisplay routinely lands an attach in its own damage window. The attach path now marks the row, and a new property test guards the whole bug class: randomized VT streams, with bare continuation codepoints arriving in their own damage windows on purpose, asserting that every row whose content changed is covered by reported damage.
-
Large escape-sequence payloads parse at memory speed. The parser handled OSC, APC, SOS, PM, and DCS passthrough one byte at a time, paying two state dispatches and a push per byte, which is where kitty-graphics images, OSC 52 clipboard writes, and sixel data spent their time. Those states now consume payload spans in bulk: an 8-bytes-per-step boundary scan finds the run up to the next terminator or control byte and appends it in one slice, with the per-byte state machine still deciding every boundary byte, so semantics are unchanged by construction. Measured on 4 MiB payloads: kitty APC 481 MiB/s to 29 GiB/s, OSC 628 MiB/s to 17 GiB/s, sixel DCS 824 MiB/s to 15 GiB/s. A differential test pins the batched paths to the per-byte machine across random chunk splits, the same discipline ghostty uses for its SIMD parser, whose string states remain per-byte.
0.5.20 (2026-08-12)
-
rioterm: Rio's terminal engine, on the web.
librionow compiles to WebAssembly and ships asriotermon npm, with areact-riotermwrapper. It is the same Rust VT core the desktop app runs, parsing your bytes in the browser, with a canvas or DOM renderer selectable per instance, and it is not a JavaScript reimplementation of a terminal:rio-vtandlibriocross-compile towasm32-unknown-unknownunchanged behind a wasm-bindgenRioTermclass, and the browser is handed the transport (a WebSocket to a real shell, an in-page interpreter) instead of a PTY. On byte-identical 120x40 workloads against xterm.js with its WebGL renderer it parses and paints plain text about 3x faster and cold-inits ~1.8x faster, with headless VT parsing 6x faster; the benchmark suite is in the repo. It runs in production in Lovable's admin terminal, and there is a write-up. -
librio: reconnect and search.
Surface::serialize()dumps scrollback and screen as a VT byte stream that reproduces content, SGR styling and OSC 8 hyperlinks when replayed into a same-width terminal. It is the reconnect-restore flow cloud IDEs need, where a dropped socket should come back with the buffer intact.Surface::search()runs a regex over the whole buffer and returns matches in ring-relative coordinates, so a hit stays valid however the viewport is scrolled. Both are exposed on the wasmRioTermand wrapped by rioterm'sserialize(),search(),findNext()andfindPrevious(). -
librio: plain-text links and cursor visibility for renderers.
Surface::url_at()regex-detects a URL (http,https,mailto, and friends) under a pointer cell, resolving a URL that wrapped across rows as one whole link, so a host gets hover-and-click links without an addon and without a per-frame cost; it is hit-test shaped, run only on pointer events.RenderState::cursor_visible()reports when the cursor is hidden, whether by DECTCEM (CSI ?25l) or by a scrolled-back viewport, so a renderer stops painting a phantom caret where the program wanted none. -
librio: a leaner web build, and a chunk-safe injector. Image-codec and glyph-protocol decoding moved behind a
graphicsfeature (on by default for native embedders, off for the web build), which halves the wasm from 2.2 MB to 1.1 MB and cuts cold init roughly in half, since the browser had been compiling png/jpeg/webp/tiff and a font-outline parser that a text terminal never runs. Separately,Surface::inject_output()now keeps its VT parser across calls: an escape sequence split across two writes, which is the norm the moment output arrives over a WebSocket rather than a PTY, now resumes mid-sequence instead of leaking its tail into the grid as literal text.teletypewriteralso retries a transientopenptyfailure (seen when spawning many PTYs at once) and reports the real errno if it still fails. -
The PTY event loop wastes fewer syscalls. Rio inherited alacritty's mio-era loop shape: every source registered edge+oneshot, so every wakeup paid a re-registration syscall to re-arm it, and every read loop paid one extra read just to hear EAGAIN. The PTY fd is now registered level-triggered and re-registered only when write interest actually changes, the control channel sits on plain edge (it is drained to empty on every wakeup, which re-arms it for free), and a read that returns fewer bytes than the buffer holds is trusted to mean the PTY is drained rather than confirmed with another syscall; the call nginx has made for two decades on every non-edge event model, and kitty makes more aggressively still with a single read per poll. Measured against a real PTY the confirmation read was pure waste: macOS hands the loop about 150 bytes per wakeup, so the old loop did exactly twice the reads for the same bytes, and dropping it takes bulk output from 23 to 26 MiB/s with per-wakeup latency down 18%. Two edge cases found by review and now spelled out in the code: the final drain after a child exits still reads to EAGAIN, because there is no next poll behind it to catch leftovers, and an interrupted read says nothing about the fd being drained, so only WouldBlock does.
-
corcovado, Rio's fork of mio 0.6, went on a diet: about 7,700 lines gone. The timer, the Fuchsia backend, the Windows TCP/UDP sample bindings and a directory of tests that were already commented out served nobody; the fork exists to poll a PTY, a signal pipe and a channel. With them wentiovec(unmaintained since 2018),cfg-if 0.1,slab,socket2and thewindowscrate. Migrating to mio 1.x or smol'spollingwas on the table first, and the benchmarks closed it: mio 1.x removed the pollable channel, the user-space readiness the Windows pipes are built on and level-triggered mode outright, and with the loop fixes above corcovado matches or beats both crates on every shape Rio's loop actually runs. The only thing a migration had left to offer was less fork to maintain, and the trim delivered that without one. -
Combining marks finally render. The grid renderer hashed a cell's attached marks into its glyph-cache key but never handed them to the font shaper, so a decomposed
é— aneplus a combining accent, the formlsoutput and git logs are full of — drew as a baree. Marks now shape together with their base on both the CoreText and Swash paths, which meant teaching the glyph-to-cell mapping to use explicit per-cell offsets: the old per-character cursor assumed one char per cell and would have pinned every glyph after a mark to the wrong column (#1854). -
Erasing half a wide character erases the whole character.
write_cellalways repaired a wide pair split by a single-cell overwrite, but the range operations — ECH, DCH, ICH, EL, and ED's partial rows — never did, leaving stranded halves behind: a lead rendering with a live cell inside its right half, orphaned spacers, stale pre-wrap padding dragged into the row by a shift. The repair is ghostty's design (splitCellBoundary): each operation names the exact seams it cuts before mutating, O(1) per seam — a worst-case EL on a 320-column grid costs 61ns against 42ns with no repair at all — and a repaired cell keeps its WRAPLINE bit, so resize-reflow can't mistake a soft wrap for a hard break. Alacritty does none of this; rio now sits with ghostty and xterm (#1854). -
A combining mark typed inside an OSC 8 hyperlink attached itself to every cell of the link. All cells written under one hyperlink share a slot in the grid's extras table, and the mark-attach path mutated that slot in place. Slots are interned by content now — repeated emoji and combining sequences cost one slot total instead of marching the table toward its silent 65,535-slot cliff — which makes shared slots immutable by construction: writers copy, extend, and re-intern, so the marked cell gets its own entry and its neighbors keep theirs. Hyperlink detection stops keying on raw slot ids (a marked cell mid-link legitimately differs now) and compares the link itself; a link left open across an alt-screen switch is re-interned into the alt grid's table instead of dangling a foreign id; and a mark aimed at a color-only blank — whose bits store the background, not an id — is dropped instead of cloning a stranger's slot onto the cell (#1854).
-
One Unicode version for the whole terminal: the new
rio-unicodecrate carries both the width tables and grapheme cluster segmentation, generated from the same Unicode 17 release, ending the skew where cell widths answered to Unicode 16 while string segmentation answered to 17. The width side keeps the exact per-character semantics rio has always shipped — an every-codepoint audit against the old tables pins the difference to 196 codepoints, all genuine 16-to-17 data changes, and fails CI if a regeneration ever drifts further — deliberately rejecting upstream unicode-width's newer semantics (soft hyphens going zero-width, conjoining jamo collapsing) that the tree pinned a fork to avoid. The grapheme side is a pairwise break state machine built for feeding a terminal grid codepoint by codepoint, ghostty's shape, passing all 766 Unicode conformance vectors; it's the substrate for grapheme clustering (mode 2027) if rio goes there (#1854). -
Rio went there: grapheme clusters, opt-in via DEC private mode 2027. A program that enables it (
CSI ? 2027 h, discoverable through DECRQM) gets extended grapheme clusters as the unit of cell layout: a ZWJ emoji like 🧑🌾 occupies one wide cell instead of shattering into per-codepoint cells, flag pairs consume exactly two columns with regional-indicator parity honored, Indic conjuncts join across their linker, and emoji variation selectors flip a cluster's width — VS16 wide, VS15 narrow, judged against the codepoint they actually follow — rather than being blindly attached. The design deviates from ghostty's reset-hooks on purpose: Rio keeps no cross-call segmentation state at all. A no-break sequence accumulates into a single cell, so everything the break rules can look behind at is the previous cell's contents, rebuilt per codepoint fromrio-unicode's conformance-tested machine; cursor movement, clears, scrolling and screen switches invalidate clusters by construction, with no hooks to forget. The hot path gets the treatment from ghostty's devlog-006: a flat per-codepoint class table plus a precomputed 5,832-entry transition table that folds the entire break-rule chain into one indexed byte, generated at first use by driving the reference implementation so it can never drift from the rules it replaces — cutting the mode's worst-case overhead (pure CJK plus emoji, no ASCII in sight) from 3.05x to 1.53x, with the mode off staying bit-identical and cost-free. The rest of the grid keeps up: search feeds every codepoint a cell carries to the regex engine so a decomposed accent or a ZWJ sequence finally matches, reflow and serialization round-trip clusters intact, and embedders read cluster text through new wasm (cluster_text()) and C ABI (rio_render_state_cell_cluster()) channels. It ships on by default, the ghostty path (grapheme-width-method = unicode): a new top-levelgrapheme-clusteringconfig option turns it off for legacy wcwidth layout, every rio-vt consumer can configure its own default (librio exposesset_grapheme_clusteringon the surface, the C ABI and the wasm class), a program's DECSET/DECRST always wins at runtime, and RIS restores the configured default rather than a hardcoded one. On the web it ships in rioterm 0.1.8, whose canvas and DOM renderers now read the full cluster text off flagged cells instead of drawing only the base codepoint (#1857). -
Nix: a binary cache.
nix run github:raphamorim/riono longer means compiling the whole workspace: every merge to main pushes the build to rioterm.cachix.org, and the flake advertises the substituter throughnixConfig, so nix offers to enable it on first use and the build becomes a download (#1829). Two flake-CI repairs landed alongside: FlakeHub cache authentication had been silently disabled by missing OIDC permissions (the action logs told nobody in particular), and the flake build stopped charging every PR push, running on PRs only when they touch what the flake consumes while every merge to main still builds the full tree. Also fixed for flake users building with tests: the context tests were signalling PID 1 inside the nix sandbox, which is the builder itself, killing the build mid-run with no failure output. -
CI costs an order of magnitude less per pull request. A push to a PR branch fired both
pushandpull_requestruns of everything, and each run built three MSYS2 flavors in release mode under full LTO: roughly 130 runner-minutes per push across up to 14 jobs, saturating the account-wide concurrency cap that GitHub applies even to public repos where minutes themselves are free. Pushes now trigger on main only, PRs smoke-test the one MSYS2 flavor upstream recommends (UCRT64, debug profile, cached) with the full three-flavor release matrix moved to the release gate where its LTO coverage belongs, stacked Nix builds cancel instead of piling up behind a contributor's pushes,cargo fmtruns once instead of three times, and CI builds drop line-level debug info so caches stay under the eviction threshold. The result is about 15 minutes across 5 jobs per PR push, with a build-timings report uploaded from every run so a future slowdown is one artifact download to diagnose. -
Wayland: background blur, beyond KDE.
window.blur = truenow works throughext-background-effect-v1, the cross-desktop staging protocol COSMIC and KWin ≥ 6.4 implement, so a translucent Rio gets frosted glass behind it on those compositors instead of only under the KDE-specific blur protocol, which stays as the fallback for older Plasma. The protocol starts every surface with an empty blur region, so Rio sets a full-surface one explicitly and lets the compositor clip it (#1841, by @milkowski). -
Wayland: a compositor that drives key repeat itself no longer crashes Rio.
wl_keyboardv10 lets the compositor take over repeat: it disables client-side repeat withrepeat_info { rate: 0 }, then delivers held keys in a thirdrepeatedkey state, which landed in a_ => unreachable!()arm and aborted the whole process. Repeated keys are now forwarded exactly as the client-side repeat timer forwards them, and unhandled keyboard events log a warning instead of taking the terminal down with them (#1774, by @nikicat). -
Color emoji render correctly from bitmap fonts. Every strike format was pushed through Swash as if it were the same thing, and none of them were: PNG strikes (Noto Color Emoji) decode to straight RGBA that Rio's premultiplied atlas then over-darkened, raw CBDT strikes arrive as premultiplied BGRA that drew with red and blue swapped, and the packed CBDT formats make Swash under-allocate its decode buffer and panic outright. Each path is now handled for what it is: PNG premultiplied after decode, raw strikes channel-swapped and taken only at their exact strike size (resampling premultiplied data is what corrupted them), packed formats skipped before Swash can crash on them. The strike selection walks the font's CBLC table with the same nearest-size logic Swash uses, so the format decision always matches the strike Swash actually renders — and a synthetic-font test suite assembles real CBLC tables byte by byte to prove it, including truncated and lying ones. For the record: cosmic-text, the largest Swash consumer, still has all three bugs (#1843, by @mirsella).
-
macOS: SKK works. Its hiragana mode commits text directly without a preedit — input Rio dropped on the floor — and its mode-switch keys (Ctrl+J,
q) reached the shell as control sequences because the IME consumes them throughselectMode()without any text callback Rio could see. Direct commits are now detected by comparing what the IME inserts against what the key actually says. For the mode switches, Rio borrows the detection ghostty has shipped for over a year: each SKK mode is its own macOS input source, so a key that changes the input source mid-event belongs to the IME and never reaches the shell — and nothing else changes, so IMEs that quietly inspect Ctrl combinations (Chinese, Korean) can't swallow app-bound keys like Ctrl+C, the regression that pattern caused elsewhere. A newkeyboard.forward-to-ime-modifier-maskadditionally decides which modifier combinations go to the IME at all — matched as a subset, so listingctrldoesn't drag Cmd+Ctrl combos along. The default forwards everything, exactly as before (#1845, by @shiena). -
The OSC 9;4 progress bar sits at the top of the window when the tab strip is hidden, instead of floating at the strip's height below nothing. With
hide-if-singlenow the macOS default, a lone tab is exactly when this matters (#1844, by @mirsella). -
navigation.hide-if-singlenow defaults per platform:trueon macOS, where hiding the strip for a lone tab is the native-app feel, andfalseon Linux and Windows, where the strip stays as a centred title. Either value can still be set explicitly, globally or per platform. -
Windows: no flash of blank window at startup. Rio could show the bare native window before the first frame was ready, a white blink that made launch feel slower than it was. The window now stays cloaked (DWM's mechanism for exactly this) until the first frame has rendered, so it appears with content already in place (#1814, by @lalvarezt).
-
An unfocused window shows a hollow cursor. The cursor style decision consulted panel focus but not window focus, so the active panel kept drawing a solid block after you switched apps; it now checks both, giving an unfocused window the same hollow outline an unfocused split gets: steady, not blinking, until focus returns (#1835, by @mirsella).
-
libriobuilds on Windows again.Surface::foreground_process_nameleaned on a process lookup and PTY fields that only exist on Unix, which broke the Windows build the moment it landed. On Windows it now returns an empty name, the same unavailable-result conventionworking_diralready follows there, with the Rust and C APIs unchanged (#1838, by @mirsella). -
The Nix package build works again, and the OOM theory was wrong. Every Nix build died with exit code 129 partway through the test suite, which read as the kernel reclaiming a 7 GB runner; but 129 is SIGHUP, not the OOM killer's SIGKILL, and the death always landed on the context tests. The real cause: a dead context stores
1as its placeholdershell_pid, and dropping it SIGHUPed that pid unconditionally — and in the Nix sandbox the builder shell is PID 1, socargo testkilled its own parent. The kill is now guarded against placeholder pids, the check phase that was briefly skipped as a stopgap (#1828, by @bet4it) is back on, and the rio 0.5.x update in nixpkgs is unblocked (#1842, by @pinpox).
0.5.19 (2026-08-07)
-
Canario, security: a
canario://runlink could show one command in the confirmation and run a different one. Percent-encoded terminal control characters survived into the alert, where they have no glyph to give themselves away, and the approved string was then replayed into the shell as keystrokes:canario://run?cmd=echo+Foo%15lsreads asecho Foolsand runsls, because ^U kills the line the user was just shown. ^P recalls a history entry instead, and the bidi overrides reorder the rendered line without changing a byte of it. Deep-link parameters now reject every Unicode control and format character (categories Cc and Cf, which covers C0, DEL, C1, the bidi overrides and the zero-width formatters), so a link carrying one never opens at all (#1824, reported by @lalvarezt). -
Canario: an approved command is no longer typed into the shell at all, which is the deeper half of that fix. It is handed over at spawn as a single
-cargument, so no part of it is ever read by a line editor;-ikeeps the interactive rc files sourced so aliases and PATH still apply, and a trailing exec leaves the usual interactive shell behind once it finishes. The old "wait 600ms and hope the shell has settled" timer is gone with it. The confirmation now renders the command in a bounded monospaced box, so a long one scrolls rather than pushing its tail out of a dialog that looks fully read, and Return activates nothing (Escape still cancels). Fixed on the way:sendTextmeasured withstrlen, so an embedded NUL silently truncated what was sent, a mismatch between what was displayed and what was transmitted that the paste path shared. -
librio:rio_surface_config_sgainedargsandargs_len, an argv for the spawned program, so an embedder with a command to run can spawn it instead of typing it into the terminal. The fields are appended to the struct, so zero-initialized callers keep working untouched. -
Security issues can now be reported privately, through the repository's Security tab rather than a public issue, and the project has a security policy describing scope and disclosure.
0.5.18 (2026-08-07)
-
Canario: color schemes, picked the way Arc and Zed pick them. ⇧⌘T (or "Change Theme" in the command bar) opens a floating picker with no scrim and no preview pane, because the live window is the preview: arrowing or hovering recolors every terminal instantly, Enter keeps it, Esc or a click outside puts everything back the way it was. Each row is a mini terminal rendered from the scheme's own tokens (a prompt line, ls colors, an error line, a selection run and the 16-color strip with the cursor block), so the colors a swatch can never show (selection and cursor over the real background) are visible before committing. The prebuilt set is the classics: Dracula, Catppuccin, Nord, Solarized, Gruvbox, Tokyo Night, One Half, Rosé Pine, GitHub, Monokai, Snazzy, Everforest, Kanagawa (vendored from the same iTerm2-Color-Schemes exports Ghostty and kitty bundle theirs from), plus Rio's default and Lucario. The choice persists and new, split and restored sessions all start on it.
-
librio:rio_set_colors()swaps the palette that named and indexed cell colors resolve against, at runtime and process-wide; NULL restores Rio's default theme. The render snapshot keeps each cell's original color form and resolves at query time, so a swap re-themes the entire scrollback on the host's next draw with no re-snapshot. Found on the way: the dim-color fallback (2/3 luminance) did its arithmetic in u8 and overflowed for any component of 128 or more (invisible with the default palette the tests exercised, guaranteed with brighter schemes), now widened, with the swap/reset path under test.
0.5.17 (2026-08-06)
-
Canario: input methods actually work now. The in-progress composition (dead keys, Japanese, Chinese, Korean) was tracked but never drawn, so composing was invisible until commit; it now renders at the cursor the way IME-aware apps draw it, an inverted box with a thick underline that slides left when the composition outgrows the row. Option composes characters by default (the macOS convention Terminal.app, iTerm2 and ghostty share), so dead keys and international layouts work out of the box; alt-as-meta remains available through
librio's existing switch. The composition state machine follows ghostty's: a backspace that cancels romaji no longer also deletes terminal characters, committed text arrives as text-only key events rather than raw bytes (alibriopath that existed but encoded nothing, now fixed with a test), bare control characters an input method consumed are never forwarded, arrows that commit Korean input still move the cursor afterwards, and a keystroke that switched keyboard layouts encodes nothing. -
Canario: keys report completely. Repeats are repeats rather than fresh presses, releases are delivered (programs using the kitty keyboard protocol's event types were receiving none), and bare modifier presses are reported in the protocol's report-all mode, with left/right distinguished the way ghostty distinguishes them.
librio's key model gained the nine modifier keys with kitty's assigned codes, encoded only where the protocol says they exist. -
Canario: no more flicker under heavy output. Rendering is paced to the display: PTY wakeups mark the session dirty and a per-view display link performs exactly one grid snapshot and draw per refresh, pausing when idle, so a flood of output can no longer outpace the screen or saturate the main thread with redundant snapshots (
seq 1 200000renders clean in 0.24s). Applications that wrap redraws in synchronized output (ESC[?2026) were already buffered whole by Rio's parser, timeout and all; the pacing covers everything that doesn't. -
Canario: watchers, which are breakpoints for output. Select any text, right-click, "Watch for", and when that text next appears in the terminal's output, the sidebar tab badges with an eye and a hit count, and the Dock asks for attention if Canario is in the background. The scanner diffs each render's visible rows against the previous ones, so re-renders of an unchanged screen never refire, text already on screen when the watcher was created doesn't count, a chatty log is held to one hit per two seconds, and a terminal with no watchers pays nothing. The badge's context menu stops individual watchers or clears the count. iTerm2 has carried this power for a decade as regex Triggers buried in profile preferences; here it's two clicks on the text itself.
-
Canario: picture-in-picture, for panes. Right-click a pane, "Pop Out Panel", and the running pane moves into a small always-on-top panel, the way videos pop out of a browser: watch the deploy from any app, and close the panel (or press Bring Back on the placeholder tile) to slide the pane back into its tab. It is the same live view, not a copy: the PTY, scrollback and selection all come along and come back.
-
Canario: long commands report progress with OSC 9;4 (the ConEmu sequence winget, systemd and a growing list of CLIs emit), and Canario carries it beyond the window: a spinner or determinate ring on the sidebar tab, a live percentage on the Dock icon, and a menu-bar pill that jumps to the reporting terminal when clicked. Error state turns the pill into a warning and the ring red; indeterminate shows a spinner; state 0 clears all three. Ghostty draws these in-window; the point here is that progress follows you out of the app.
librioforwards the reports over the C ABI asRIO_ACTION_PROGRESS(the action struct gained genericdata_a/data_bpayload fields). -
Canario: deep links.
canario://quicktoggles the quick terminal,canario://new?space=Work&cwd=~/apiopens a terminal in the named space at a directory,canario://terminal?title=htopjumps to a session by fuzzy title, andcanario://run?cmd=npm+test&space=Workopens a terminal and runs a command, after a confirmation showing the exact command, because URLs arrive from browsers and other apps and a shell one-liner should never execute on a click alone. Launchers, Shortcuts, other apps and README badges can now drive the terminal. -
Canario: ctrl+click opens the context menu everywhere in a pane, matching right-click. AppKit performs that translation in NSView's default mouse handling, which a terminal's own mouse handling replaces, so it is now done explicitly.
-
librio:rio_render_state_alt_screen()reports whether the alternate screen (full-screen TUIs) is active, so embedders can gate prompt-output affordances away from applications that draw their own UI. -
rio-vt: the PTY driver is a feature now. Embedders that bring their own PTY layer and use rio-vt purely as a VT state machine can setdefault-features = falseand dropteletypewriter,corcovadoand 19 transitive dependencies, several of them unmaintained 2018-era crates that were a hard question for anyone auditing their tree. Theptyfeature stays in the default set, so nothing changes for Rio, Canario, or existing embedders (#1819, reported by @gold-silver-copper). -
macOS: local network access works from programs running inside Rio and Canario. macOS attributes local-network traffic from child processes (
ssh host.local,ncto a LAN address, mDNS lookups) to the responsible terminal application, and withoutNSLocalNetworkUsageDescriptionin the app's metadata the permission prompt never appears and connections quietly fail, and the terminal doesn't even show up under Privacy & Security → Local Network to allow by hand. Both apps now declare it, so the prompt appears the first time a program reaches for the local network (#1821, by @Goooyi).
0.5.16 (2026-08-06)
-
Canario: images render in the terminal via the kitty graphics protocol.
chafa -f kitty,kitten icat, yazi's previews and every other kitty-speaking tool now draw real pixels instead of character art: chunked transmissions reassemble, RGB and RGBA payloads both decode, retransmissions of the same image id refresh in place, and placements are anchored to the scrollback like every kitty terminal anchors them, so an image scrolls away with its prompt and comes back when you scroll up. Layering follows the protocol's z-index rules the way ghostty's renderer splits them: below cell backgrounds, below text (a chart can sit under its own axis labels), or above everything. -
Canario: virtual placements (
U=1, the Unicode-placeholder modekitten icatuses under multiplexers) work too. The renderer collapses runs of U+10EEEE placeholder cells, whose foreground color and combining diacritics say which image and which slice each cell shows, into image draws, with the aspect-fit and centering rules matching kitty's and ghostty's. -
Canario: images are objects, not just pixels. Click one and it opens in an Image Peek: an Arc-style lightbox that springs out of the cell rect, dims the window, and pinch-zooms up to 12x, with Esc or Space to close and arrow keys to walk every image in the buffer. Inside the peek, Live Text runs on the image (the same interface Photos uses), so text inside a matplotlib chart or a screenshot of an error is selectable and copyable, and QR codes a CLI prints are clickable. Right-click an image in the terminal for Copy Image, Save to Downloads, Open in Preview and Share, or press and drag it straight out into Finder, Slack or Figma as a PNG, the way images drag out of Messages.
-
librio: the kitty pipeline is exposed over the C ABI for any embedder drawing its own cells:rio_render_state_kitty_count()andrio_render_state_kitty_placement()iterate placements as viewport-resolved pixel rectangles (z-sorted, with normalized source rects for crops),rio_render_state_kitty_image_info()carries dimensions plus a change stamp so decoded bitmaps can be cached until a retransmission, andrio_render_state_kitty_image_rgba()copies pixels out as tightly-packed RGBA. Virtual placeholder runs surface through the same iterator, so an embedder that draws direct placements getsicatunder tmux for free. -
librio: two placement bugs found on the way. Surfaces created through the C API reported zero cell dimensions to the graphics subsystem, which silently dropped every kitty placement (the reason no embedder had images until now); cell metrics now derive from the surface's pixel size. And placement rows are absolute counting lines evicted from the scrollback ring, so once a long-lived session filled its scrollback, every image quietly culled as off-screen; the viewport math now accounts for evicted lines, with a regression test that forces eviction.
0.5.15 (2026-08-06)
-
Canario: a settings window (⌘,), in the shape Arc uses: native preference tabs over dark grouped sections. The Text tab holds the terminal font: a size slider and every monospace family installed on the machine, each row rendered in its own typeface above a live sample, applied to running terminals as you click and persisted across launches. Families are found by asking each font whether it is fixed-pitch, so the list is exactly what a terminal can use.
-
Canario: the Appearance tab makes the window's colors yours: window, text, selection and focused-panel border each get a picker, applied live and persisted. Text is picked once and the interface derives its opacity tiers from it, so a dark window with light text stays legible everywhere without adjusting five shades by hand. The preset swatches (salmon, blush, rosewood, cocoa, ultramarine, from the chrome study) each carry a complete four-color palette rather than just a window color, so one click can't strand black text on a dark window.
-
Canario: Nerd Font icons render out of the box, sized and positioned like a patched font. Two things had to be true at once. First, the glyphs have to exist: the symbols-only Nerd Font is embedded in
librioitself, the way libghostty embeds it, and Canario cascades to it from the terminal font, so Powerline separators, Font Awesome and Material icons resolve on a machine with no patched font installed and no font file in the app bundle. Second, they have to be placed correctly: raw icon glyphs are designed against wildly different boxes, which is what the Nerd Fonts patcher's per-glyph scaling rules are for. Rio carries a port of that table (by way of ghostty's generated version); Canario now applies it at render time, so Powerline triangles stretch to the full cell and butt seamlessly against their coloured background, icons centre on the patcher's icon height, and an icon with a free cell beside it may span two. Private-use glyphs the table doesn't know are fitted to their cells so nothing bleeds into the neighbour. -
librio: two additions for embedders drawing their own cells.rio_symbols_nerd_font()returns the embedded symbols-only Nerd Font as raw TTF bytes, so icon fallback needs no file management on the embedder's side. The Nerd Font constraint table moved from sugarloaf intorio-fonts, a new dependency-free crate for font assets and glyph placement rules (the symbols font lives there too, behind asymbols-nerd-fontfeature so only renderers that want the ~2 MB opt in), and is exposed asrio_nerd_constrain(): pass a codepoint and the glyph's measured bounding box, get back the box the patcher's rules would produce; the maths stays in one place, so any embedder's renderer lines up with Rio and ghostty by construction. One convention to know: boxes are y-up from the cell bottom, ghostty's coordinate space, so CoreText-style baseline-relative measurements shift by the descent on the way in and out.
0.5.14 (2026-08-05)
-
Canario updates itself. A quiet pill appears beside the sidebar toggle when a new release is out (GitHub Releases is the feed; the notarized
Canario.dmgper tag is the artifact); its dropdown offers installing or skipping that version. Installing downloads the image, swaps the app bundle in place and relaunches, with progress shown in the pill and a fall-back to revealing the image in Finder if any step refuses. Checks run shortly after launch and at most daily, plus a "Check for Updates…" menu item that also reports "up to date"; development builds never check. Sparkle remains the eventual destination, but this covers the same user story with no new dependencies while the release pipeline already publishes everything the updater needs. -
Canario: dragging a selection past the top or bottom edge now scrolls the view and keeps extending, ghostty's selection-scroll-tick behavior: speed grows with how far past the edge the pointer sits, and the anchor stays put because librio stores selections in absolute grid coordinates.
-
Canario: the command palette is a real fuzzy finder now. Every whitespace-separated token must match, the space or parent name is part of the haystack (so "wrk" narrows to the Work space), scoring rewards word starts, prefixes and consecutive runs, and the matched characters light up in the results so it's visible why a row is there.
0.5.13 (2026-08-05)
-
librio: shells now spawn with a TERM that actually resolves. The child inherited the host process's environment, which for an app launched from Finder contains no TERM at all, and for one launched from another terminal contains whatever that terminal used, such asrioon a machine where rio's terminfo was never installed. Either way programs that query terminfo got nothing back, which showed up as prompt frameworks drawing fragments of their glyphs, and ssh forwarding a TERM the remote host answered with "unknown terminal type". TERM is now resolved at spawn the way Rio resolves it:xterm-riowhen that terminfo is installed,riowhen only the older entry is, andxterm-256colorotherwise, which is the case for a fresh Canario install and is known to every local terminfo database and every ssh host.COLORTERM=truecolorrides along. -
Canario: shells receive
TERM_PROGRAM=canarioandTERM_PROGRAM_VERSION, the same convention Rio follows, so shell integrations can tell which frontend they are running in.
0.5.12 (2026-08-05)
-
Canario: the cursor no longer floats over whichever history row happens to occupy its grid position while the view is scrolled up. It is drawn at its viewport-relative position, sliding down as you scroll and not drawn at all once it leaves the viewport, which is where Ghostty draws the line too.
libriogainedrio_render_state_display_offset()so any renderer can make the same call. -
librio: input snaps a scrolled view back to the live screen and drops any selection, the scroll-to-bottom-on-input behaviour of every terminal. It lives in the one path all keys, text and paste go through, so it only fires when a key actually produced PTY bytes (Ghostty gates its equivalent the same way), and every embedder gets it rather than each frontend reimplementing it. -
Canario: ⌘W closes the focused panel rather than the whole terminal, falling back to closing the terminal when the panel is the last one, and to the window when nothing is open. ⇧⌘W closes the terminal with all its splits.
0.5.11 (2026-08-05)
-
Canario, an experimental macOS frontend built on
librio, ships from this release asCanario.dmg. It borrows its workflow from browsers: terminals live in coloured spaces with ⌘1 to ⌘9 to jump between them, ⌘K opens a command bar that finds any terminal or pane by title and runs app actions, hovering a tab or pane in the sidebar shows a live preview, ⌥⌘T summons a floating quick terminal over whatever app is frontmost, new shells can be routed into spaces by working directory, and quitting asks first. Sessions restore in full: the sidebar tree, splits, scrollback and each pane's working directory. -
librio: cells that carry only a background colour (the fills erase-to-end-of-line leaves behind, htop's header bar, blank lines afterclear) resolved their colour through the style table, misreading the inline colour bits as a style id, so erase fills rendered with the wrong colour or none. The snapshot accessors now decode them as the bg-only cells they are. The same cells previously leaked NULs into persisted scrollback text, which now records them as trimmable spaces. -
librio:Surface::working_dir()no longer requires OSC 7. When the shell has not reported a directory, the kernel's view of the foreground process's cwd is used instead (proc_pidinfo on macOS, /proc elsewhere, via the same helper Rio already used for spawning daemons), so session restore and directory-based routing work with entirely unconfigured shells. -
librio: named and low-indexed colours resolve from Rio's default theme (rio-vt'sColors::default()) rather than a hardcoded xterm palette, so an embedder's terminal matches Rio's look out of the box, pink cursor included, and the two can never drift apart. Everything downstream reads through one resolved table, which is where theme-file loading will plug in. -
The tab strip stays visible with a single tab, drawn as the tab title centred with nothing behind it, and
navigation.hide-if-singledefaults tofalseto match. A lone tab has nothing to be distinguished from, so the tab shape carried no information worth the space, and dropping it hands the title the width of the window rather than one tab slot, which is where long titles used to lose their ends. A custom tab colour, whether from colour automation or the picker, has no fill left to sit in and colours the title text instead. Setnavigation.hide-if-single = trueto keep the strip hidden on a single tab as before (#1817). -
With a single tab, right-clicking anywhere on the strip opens the colour picker for it. The whole strip belongs to that tab now that its title is centred, where before only the first tab slot responded.
0.5.10 (2026-08-04)
-
Windows: opening a hint could run arbitrary commands. The default hint launched
cmd /c startwith the matched text appended as an argument, and Rust quotes an argument only when it contains whitespace or a quote, so cmd metacharacters in the match reached cmd's parser as syntax: everything after an&in a URL ran as its own command. Nothing needed to be configured for this. The shipped hint rule covers OSC 8 hyperlinks, binds ctrl+shift+O, and enables mouse hints, so the requirements were that text arrived in the terminal (catof a file,curloutput, a log tail, an ssh banner) and that it was opened once. With OSC 8 the visible link text is chosen by whoever sent it, so it need not resemble what runs. Matches now go to the Windows default handler throughShellExecuteW, which takes the target as a single string rather than a command line, andopenandxdg-openreceive it as one argument with no shell involved. Nothing changes on macOS or Linux, which were never affected (#1816, reported by @lalvarezt in #1811). -
Windows: a hint that fails to open now says so in the log.
ShellExecuteWreports failure in its return value, which was discarded, so the only symptom was a click that did nothing at all.
0.5.9 (2026-08-04)
-
Applications that narrow the scroll region no longer lose rows from the screen. Rio derived the visible viewport from the DECSTBM scroll region rather than the screen height, so once vim, less, htop, top, tmux or man narrowed it, the snapshot the renderer draws from was short by however many rows the region excluded, while the terminal kept reporting its full height. The usual
CSI 1;Nrshape showed up as the bottom row or two going stale; a region narrowed at the top (CSI 2;8r) shifted the whole viewport up. The region bounds where scrolling happens, not what is displayed, which is how alacritty and Ghostty both draw the line (#1805, reported by ratty). -
X10 mouse reporting (
CSI ? 9 h) is now supported. Mode 9 was parsed as an unknown private mode and dropped, so a program that asked for it received nothing and had no way to find out why: DECRQM answered 0, not recognized. It joins 1000, 1002 and 1003 as a fourth protocol and reports what X10 defines and no more, meaning presses of the left, middle and right buttons, with no release, no motion and no modifier bits in the button code. Setting 1005 or 1006 alongside it still selects the UTF-8 or SGR wire format, since the format and the event mode are tracked separately (#1809, reported by ratty). -
Resetting a mouse protocol other than the one in use no longer leaves mouse reporting on. The four protocols are one setting, so setting any of them already cleared the others, but a reset cleared only its own bit: after
CSI ? 9 h, a program that sentCSI ? 1000 lto stop reporting kept receiving reports. A reset now turns reporting off whichever of the four it names, since there is no protocol underneath to fall back to, which is how Ghostty models it. Sequences that reset the protocol they set, which is what programs actually send, behave as before. -
rio-vt: a grid one column wide no longer panics or hangs on double-width characters. A wide glyph needs a second cell for its trailing spacer, and on one column there is never one, nor can the usual escape of wrapping to make room help, because the new row's column 0 is also its last column. Writing你wrote the spacer past the end of the row and panicked, promoting an already-written cell with a variation selector did the same, and shrinking a row that already held a wide character displaced it into the next row where it landed at column 0 and was displaced again on every iteration, growing the row buffer without bound. That last one hangs rather than crashing, so it was the worse of the two. Writing and reflow now both drop the glyph for a blank narrow cell and a VS16 promotion is declined, which is what Ghostty settled on for the same degenerate size. Embedders are entitled to ask for such a grid: drag-resize and tiling layouts produce them transiently, and nothing announces that the floor is two columns (#1807, reported by ratty). -
rio-vt:EventListener::event()is gone. It was the trait's one required method, yet nothing in the tree called it and every implementation returned(None, false), so the only method an embedder was obliged to write was the one that did nothing. Every other method on the trait already had a default. Implementors should delete their own override, which is the whole migration (#1808, reported by ratty). -
rio-vt: three accessors for embedders that encode their own key events or read cells directly.keyboard_mode()returns the active kitty keyboard flags, the same byte the terminal reports to the application, instead of every embedder rebuilding it fromModebits and inheriting a bit order that drifts. xterm'smodifyOtherKeys(CSI > 4 ; n m) is now parsed and readable throughmodify_other_keys(), where before it had no mode bit and no handler, leaving embedders to scan raw PTY bytes outside the parser for it.Grid::cell_text()yields a cell's base character followed by its zero-width marks, sinceSquare::c()returns only the base and silently drops combining accents, ZWJ joiners and variation selectors.
0.5.8 (2026-08-04)
-
rio-vtre-exportsteletypewriterandcorcovado, so an embedder that drives the PTY loop no longer has to declare them itself.Machineis generic over a teletypewriter trait and hands back a corcovado channel, which previously forced consumers to name both crates in their own manifest and keep those versions in lockstep with rio-vt's, or get type errors that read asexpected Sender<Msg>, found Sender<Msg>. They are now reachable asrio_vt::teletypewriterandrio_vt::corcovado. -
rio-vtowns its terminal size type.Msg::Resize,RioEvent::TextAreaSizeRequestandOnResizecarriedteletypewriter::WinsizeBuilder, so anything touching the event model named the PTY crate's type for fouru16s; they now carryrio_vt::event::WindowSizeand the PTY driver converts at the one place it callsset_winsize(#1802). Together with the re-exports, an embedder that supplies its own PTY needsrio-vtas its only rio dependency.
0.5.7 (2026-08-03)
-
OSC 7 working directories with characters outside
[A-Za-z0-9/._-]now resolve correctly. Shells percent-encode the path they report (that is whatvte-urlencode-cwdand its equivalents are for), but Rio read it back through a URL parser whosepath()hands the encoding straight through, so/home/My Filesarrived as/home/My%20Filesand anything downstream of the reported directory (the title, opening a new tab in the same place) was working from a path that did not exist. The path is now decoded, with a malformed escape passed through literally rather than dropping the directory over one stray%. -
OSC 7 payloads that are not
file://are no longer accepted. The URL parser took whatever path came back for any scheme, soOSC 7 ; http://elsewhere/tmpwould move Rio's idea of the working directory. Both foot and Ghostty require thefilescheme; Rio now does too. -
A shell on the far side of an ssh session can no longer set the local working directory. Anything at the other end of the PTY can emit OSC 7, and Rio applied it unconditionally, so a remote prompt would report a directory that only exists on the remote machine. The host is now checked against this machine's hostname, accepting
localhostand the empty host thatfile://$PWDproduces (RFC 8089 defines that as the local machine, and rejecting it would break a common shell setup). A refused payload is logged with the host so a working directory that stops updating can be diagnosed rather than guessed at. This follows what foot and Ghostty already do; Ghostty's own note calls validating the host the best practice terminals follow. -
Vi mode gained the
{and}paragraph motions, which skip any blank lines under the cursor and then run to the far side of the paragraph they land in. A line of spaces or tabs delimits a paragraph the same way an untouched one does, matching the other motions. -
macOS: a shell you configure yourself with
shell.programis now started directly rather than through/usr/bin/login. Rio wrapped every spawn, so a named program collected a utmp entry and aLast loginbanner it never asked for. Only the default shell, meaning noshell.programset, which is what Rio ships with, still goes throughloginfor its login-session environment, so a default configuration behaves exactly as before. Alacritty draws the line in the same place. -
shell.programis now optional rather than an empty string standing in for "use my default shell"; an existingprogram = ""in a config keeps working and still means the default. -
A command that writes and exits in the same breath no longer loses its last chunk of output. The PTY reader broke out of its loop as soon as the child-exit event arrived, which races the final readable event, so the tail of a short-lived command could be dropped before it was parsed. The PTY is now drained once more after the child exits.
-
rio-vtis a little over a third smaller: 84 crates to 54.urlaccounted for 29 of them: it pulledidna, the ICU normalizer and collections,zerovec,yokeand a handful of proc-macro crates that also serialize the build, all to parse the one URL the terminal core ever looks at.bytemuckandlazy_staticwere declared but never referenced anywhere in the crate. -
rio-vt:ChildEvent::Exitednow carries the child's raw wait status (waitpidon unix,GetExitCodeProcesson Windows) andMachineforwards it asRioEvent::ChildExited, so an embedder can report the exit code of whatever it ran.create_pty_with_spawnandcreate_ptytake an optional set of environment variables to apply on top of the inherited environment, and "no program configured" is nowNoneinstead of an empty string across the config type and all threecreate_ptyentry points. -
rio-vt: the child's signal mask is reset beforeexec. Ignored signal dispositions were already reset, but a blocked mask survivesexectoo, so a shell spawned from a thread that hadSIGINTblocked came up unable to see ctrl+c. Rio spawns from the main thread and was unaffected; embedders that build their terminal off-thread were not.
0.5.6 (2026-08-03)
-
macOS: waking from sleep no longer leaves the font, grid, or scale wrong. Rio read the display scale once at window creation and then relied on a single AppKit notification to learn about changes, but wake sequences rebuild the backing store without the numeric scale changing, so nothing ever fired. The scale is now re-checked at cheap checkpoints (window focus, un-occlusion, screen changes, and a new app-level display-reconfiguration observer that sweeps every window), the Metal layer's
contentsScaleis re-asserted on every rescale instead of trusting its creation-time value, and the first frame after wake (which can fail to acquire a drawable) is retried instead of silently dropped (closes #1506). Idle terminals also repaint immediately when the window becomes visible again, rather than waiting for shell output (#1792). -
Switching to a tab that wasn't visible no longer shows glyphs at a stale size after a DPI change. Background tabs always received the new dimensions, but nothing forced their rendered cells to rebuild: a scale change now invalidates every pane in every tab, tab switches reliably trigger a full refresh (the change detector compared layout node ids across tabs' separate layout trees, which collide by construction), and per-pane events (damage marks, titles, color requests) now reach panes in background tabs instead of being dropped until that pane's own shell produced output.
-
Split paddings, gaps, and divider hit-boxes now follow the current display scale; they previously kept the DPI of the display the tab was created on.
0.5.5 (2026-08-01)
-
Fixed typing echo in synchronized-output TUIs arriving ~150-200 ms late through Windows ConPTY. ConPTY coalesces output, so a frame's begin/end synchronized-update pair (mode 2026) often arrives inside one chunk; the begin armed Rio's 150 ms timeout but the inline end never disarmed it, so every following frame waited out the timer. An inline end now disarms the timeout, and replaying a buffered update re-arms it when a new begin is still pending (closes #1753: thanks to @cmoron for the original diagnosis and fix in #1754, ported to
rio-vtby @marc2332 in #1788, landed via #1789). -
rio-vt: synchronized updates whose 150 ms deadline has passed now flush on the nextadvance()call. Rio's event loop already flushed at the deadline, but embedders that drive the processor straight from a read loop had no timeout driver at all: a client that armed mode 2026 and stalled could freeze their screen until 2 MB of output accumulated. The latency cap now works out of the box for every embedder.
0.5.4 (2026-08-01)
rio-vt: inserting a sixel/iTerm2 image with unset cell dimensions no longer panics. Headless embedders never report a cell size, so arbitrary input containing image sequences could hit astep_by(0)panic in the row-fill loop; it is now a no-op, matching the existing guard on the kitty placement path. Found by atuin's property tests during its vt100 →rio-vtmigration.
0.5.3 (2026-07-31)
-
The terminal engine (
rio-vt) is substantially faster across the board. Plain text and scrolling-heavy output parse ~2.7x faster (865 → 2340 MiB/s on plain ASCII, 266 → 772 MiB/s on scroll-dominated streams), CJK and emoji text 3x (243 → 726 MiB/s), color-change-heavy streams 1.6x, and full-screen TUI redraws 1.6x. Under the hood: scrolling no longer pays per-row dirty and damage bookkeeping (a full-screen scroll marks damage once), recycled rows reset only their occupied cells, printable runs and CSI parameters are scanned a word at a time instead of a byte at a time, SGR dispatch no longer heap-allocates per sequence, wide characters are written as bulk cell pairs the way ASCII runs already were, UTF-8 decodes in large chunks instead of per-fragment, and the character width table covers emoji directly. Measured with rio-vt-benchmark. -
rio-vtnow exposes its VT parser and thePerformtrait, so embedders can drive the escape-sequence parser with their own handler instead of the built-in grid. TheHandlertrait also gained a providedinput_ascii_strmethod that carries the parser's printable-ASCII guarantee, letting implementations skip revalidating the bytes. -
macOS: quake mode now opens with the right size and position on setups with mixed-DPI monitors. The window geometry was computed in physical pixels for the monitor under the cursor but applied using the window's own backing scale, so the dropdown came out mis-sized when the two differed; it is now converted through the target monitor's scale factor.
0.5.2 (2026-07-28)
- Maintenance release fixing the release pipeline: the
rio-vtcrate publish and the macOS dmg artifact were both missing from the 0.5.1 release.
0.5.1 (2026-07-28)
-
Windows: resizing the window while the terminal sat idle could leave the newly exposed area unpainted (the desktop showed through behind Rio) until the next keystroke or output. A resize reflows the grid, but presenting a frame was gated on terminal damage, so an idle resize produced no repaint into the freshly reconfigured swapchain; the resize path now marks the grid dirty so it always presents (closes #1773, and the resize symptom in #1759).
-
The bundled
corcovadoevent-loop crate now usessocket2in place of the unmaintainednet2, clearing the RUSTSEC-2020-0016 advisory for every project that depends onrio-vtorteletypewriter.
0.5.0 (2026-07-27)
-
Rio's terminal core is now an embeddable library, split out of the app.
rio-vtis a standalone, dependency-light Rust crate: the VT state machine, ANSI/escape parser, grid with scrollback, selection, search, PTY driver, and the sixel / Kitty / iTerm2 image protocols, with no renderer, GPU, or font-shaping code, so building it with no features is just the terminal.libriowraps that same core behind a C ABI for Swift, C, and any language that speaks C, shipped as aRioKit.xcframeworkplus a barelibrio.a+librio.hon each release rather than a published crate. Rio's own frontend and other products now run the same engine;rio-vtis already in production at Lovable. Full write-up in the announcement post. -
Glyph Protocol registrations accept a
widthparameter again (1or2), honored purely at render time: a wide glyph paints across two cells while the codepoint's logical width stays at one cell (itswcwidth), so cursor position, wrapping and selection never desync from width-unaware applications like shells and line editors. Authors of wide glyphs emit a trailing space so the overflow lands on an empty cell. Registrations and clears now also repaint cells already showing the codepoint, and glyph rasterization is hardened against hostile payloads (a bounding-box contain guard plus a hard raster dimension ceiling make degenerateupmvalues harmless). This settles #1649 by keepingwidthin the spec at render level only (#1650). -
Fixed the mouse wheel needing two notches per scrolled line with notched mice: wheel ticks were converted to pixels with the font size but consumed in cell-height units, so a single notch floored to zero lines. One notch is now exactly one line before the configured
scroll.multiplier, so the default scrolls the conventional three lines per notch (closes #1350). -
macOS: clicking the dock icon while every Rio window is minimized now restores and focuses one, instead of doing nothing (closes #1151).
-
Fixed a stale selection surviving panel switches: clicking into an unfocused split never reached the click handler that resets selections, so the next drag in that panel extended a leftover anchor instead of starting fresh (closes #1638).
-
Fixed
copy-on-selectsilently doing nothing when a selection ends on top of a hyperlink or hint: the hint fired first and its early return skipped the copy. Finishing a selection now copies it and no longer activates whatever sits under the release point, so sweeping a selection across a URL doesn't open it; plain clicks trigger hints exactly as before (closes #1494). -
Hints rules now accept the TOML shapes the docs always showed.
[hints.rules.action]withcommand = "open"parses (it previously failed with "missing field action" and silently reverted the whole[hints]table to defaults), and both keys can be written inline on the rule:action = "Copy"orcommand = { program = "code", args = ["--goto"] }. Misconfigured rules produce a clear error message (closes #1407, #1618). -
Fixed dead ctrl+c and ctrl+\ in shells when Rio was launched as a background job (
rio &from a script, some desktop launchers): ignored signal dispositions survive exec and the fork pty child never reset them. The child now resets the full set before exec, which also restores defaultSIGPIPEhandling (the Rust runtime ignores it in the parent), fixing pipeline semantics likeyes | headfor every shell spawned through the default Linux/BSD fork path (closes #1120). -
Windows: hyperlinks open through
ShellExecuteWinstead ofcmd /c start, whose argument re-quoting corrupted URLs (https://becametps://) or made clicks silently do nothing (closes #1457, #1278). -
OSC 52 clipboard support is now advertised in the primary device attributes response, so applications that probe DA1 before enabling remote clipboard writes (tcell-based tools over ssh, for example) will use it (closes #1398).
0.4.12
-
Quake mode: bind
ToggleQuakeand a dropdown terminal slides in from the top of the monitor under your cursor. The binding also works as a system wide hotkey while Rio is unfocused (no accessibility permission needed on macOS), hiding it restores focus to the app you were in, and the size is configurable viawindow.quake-width-percentageandwindow.quake-height-percentage. Binding changes live reload (closes #89).[bindings]keys = [{ key = "'", with = "super", action = "ToggleQuake" }] -
Shell integration: OSC 133 semantic prompt zones are now tracked (closes #975), with two new binding actions,
ScrollToPrevPromptandScrollToNextPrompt, that jump between shell prompts in the scrollback. OSC 1337SetUserVaris parsed and stored per terminal (closes #976); these sequences were previously dropped by the image protocol parser.[bindings]keys = [{ key = "up", with = "super | shift", action = "ScrollToPrevPrompt" },{ key = "down", with = "super | shift", action = "ScrollToNextPrompt" },] -
Sixel and iTerm2 inline images are back (broken across 0.4.x, closes #1591), rebuilt so images behave as grid content: they scroll with the text including inside scroll regions, are clipped by characters printed over them and by erase/delete sequences, survive in scrollback until their rows scroll off, and stay inside their split panel. Cursor movement after an image follows each protocol: sixel lands on the image's last row (with mode 8452 and DECSDM honored), iTerm2 moves right of the image and supports
doNotMoveCursor. -
Kitty graphics protocol fixes: images no longer drift once scrollback saturates, they expire when their rows leave scrollback instead of lingering forever, deletions repaint immediately, and images no longer bleed across split panel borders. Images also render on the CPU fallback renderer now, and GPU image textures are bounded by a least recently used budget instead of growing without limit.
-
Fixed yazi image previews collapsing into a tiny single-cell thumbnail: kitty virtual placements transmitted without the
c=/r=grid parameters (what yazi's kitty protocol driver emits) now imply their grid from the image and cell size, instead of squeezing the whole image into a 1×1 placement box (#1314, #1530). -
Fixed
[shell] argsbeing silently dropped on Linux and BSD: the fork pty path (the default there viause-fork = true) never passed the configured arguments to the shell. This also fixesOpenConfigEditorlaunching the editor without the config file (closes #1016, #1423). -
Fixed two crashes: the rich text atlas textures now respect the GPU's texture size limit instead of hardcoding 4096 (startup crash on Raspberry Pi class GPUs, closes #1641), and the grid iterator no longer panics on positions stale relative to the live grid, such as during tiling window manager resizes (closes #1713).
-
Fixed the tab bar overlapping the last terminal lines after opening a tab (and the leftover gap after closing back to one tab). Margin changes from the tab bar appearing or disappearing never reached the layout engine until a window resize; they now trigger a full relayout of every tab (closes #1495, #1528).
-
Tabs grow up to 240px wide (was 180px) so titles crop later, and the cap is now configurable via
navigation.max-tab-width. -
Dropped file paths are now shell escaped: paths containing spaces, parentheses, quotes or other shell metacharacters get each sensitive character prefixed with a backslash instead of being pasted raw (closes #1730).
-
Fixed
[shell] argscontaining spaces being word split on macOS: custom commands are now passed directly tologin(1)instead of going through an intermediate shell string, so arguments likeargs = ["-c", "tmux attach || tmux"]survive intact.
0.4.11
- Font caches and glyph atlases are now cleared when the font library changes. Stale entries could serve the old font's shaping, metrics and bitmaps after a config reload, or crash on font ids past the new library's length (closes #1639, #1110, #818).
- Glyph atlases recover when full: instead of silently dropping characters once the atlas hit its size limit, it is cleared and every row re-emitted against the fresh atlas.
- Fonts inside TrueType collections (.ttc) load the right face. The face index was ignored when loading configured fonts, so families like Sarasa rendered whichever face sat first in the file (closes #1302).
- The configured bold/italic/bold-italic font wins over weight metadata, so families that ship their bold at weight 600 (Nerd Font patches, Operator Mono) no longer render bold cells with the regular face or stack faux bold on a real bold face.
fonts.featuresworks again and now live reloads. Features reach both shapers (swash and CoreText), and can be disabled with a-prefix:features = ["-calt", "-liga"]turns ligatures off (closes #1125, #1032, #1258).fonts.hintingnow applies to the terminal grid; it was previously hardcoded on.- Per-slot font
weightis back:[fonts.bold] weight = 600steers face selection and pins thewghtaxis on variable fonts, which also fixes variable-font weights never being applied on Linux and Windows (closes #1577). - Font families are matched by any of their names, so CJK fonts like "Source Han Mono SC" or "LXGW WenKai Mono" are found by their English alias, not only the localized name listed first in the file (closes #1466, thanks @qiuzhiqian for the analysis).
- ctrl+digit and ctrl+punctuation combos reach the terminal: Rio computes the C0 control byte itself (ctrl+6 sends 0x1E, ctrl+/ sends 0x1F, same table kitty uses) instead of relying on inconsistent platform behavior. The kitty keyboard protocol encoding is untouched (closes #863, #1328).
[bindings]edits live reload instead of requiring a new window, unknown binding actions are rejected loudly instead of silently unbinding the default, andf1throughf20can be used as binding keys (plusenter,escapeandbackspacealiases).- Fixed font size changing by two steps per keypress: the increase/decrease defaults were registered twice on every platform.
- Updated
swashto 0.2.10, which fixes a hinting cache regression that rebuilt hinting state per glyph.
0.4.10
- New
SelectAllaction: selects the entire terminal content, including the scrollback history, so it can be copied. Bound toCommand + Aon macOS by default, and available on every platform for custom key bindings viaaction = "SelectAll". - Fixed hint label rendering: keyboard hint labels (hyperlink hints) are now drawn as proper grid overlays using the configured hint foreground/background colors, with the leading character of each label highlighted.
- Tab strip refresh: tab island backgrounds are now derived automatically from the window background color.
colors.tabsandcolors.tabs-activenow set the inactive and active tab title colors, and thebar,tab-border,tabs-foreground,tabs-active-foregroundandtabs-active-highlightcolor options were removed.
0.4.9
- Updated
wgputo 30.0.0 and thelibrashaderfilter chain to 0.12 (the wgpu path used for RetroArch shaders on Windows/WASM and behind thewgpufeature flag elsewhere). librashader 0.12 brings a smarter framebuffer pool that only allocates intermediate framebuffers for the shader passes that actually need them.
0.4.8
- Adaptive theme on Linux: Rio now follows the system light/dark preference on Wayland and X11. With
adaptive-themeconfigured, Rio watches the XDG Desktop Portalcolor-schemesetting (the same one Firefox and GNOME/KDE use) and switches between your light and dark themes live when the system appearance changes, no restart required. This previously worked only on macOS and Windows (#408; based on #1358 by @pinpox).
0.4.7
- Tabs can now be reordered by dragging them along the tab strip. Displaced tabs slide into place with a spring animation, and a released tab settles into its new slot.
- Font fallback discovery now works on Linux and Windows: glyphs missing from your primary font (Nerd Font icons, CJK, emoji, and box/symbol characters) are discovered from installed system fonts (fontconfig on Linux, font-kit on Windows) and registered on the fly, instead of rendering as tofu (missing-glyph boxes). Previously only macOS did this. (#1630 by @nikicat, #1642 by @pinpox; closes #1015).
- A tab's custom background color now follows the tab when tabs are reordered or closed, instead of staying pinned to a slot and painting under the wrong tab. The color picker also closes when its tab is closed.
- New tabs show
~as a placeholder title until the running program sets one. - The smooth (trail) cursor no longer animates between tabs and panels: switching tab or split places the cursor directly instead of sliding a trail across the screen.
0.4.6
- Box-drawing and related symbols render again. Box-drawing, block elements, braille, powerline separators, geometric shapes, and legacy computing symbols are now drawn as crisp, pixel-aligned atlas sprites that tile seamlessly at any font size and scale factor: they no longer fall back to the font's (often gappy) glyphs. These had been dropped during the v0.4.x grid rewrite.
- Kitty graphics: the
X=/Y=sub-cell pixel offset is now applied when placing images (#1645 by @floens): the parser already understood it, but placements were pinned to the cell boundary. Offsets are clamped to the cell box per the kitty spec, and an offset that spills the image into an extra row/column is now accounted for in cursor movement and row occupation. - Updated
wgputo 29.0.3 and thelibrashaderfilter chain to 0.11 (the wgpu path used for RetroArch shaders on Windows/WASM and behind thewgpufeature flag elsewhere).
0.4.5
- Tab color picker now also opens on right-click (previously Control + left-click only).
- New reset swatch in the tab color picker: a slashed box at the end of the swatch row clears the tab's custom color back to the default.
- Fix clicks and cursor overrides being intercepted over the empty band at the top of the window when
navigation.hide-if-singlehides the tab strip on a single tab. New sharedNavigation::island_visible(num_tabs)predicate keeps the renderer, click router, and cursor handler aligned: the empty band now passes through to the grid for selection and double-click maximize.
0.4.4
- fix characters disappearing while typing on macOS: e.g. "agg" rendering as "ag", "355" as "35" (#1595). The text-run iterator now breaks the run around the cursor cell so speculative substitutions on later cells can't blank earlier ones.
- fix panic on window resize / maximize (#1593, #1596 by @kronberger-droid). Grid dimensions are now sourced from the same snapshot that sized the row buffers, not from a live value that could race ahead.
- macOS: text selection at the top of the window now works when
navigation.hide-if-singleis on with a single tab (#1512, #1516 by @0x0aa). Click routing and the cursor override now share a single gate that matches what the renderer paints. - reduce per-frame allocations in the rioterm renderer: per-cell styles are materialized once per snapshot, per-row dirty bits skip unchanged rows on partial damage, and visible-cell extras live in a per-frame map.
- text-run shape cache key is now position-independent, and runs no longer break on space: adjacent words shape in a single call and cache hits stay high as the cursor walks a row.
0.4.3
- fix wrong font size and window chrome alignment after connecting/disconnecting an external monitor (#1588 by @tauil).
- drop the
copaandrio-proc-macroscrates: the escape-sequence parser now lives inrio-backendwith hot-path optimizations (bulk ASCII dispatch, inline OSC buffer, flat codepoint-width table, fused validate+decode). - adopt
simdutffor SIMD UTF-8 transcoding, validation, and base64 decoding.
0.4.2
- macOS Metal: window transparency now actually renders. The
CAMetalLayeris flipped to non-opaque wheneverwindow.opacity < 1or a blur style is set, so the alpha in the drawable's pixels reaches the compositor. Default windows stay opaque so the macOS opaque-window fast path is preserved. - Per-cell background alpha: cells that don't paint an explicit background color now write
alpha = 0instead of stamping the default theme background at full alpha. The drawable's translucent clear shows through, which is what makes the window actually look transparent (not just the margins). Cells with an SGR-set background, selection / search highlights, and inverse-video cells stay fully opaque. - New
window.opacity-cellsconfig option. Off by default: cells with an SGR-set background stay fully opaque so syntax-highlighted regions and TUI panels (Neovim, tmux, lazygit) keep their contrast. Set totrueto apply the opacity multiplier to those cells too, so the entire terminal, including TUI surfaces, shares the configured translucency. window.blurnow accepts the macOS liquid-glass styles in addition to the existing bool. New string values:"macos-glass-regular"(regular opacity) and"macos-glass-clear"(highly transparent), both available on macOS 26 (Tahoe) and later. Older macOS / other platforms fall back to the standard system blur and emit a warning instead of failing. Existingblur = true/blur = falseconfigs are unchanged.
0.4.1
- small updates on goreleaser build config for perf optimizations.
0.4.0
Note: There's a decent chance v0.4.0 may not work for many users. I've done my best to test it on my very old Windows and Linux machines, but it's difficult to cover all cases. This version includes many rewrites, so I recommend checking that it works properly before updating.
- reduced app size (dmg for example went from 16mb to 7.11mb).
- macos core text for searching and shaping.
- yeslogic-fontconfig-sys and windows core apis for searching. swash keeps for shaping.
- removed the extra ir for rendering so no more textruns, less memory and faster operations
- vulkan native support.
- no more font extras, rio will always find the glyph if the font is installed.
- wgpu now is optional via feature flag, this feature flag is required if you use rio with retro arch shaders. This is a movement to make rio possible for official debian.
- rio now only renders on Screen::render to ensure GPU is not stuck or overloaded during high render peaks.
- renderer.backend is only three options:
wgpu,metalandvulkan.
tested with 7e222ef2f1bc0a9eb4ff7f111b8f4c94faa9be97
| Scenario | main | new-v4 | Delta |
|---|---|---|---|
| Idle frame | ~150 µs | ~100 µs | v4 ~33% faster |
| Typing, light redraw | ~300 µs | ~200 µs | v4 ~33% faster |
| Shell output / row damage | 1000–2000 µs | 100–300 µs | v4 5–10× faster |
| 25-row scroll frame | 5500 µs (renderer=3448 µs) | 1661 µs (emit=1424 µs) | v4 ~3× faster |
| Trail animation tail (CPU work) | ~300 µs | ~200 µs | comparable, v4 slightly faster |
| GPU exec time (both) | ~700–1000 µs | ~700–1500 µs | comparable |
| First-frame setup | 15 638 µs | 9 397 µs | v4 ~40% faster |
0.3.11
- Windows: native
MessageBoxWclose-confirmation dialog whenconfirm-before-quit = true(default), mirroring macOS'sapplicationShouldTerminateNSAlertinrio-window/src/platform_impl/macos/app_delegate.rs. Replaces rio's in-window GPU-rendered confirmation modal on Windows. NewEventLoopRunner.confirm_before_quit: Cell<bool>set via the same publicEventLoop::set_confirm_before_quitthat macOS already uses (cfg gate widened toany(target_os = "macos", target_os = "windows")). TheWM_CLOSEhandler inevent_loop.rschecks the flag andvsync_state.window_count() <= 1(only the last window prompts, matching macOS's app-wide quit semantics) and on confirm-No swallows the message so the window stays open. rioterm'sWindowEvent::CloseRequestedhandler now follows the same fast path on Windows as on macOS (routes.remove(&window_id)+ maybe-exit()) since the user already confirmed at the OS layer. - Windows render loop now matches the macOS / CVDisplayLink model exactly:
Window::request_redrawsets a per-windowArc<AtomicBool>dirty flag instead of immediately callingRedrawWindow(RDW_INTERNALPAINT). The DwmFlush worker thread (rio-window/src/platform_impl/windows/event_loop/vsync.rs) is the single source of frame timing: per composition cycle it iterates the window registry and, for each window wheredirty || should_present_after_input(1 s post-input window, identical to macOS), callsRedrawWindow(.., RDW_INVALIDATE). ExistingWM_PAINT→RedrawRequestedpath is unchanged. Plumbing: newvsync::VSyncSharedState(Arc<RwLock<HashMap<HWND, Arc<AtomicBool>>>>registry +Mutex<Instant>for last input) lives onActiveEventLoop, threaded intoWindowDataand theWindowstruct so input handlers,request_redraw, and the worker all share it.Window::Dropunregisters beforeDESTROY_MSG_ID. Replaces the earlier "always invalidate per vsync" zed mirror; that approach worked but didn't compose with the app's ownrequest_redraw, which made scroll feel locked to DWM tick. Now scroll-driven renders queue immediately into the next vsync (≤16 ms wait) and idle frames are skipped entirely. Net behaviour matches macOS one-to-one. - Windows:
window.blur = truenow actually blurs (was a no-op stub). Implementation callsDwmSetWindowAttributewithDWMWA_SYSTEMBACKDROP_TYPE = DWMSBT_TRANSIENTWINDOW(Acrylic) when blur is on,DWMSBT_NONEwhen off: uses the existingset_system_backdropplumbing inrio-window/src/platform_impl/windows/window.rs. Wired both at window creation (viaattributes.blurinon_create) and at runtime via the cross-platformWindow::set_blur. Requires Windows 11 22H2+; older builds silently no-op (matches the previous behaviour). - Windows: vsync-driven render loop with 1-second post-input sustain (matches macOS / Linux / zed behaviour). All inside
rio-window; frontends still just respond toRedrawRequested. New worker thread (platform_impl/windows/event_loop/vsync.rs) callsDwmFlush()per composition cycle; when DWM is disabled, the monitor is asleep, or the call returns under the 1 ms threshold (RDP / occluded), it falls back tothread::sleepat the queriedDwmGetCompositionTimingInfo.qpcRefreshPeriodinterval, with arateRefreshnumerator/denominator fallback for spuriously low values and a 16.6 ms (60 Hz) default if both queries fail. Same heuristic zed uses ingpui_windows/src/vsync.rs. Each tickPostMessageW's a registered custom message (Winit::VsyncTick) to the existingthread_msg_target; the handler inthread_event_target_callbackenumerates thread windows viaEnumThreadWindows, filters withIsWindowVisible, and postsRedrawWindow(hwnd, RDW_INTERNALPAINT)per visible window so the existingWM_PAINTpath emitsRedrawRequestedunchanged. The fan-out is gated on a newEventLoopRunner.should_present_after_input()(1 s window after the last input event), with the same field/method names as the macOS / Wayland / X11 implementations.mark_input_receivedis hooked intopublic_window_callback_innerforWM_KEY{DOWN,UP},WM_SYSKEY{DOWN,UP},WM_MOUSE{MOVE,WHEEL,HWHEEL}, all four button down/up pairs,WM_TOUCH, andWM_POINTER{DOWN,UPDATE,UP}.EventLoop::dropnow joins the worker thread (via astub()-and-mem::replaceswap) before destroyingthread_msg_targetso the worker can neverPostMessageWto a freed HWND. New windows-sys featureWin32_System_PerformanceforQueryPerformanceFrequency.build.rsno longer panics when cross-compiling between host and target OS (#[cfg(target_os = ...)]branches now also checkCARGO_CFG_TARGET_OS), socargo check --target x86_64-pc-windows-gnuactually works from a macOS workstation. - Linux: vsync-driven render loop with 1-second post-input sustain (matches macOS / zed behaviour). Two changes inside
rio-window(no rioterm churn; frontends still just respond toRedrawRequested). Wayland (platform_impl/linux/wayland/event_loop/mod.rs): thewl_callback::Donehandler now unconditionally re-arms the nextwl_surface.frame()and drives an auto-loop, modelled on zed'sgpui_linux/src/linux/wayland/window.rs:572-587. Compositors stop delivering Done for occluded windows so the loop pauses naturally without an explicit visibility check. X11 (platform_impl/linux/x11/mod.rs): a newcalloop::timer::Timersource reschedules at the primary monitor's xrandr-derived refresh rate (monitor::mode_refresh_rate_millihertz, fallback 60 Hz); each tick setsEventLoopState.vsync_pendingand the main pump fans the flag out to every visible window via the existingredraw_senderchannel. Mirrors zed'sgpui_linux/src/linux/x11/client.rs:1934-1971. Both paths gate the syntheticRedrawRequestedon a newshould_present_after_input()(1 s window after the last input event), with the same field/method names as the existing macOS implementation inplatform_impl/macos/window_delegate.rs:139,997.mark_input_receivedis hooked into the WaylandKeyboardHandlerandPointerHandlerand into the X11 KeyPress/KeyRelease + XInput2 ButtonPress/Release/Motion dispatch sites inevent_processor.rs. Net effect: ProMotion / 144 Hz / 240 Hz monitors now stay at peak refresh during typing/scroll on Wayland and X11; idle terminals don't burn extra CPU because the gate falls back to the existing dirty-driven path outside the 1 s window. - Full kitty graphics protocol Unicode-placeholder support (
kitten icat --unicode-placeholderand any tmux/yazi/etc. that uses U+10EEEE placement cells). Wire-protocol bugs fixed: (1) the APC parser storedU=1into a privatecmd.virtual_placementfield that was never propagated toPlacementRequest, soplace_graphicalways fell through to the direct-overlay branch; (2)place_virtual_graphicwas auto-writing U+10EEEE cells to the grid, racing kitty's own writes (per the spec the application emits the cells, the terminal only stores metadata); (3) icat usesa=T,U=1(combined transmit-and-display) which goes throughkitty_transmit_and_display, notplace_graphic; that handler now also routes virtual placements correctly and pushes pixel data topending_images(the regular overlay path did this implicitly viaplace_kitty_overlay); (4) the diacritics table had 299 entries instead of the canonical 297 (two stray entries\u{06EA}and\u{06ED}from earlier work), shifting every index past the divergence point soimage_id_highdecoded as the wrong byte (e.g.0x5Cstored,0x5Edecoded). Replaced with the 297 entries fromkitty/gen/rowcolumn-diacritics.txt. Shader bug fixed:image.metalinterpretedsource_rect.zwas size but the new code passes it as end-coords; switched tomix(.xy, .zw, corner)(only worked before because every overlay used the full-image default[0,0,1,1]). Renderer side, modeled cell-by-cell on ghostty'sgraphics_unicode.zig: newRow.kitty_virtual_placeholderper-row dirty flag set inCrosswords::inputand checked by the scan loop, so we only walk rows that contain a placeholder (page.zig:1953-1958); newIncompletePlacement+can_append/append/completeimplements kitty's diacritic continuation rules: a cell with missing row/col/high-byte diacritics inherits from the previous cell on the row and the col field can be omitted to mean "auto-increment from prev" (graphics_unicode.zig:407-535); the renderer now walks each visible row left-to-right, builds runs of consecutive cells that belong to the same(image_id, placement_id, image_row)with sequential image columns, and pushes ONEGraphicOverlayper run instead of one per placement (matches ghostty'sPlacementIterator); per-run aspect-preserving fit, centering, and source-rect clipping factored intokitty_virtual::compute_run_geometry, which handles partial visibility (placement scrolled half off-screen renders only the visible image slice), runs that fall entirely in the centering padding (returnsNone), and runs that straddle the padding boundary (clips both the screen rect and the source rect so the rendered slice exactly covers the fitted-image area). Placeholder cells render withstyle.background_color = Noneso the per-cell bg quad doesn't cover the BelowText image.GraphicOverlaygained asource_rect: [f32; 4]field (default[0,0,1,1]viaFULL_SOURCE_RECT) wired through to the existingImageInstance.source_rect. Tests cover: the 297-entry diacritic table,IncompletePlacement::from_cellacross all input shapes (Indexed fg, Spec fg + 3rd diacritic, underline=placement_id, missing diacritics, Named fg → 0), allcan_appendcases (row inherit, col inherit, sequential col, col jump, row mismatch, image-id mismatch, image-id-high inherit), a 3-cell run with only the first cell carrying diacritics, parser-levelU=1propagation, the metadata-only contract ofplace_virtual_graphic, an end-to-end pass that feeds icat's exact wire format and asserts both the resulting grid cells AND the per-row dirty flag, andcompute_run_geometryacross exact-fit / image-taller-than-grid (horizontal centering + left-padding cull) / image-wider-than-grid (vertical centering + top-row cull) / partial-visibility-scrolled-off-top / origin-offset / zero-sized-image cases. - macOS Metal renderer: triple-buffered pipeline modeled on zed's
gpui_macos::InstanceBufferPool.CAMetalLayer.maximumDrawableCountis now 3 (was 2). The six per-frame buffers (text vertices, quad instances, kitty/sixel image instances, bg-image instance, bg-fill instance, Globals uniform) collapsed into a single pooledmetal::Bufferper frame: text/quad/image data bump-allocates from the pool buffer with 256-byte aligned offsets, andGlobals(transform +input_colorspace, ~80 B) goes throughset_vertex_bytes/set_fragment_bytesso no buffer is needed for it at all. The pool starts at 2 MiB, doubles on overflow up to a 256 MiB cap (matches zed). On overflow we end-encoding, drop the never-committed command buffer, grow the pool, and retry the frame from scratch; old smaller buffers in flight get rejected byreleaseaftergrowand dropped naturally, no "all 3 slots must grow together" coordination.command_buffer.add_completed_handlerreleases the buffer back to theArc<Mutex<InstanceBufferPool>>on the GPU completion thread. Net effect: CPU can stay up to 3 frames ahead of the GPU without racing the previously singleStorageModeSharedbuffers (the old code was relying on luck: every frame shared one allocation), and ProMotion 120 Hz is now reachable without dropped frames during heavy scenes.MetalRenderer::resizeis gone (no more uniform buffer to refresh on resize);Renderer::render_metalnow owns command-buffer / encoder / drawable / commit, soSugarloaf::render_metalis just a one-liner that handsbg_colorand theMetalContextover. - Fix Nerd Font glyphs from an
extrasfamily (e.g.extras = [{family="JetBrainsMono Nerd Font Mono"}]) overflowing into the next grid cell.FontLibraryData::loadwas loading every extras/symbol-map font withis_emoji = true, which madefont_cache::resolve_withclamp every glyph from that font towidth = 2.0; the terminal grid still budgeted one cell per PUA codepoint, so the layout advanced 2× per glyph and the next character painted on top of the right half. Extras and symbol-map fonts now load withis_emoji = false, andFontData::from_data/from_sliceauto-promote tois_emoji = truewhen the SFNT carries a color table (COLR,CBDT,CBLC, orsbix): mirroring ghostty'sFT_HAS_COLOR()/ CoreText SBIX check, so a real emoji font inextrasstill gets the wide-cell / color-atlas treatment without needing a config flag. - Removed the dedicated
fonts.emojiconfig slot. Rio now relies entirely onfonts.extrasplus the color-table auto-detection above: dropextras = [{family="Apple Color Emoji"}](or any color family) and it's picked up as emoji; otherwise the bundled Twemoji continues to serve as the default color-emoji fallback. User[fonts.emoji]sections in existing configs are silently ignored instead of erroring. - PUA / Nerd Font glyphs with an adjacent blank cell now fill the full 2-cell constraint crisply instead of rendering half-sized or blurry.
pua_constraint_widthin the rioterm renderer still picks 1 or 2 cells based on neighbour content; the compositor's fit pass (sugarloaf/src/renderer/compositor.rs) dropped the.min(1.0)cap so the glyph can scale up to the 2-cell slot: and to avoid stretching a bitmap atlas entry (which is blurry),GlyphCacheSession::get_at_size(id, size)now rasterizes the glyph fresh atfont_size × cellswhencells > 1. Cache key(id, size)already disambiguates the two rasterizations, so 1-cell and 2-cell lookups for the same codepoint coexist. Fixes JetBrainsMono NF Mono (patched to ~1-cell advance) showing as half-sized inside a 2-cell slot next to Cascadia NF whose glyphs render ~2 cells wide natively. - Fix vertical positioning of constraint-fit PUA glyphs. The compositor was placing the scaled glyph at
baseline − entry.top × scale, which drifts upward as the scale grows because the top-bearing scales faster than the descent-bearing. Switched to cell-centered placement (topline + (line_height − sh) / 2.0), matching ghostty's.align_vertical = .center1choice forisSymbol(cp): symbols aren't baseline-anchored the way text characters are. - macOS Metal renderer: wide-gamut pipeline with ghostty-compatible
nativealpha blending.CAMetalLayeruses plainBGRA8Unormtagged withkCGColorSpaceDisplayP3(earlier iterations usedBGRA8Unorm_sRGB, which makes Metal do linear-light blending: physically correct but visibly brighter on AA edges and translucent overlays than ghostty's and Terminal.app's default). The three pipeline color attachments moved back toBGRA8Unormto match. Fragment shaders (renderer.metal,image.metal) nowsrgb_to_linear → sRGB-to-P3 matrix → linear_to_srgbbefore returning, emitting gamma-encoded DisplayP3 bytes that the drawable stores verbatim and the compositor displays directly.MTLClearColorgoes through the same encode on the Rust side (sugarloaf::prepare_output_rgb_f64) so the first cleared pixel matches a shader-drawn quad of the same theme colour. Net effect: same saturation as before (P3 gamut preserved), same glyph weight as ghosttyalpha-blending = native/ Terminal.app (no more AA-edge brightening). Themetalcrate doesn't wrapCAMetalLayer.colorspaceyet, so the setter goes throughmsg_send!; theCGColorSpacehandle ismem::forget-ed to guarantee the pointer stays live for the layer's lifetime, and a post-set read-back logs a warning if the colorspace didn't take. - Breaking (macOS):
[window] colorspacedefault flipped fromdisplay-p3tosrgb. The semantics also changed to match ghostty'swindow-colorspace: the setting now describes how Rio interprets input color bytes (hex values in config, ANSI direct-color sequences), not which colorspace the Metal surface uses. The Metal surface is always DisplayP3 regardless of this setting. Withsrgb(the new default), Rio applies a Bradford-adapted sRGB D65 → DisplayP3 D65 matrix (in linear light, aftersrgb_to_linear) so#ff0000renders as sRGB-standard red: matching ghostty and every other app. Users who preferred the previous more-saturated P3-interpreted look can pin it withcolorspace = "display-p3". The matrix runs in the fragment shader (prepare_output_rgbinrenderer.metal/image.metal) driven by a newinput_colorspace: u8field on theGlobalsuniform, and at the Rust boundary for theMTLClearColor(sugarloaf::prepare_output_rgb_f64) so the first HW-cleared pixel lands in the same colorspace as shader-emitted pixels.MetalRenderer::newtakes the colorspace at construction and writes it into every uniform upload; the Metal encoder now binds the uniform buffer to fragment slot 1 (in addition to the existing vertex slot 1) sofs_main/image_fs_maincan read the flag. - New
OpenCommandPalettekey-binding action (defaultCmd+Shift+Pon macOS,Ctrl+Shift+Pelsewhere), user-remappable viaopencommandpalettein[bindings]. Replaces the hardcodedCmd/Ctrl+Shift+Pbranch that used to sit inscreen::process_key_eventahead of the binding system, so the palette shortcut now composes with mode-gating like every other action. - New
List Fontscommand palette entry: selecting it keeps the palette open and swaps the list for the host system's font families (viafont-kit'sSystemSource), fuzzy-filterable. Enter copies the selected family to the clipboard and closes the palette. Each font row shows a hand-drawn (rect-only) rounded copy icon on the right to advertise the action. - Command palette scrollbar now reuses the terminal scrollbar's look and behaviour through shared primitives in
renderer::scrollbar(opacity_from_last_scroll,compute_thumb,draw_thumb): 6 px wide,[0.6, 0.6, 0.6, 0.5]gray, no rounded corners, 2 s visibility + 300 ms fade after the last scroll event. Only appears when the user has actually scrolled and resets on palette close / query change. Sugarloaf::font_family_names()+FontLibrary::family_names()for enumerating the host font catalog.- Rio
Attributesre-exported at the sugarloaf crate root so downstream callers don't have to reach intofont_introspector.
0.3.10
- Fix tab-title overflow spilling into neighbour tabs / off-screen when the title is longer than the tab width (issue #1508). The island was adding the full title as a text span, measuring it, and centering, with no truncation, so a wide
text_widthproduced a negative x offset and the text bled left of the tab's origin. AddedSugarloaf::char_advance(ch, attrs, font_size)(and extendedResolvedGlyphwithadvance_units+units_per_em, populated once at resolve time alongside the existing fallback walk) so the tab bar can walk titles char-by-char and truncate with a trailing…to fittab_width - 2·TAB_PADDING_X. WiredTAB_PADDING_Xup and dropped its#[allow(dead_code)].
0.3.9
- Fix progress bar visually freezing at the left edge when a TUI heartbeats
OSC 9;4faster than the indeterminate animation cycle (issue #1509). The island had oneprogress_last_updatefield doing double duty as the animation phase reference and the stale-bar dismissal timestamp; every report yanked the animation back to t=0. Now split intoprogress_started_at(only reset on actual state transitions) andprogress_last_seen(bumped every report, drives the 15 s timeout): same separation ghostty's GTK apprt gets for free fromGtkProgressBar.pulse()plus a sideglib.timeoutAdd. - Fix emoji with VS16 variation selector (e.g.
🎟️,⚠️) visually overflowing into the next grid cell. Rio's font shaper correctly uses cmap format 14 to pick the wide emoji glyph for(base, U+FE0F)clusters, but the grid still budgeted only one cell for the base, so the glyph painted over its neighbour: misaligning vim/tmux vertical split lines on any row containing a text-presentation emoji. Rio now promotes the cell toWide+Spaceron VS16 (and narrows it back on VS15) for any sequence listed in Unicode'semoji-variation-sequences.txt, matching kitty and ghostty. New workspace craterio-grapheme-widthcarries the table (forked fromwezterm-char-props, MIT). - Add
scrollback-history-limitconfig option (default10000, set to0to disable scrollback). Fixes #993. - Harden Kitty graphics protocol: reject images exceeding 10000 px per axis or 400 MiB, add per-chunk base64 decoding so clients like
chafa --format=kitty(which pads every chunk) merge correctly, time out stale chunked uploads after 10 s, combinei=/I=/p=response keys, validatei=/I=mutual exclusion, and requirei=fora=qqueries. - Fix kitty image protocol whenever using transmission.
- Fix color picker not rendering correctly.
- Selection feel: bumped the click/drag side-of-cell threshold from 50% to 60% (matches ghostty), so selections no longer flip to the next cell as eagerly when the cursor crosses the midpoint.
- Default URL/path regex now matches local paths in addition to schemed URLs. Ported verbatim from ghostty's
src/config/url.zig: rooted (/abs), explicitly-relative (./x,../x), home (~/x), env-var-rooted ($VAR/x), hidden-dir (.config/x), and bare relative paths with a dotted filename (src/main.rs). Lookbehinds reject mid-word starts (the/barinsidefoo/bar) and trailing punctuation (see https://example.com.won't include the period). - Switch hint regex matching from the Rust
regexcrate toonig(Oniguruma): same engine ghostty uses. Adds lookbehind/lookahead support so the default regex matches ghostty's behavior exactly, and user[hints.rules]regexes can now use lookarounds and backreferences. - When a hint match looks like a local path, rio now resolves it against the terminal's OSC 7 working directory, expands
~/and$VAR/, and only dispatches the resolved absolute path to the OS opener if the file exists; URL schemes (https://…,mailto:, …) are passed through unchanged. - Restore OSC 8 hyperlink underlines. The cell repack moved hyperlink data into a side table and the renderer's
square.hyperlink().is_some()check was disabled with a// temporarily disabledcomment that was never lifted; the renderer now reads the cell'sHYPERLINKflag directly so OSC 8 spans are underlined again. - Fix hover hint underline not appearing on the very first hover after startup.
update_highlighted_hintsnow marks the renderer'spending_updatewith full terminal damage when the hint changes, mirroring the pre-refactorset_hyperlink_rangebehaviour, so the partial-damage render path can no longer skip the re-shape. - Fix two
context::titletests panicking under sandboxed builds (e.g. Void's xbps-src) where$HOME=/tmpcollapsed the test path to~. The tests now use a path prefix that can't plausibly be$HOME.
0.3.8
- Fix click between panels not working if it's on alternative screen.
- Fix divider not appearing (regression of 0.3.7).
0.3.7
- Reduced GPU upload.
- ~17k quads before: ~8.5 MB
- ~17k quads after: ~1.55 MB
- 5.5x reduction.
0.3.6
- Performance improvements.
- Now a cell is 8 bytes.
// Bit layout for Square(u64)
//
// bits 0..20 (21): codepoint (Unicode scalar value, max 0x10_FFFF)
// OR low bits of bg color when content_tag != Codepoint
// bits 21..22 (2): wide (Wide enum)
// bits 23..29 (7): per-cell flag bits (CellFlags), incl WRAPLINE at bit 0
// bits 30..31 (2): content_tag (NEW)
// 0 = Codepoint (text cell, use style_id below)
// 1 = BgPalette (bg-only cell, palette index in 32..39)
// 2 = BgRgb (bg-only cell, RGB packed in 32..55)
// 3 = reserved
// bits 32..47 (16): style_id (when tag == Codepoint)
// bg palette idx in low 8 (when tag == BgPalette)
// bg RGB.r:g in low 16 (when tag == BgRgb)
// bits 48..63 (16): extras_id (when tag == Codepoint)
// bg RGB.b in low 8 (when tag == BgRgb)
- Add support for
window.columnsandwindow.rowsfor window sizing. Ignores invalid0values with fallback towindow.width/window.height, and guarantees a minimum startup size of300x200logical pixels. - Avoid send damage events to Application when terminal already has damage found and unprocessed.
- Fix macOS window close button (red semaphore) showing quit confirmation dialog. Clicking the close button now always closes the window. Quit confirmation is only triggered by Cmd+Q.
- Remove
window.macos-use-quit-dialogconfiguration option.
0.3.5
- Fix underline cursor rendering.
- Fix underline cursor disappearing on blank cells when
window.background-imageis set orwindow.opacity < 1.0. The empty-run dispatch in the renderer now also paints decoration-only spans. - Fix
navigation.unfocused-split-opacitynot dimming unfocused splits. The setting is now applied as a semi-transparent overlay drawn on top of inactive panes and works correctly on both opaque and transparent windows. Default raised from0.4to0.7and clamped to[0.15, 1.0]. - Add
navigation.unfocused-split-fill: RGB tint used for the unfocused-split overlay. Defaults to the terminal background color. - Re-implement
window.background-image. It had been a silent no-op since the renderer rewrite: setting it would clear the window to transparent and paint nothing on top. The image is now uploaded into a dedicated GPU texture sized exactly to the source dimensions (no glyph-atlas pollution, no atlas-size limit) and stretched to cover the full window. - Add
window.background-image.opacity:0.0–1.0multiplier applied to the image's alpha channel. Defaults to1.0. - Breaking: removed
window.background-image.width,height,x, andy. They had no effect under the old implementation and the new dedicated pipeline always fills the window. - Surface background-image load failures (missing path, decode error) through the in-window assistant warning popup instead of a silent log line.
- Fix FreeBSD build.
0.3.4
- Fix kitty image protocol overlay when has a new tab.
- Fix kitty image protocol placeholder content being rendered.
0.3.3
- CPU rendering support by
renderer.use-cpu. - Removed Font char cache friction.
- Fix kitty image protocol and sixel.
0.3.2
- Performance: Skip shaping for empty cells, perf gain can be over 50% depending of the visible rows.
- Private user area should adjust based on cells.
- Cells now by default are created with \0.
- Selection ignore \0 cells.
0.3.1
- Fix crash when filters option is on.
0.3.0
- Quit Confirmation Dialog: New in-window quit screen with Rio logo, triggered by Cmd+Q / confirm-before-quit
- Respond with
yto quit ornto cancel - Optional native macOS quit dialog via
window.macos-use-quit-dialogconfig
- Respond with
- Kitty Graphics Protocol: Display images directly in your terminal
- Direct placements (U=0)
- Virtual placements (U=1)
- Diacritic-based row/column encoding (283 combining characters)
- RGB color encoding for image/placement IDs (24+8 bit support)
- Virtual placement rendering (infrastructure complete, rendering pending)
- Sixel Graphics: Full support with proper scrolling and positioning
- Graphics Rendering Improvements:
- Fixed vertical positioning alignment
- Fixed scrolling (images persist when origin scrolls off-screen)
- Fixed duplicate rendering with per-frame deduplication
- LRU cache with automatic eviction
- Native Metal Support (macOS): Hardware-accelerated rendering with Metal
- New GPU-Rendered Navigation: Faster, smoother tab interface
- Command Palette: Quick access to terminal functions
- Toggle Appearance Theme: Switch between dark and light themes at runtime via key binding (
ToggleAppearanceTheme) or command palette (only available when adaptive theme is configured) - Custom Mouse Cursor: Configurable mouse cursor effects via
effects.custom-mouse-cursor - Trail Cursor: Smooth spring-animated cursor trail using neovide-style physics (enabled by default via
effects.trail-cursor) - Desktop Notifications: Support for OSC 9 (iTerm2) and OSC 777 (rxvt) terminal notifications using native platform APIs (macOS
UNUserNotificationCenter, Linux D-Bus, Windows Toast) - Force Theme: New
force-themeconfiguration property to override the system theme when using adaptive themes - Quake Window Mode: Drop-down terminal from top of screen
- macOS Traffic Light Positioning: Customize position of window control buttons
- Configure via
macos-traffic-light-position-xandmacos-traffic-light-position-y - Defaults to standard macOS positioning (11.4, 16.1)
- Not available in Tab navigation mode
- Configure via
- OSC 9;4 Progress Bar Support: Terminal progress indicator (ConEmu/Windows Terminal compatible)
- Scroll Bar: Overlay scroll bar that appears on scroll and fades out after 2s
- Works per-panel in split views
- Draggable thumb with click-on-track jump scrolling
- Configure via
enable-scroll-bar(enabled by default)
- Tab Title
RELATIVE_PATHvariable: New template variable that shows a home-relative shortened path (e.g.~/Documents/a/rioor…/a/psone/starpsx). Default tab title on macOS/Linux changed to{{ TITLE || RELATIVE_PATH }}. - Wgpu now is always f32.
- This fixes non arm chip macos use cases.
Breaking Changes
- Navigation modes simplified - if you use
TopTab,BottomTab, orBookmark, change to:[navigation]mode = "Tab" - Default
Decorationschanged toTransparenton macOS (wasEnabled) - Removed:
TopTab,BottomTab, andBookmarknavigation modes - Available modes:
Plain,Tab,NativeTab(macOS only) - Tab color configuration simplified: Removed
tabs-foreground,tabs-active-foreground, andtabs-active-highlight- Use
tabsfor inactive tab text and border color (default:#cccccc) - Use
tabs-activefor active tab text color (default:#ffffff)
- Use
- The old padding api became margin:
# It will apply margin rules to the main container# CSS-Likemargin = [10] # (10px to all)margin = [10, 5] # (top and bottom margin are 10px, right and left margin are 5px)margin = [10, 5, 15, 20] # (top margin is 10px, right margin is 5px, bottom margin is 15px, left margin is 20px)# It will apply margin rules to panels[panel]margin = [5] # (5px to all)row-gap = 0 # (0px)column-gap = 0 # (0px)
Technical Details
- Complete rendering architecture rewrite for GPU-based UI
- Parser now supports APC sequences for Kitty graphics protocol
- Removed legacy layer/quad rendering system
- Added Metal backend for macOS, split WebGPU backend for cross-platform
- New
kitty_virtualmodule for placeholder encoding - Graphics cleanup with LRU eviction strategy (evicts up to 5 oldest when atlas full)
- Added 5 unit tests for graphics rendering (positioning, LRU, deduplication)
0.2.36
- Fix DECSCUSR.
0.2.38
- Update wgpu to v0.28.
- Update Rust to v1.92.
0.2.37
- Support window bg color via OSC.
- Fix vi cursor not displayed when moving.
- Fix font loader for fallbacks and extra.
- Fix font size updating through config.
0.2.36
- Fix handler should process two intermediate bytes in CSI sequences by @aymanbagabas.
- Fix DECSCUSR.
0.2.35
- GPU memory usage drop 83%.
- Sync input render logic (macos).
0.2.34
- Fix issue for finding fonts introduced with the v0.2.33 new font loader.
0.2.33
- Platform-specific configuration improvements #1341:
- Added support for platform-specific environment variables via
env-varsfield in platform config - Platform-specific env-vars are now appended to global env-vars instead of replacing them
- Fixed configuration inheritance: platform overrides now use field-level merging instead of replacing entire sections
- Window, Navigation, and Renderer settings can now be partially overridden per platform without duplicating all fields
- Added
themefield to platform config for per-platform theme selection - Shell configuration continues to use complete replacement for simplicity
- Added support for platform-specific environment variables via
- Fix
ScrollPageUpandScrollPageDownactions not working in custom keybindings #1275. - Fix Noticeably slower startup compared to wezterm, foot #1346.
- Fix Font loader taking a LOT of time to load fonts #1339.
- Fix Rio panics on launch on a Raspberry Pi 5 #1332.
- Fix kitty keyboard protocol.
- Support reporting terminal version via XTVERSION.
0.2.32
- Updated WGPU to v27.0.1.
- Fix No backend are enabled on FreeBSD #1235.
0.2.31
- Update Rust to v1.90.
- Fix kitty keyboard recognition.
- Breaking: Simplified key binding escape sequences
- Replaced separate
textandbytesfields with a singleescfield - Escape sequences are now sent directly to the PTY without text manipulation
- Migration: Replace
bytes = [27, 91, 72]withesc = "\u001b[H" - Migration: Replace
text = "some text"withesc = "some text" - Example:
{ key = "l", with = "control", esc = "\u001b[2J\u001b[H" }to clear screen
- Replaced separate
- Fix key binding conflicts: Resolved issues where keys like
PageUp,PageDown, andAlt+Enterrequired explicit"None"bindings before they could be reassigned- Simplified binding conflict resolution logic to automatically remove conflicting default bindings
- User-defined bindings now always take precedence without requiring placeholder "None" entries
0.2.30
- Fix Debian/Ubuntu package installation: Resolved terminfo conflicts with system packages #1264
- Debian (.deb) packages no longer include terminfo files to avoid conflicts with ncurses-term
- Users on Ubuntu 22.04 and older need to manually install terminfo after package installation
- Debian 13+ and Ubuntu 24.04+ users get terminfo from system's ncurses-term package
- RPM packages continue to include terminfo as before
- Add audible & visual bell support #1284.
0.2.29
- Fix blinking cursor issue #1269.
- Fix Rio uses UNC (?) path as working directory, breaking Neovim subprocesses on Windows.
- Add NSCameraUseContinuityCameraDeviceType to plist for macOS.
0.2.28
- Optimized rendering pipeline for improved performance: Implemented deferred damage checking and render coalescing
- Added Wakeup events to batch multiple rapid terminal updates into single render passes
- Deferred damage calculation until render time to reduce unnecessary computations
- Skip rendering for unfocused windows when
disable_unfocused_renderis enabled - Skip rendering for occluded windows when
disable_occluded_renderis enabled - Improved damage merging to always accumulate updates even when already marked dirty
- Enhanced performance for rapid terminal output by coalescing non-synchronized updates
0.2.27
- Breaking: If
xterm-riois installed we prioritized it overrioterminfo. - Fix sixel/iterm2 graphics persistence issue: Fixed graphics remaining visible when overwritten by text
- Graphics are now properly removed when cells containing them are overwritten
- Fixes issues with file managers like Yazi where images would persist incorrectly
- Simplified graphics cleanup logic by removing unused ClearSubregion functionality
- CJK Font Metrics: Fixed CJK characters displaying "higher" than Latin characters #1071
- Implemented comprehensive CJK font metrics handling with consistent baseline adjustment
- Fixed scrolling issues for mixed Latin and CJK text content
- Added CJK character width measurement using "水" (water ideograph) as reference
- Created consistent cell dimensions across different font types
- Developed extensive test suite with 40+ font-related tests to verify fixes
0.2.26
- Fix frame dropping in release builds: Fixed an issue where release builds would drop frames due to damage event timing
- Damage events are now emitted directly after parsing PTY data, ensuring proper batching
- Removed redundant Wakeup event mechanism that was causing multiple renders per update
- Synchronized update timeouts now properly emit damage events
- Significantly improves rendering smoothness in optimized builds
0.2.25
- Fix: Rio doesn't launch from context menu on Windows.
- Fix: Rio lacks embedded icon on Windows 10 by @christianjann.
- Fix custom shells in /usr/local/bin not found on macOS: Fixed an issue where custom shells installed in
/usr/local/binwere not found when Rio was launched from Finder or other GUI applications- On macOS, Rio now uses
/usr/bin/loginto spawn shells, ensuring proper login shell environment with full PATH - Custom shells like Fish, Nushell, or custom Zsh installations in
/usr/local/binwill now work correctly
- On macOS, Rio now uses
0.2.24
- Fix game mode regression.
- Hint Label Damage Tracking: Improved hint label rendering performance with proper damage tracking
- Hint label areas are now properly marked for re-rendering when cleared
- Eliminates visual artifacts when hint labels are removed
- Optimized rendering to only update affected screen regions
- Configurable Hyperlink Hover Keys: Hyperlink hover modifier keys are now configurable
- Configure custom modifier keys through the hints system in
config.toml - Default behavior unchanged: Command on macOS, Alt on other platforms
- Supports any combination of Shift, Control, Alt, and Super/Command keys
- Example:
mouse = { enabled = true, mods = ["Shift"] }to use Shift key
- Configure custom modifier keys through the hints system in
- Hints Configuration: Renamed
hints.enabledtohints.rulesfor better clarity- Update your configuration:
[[hints.enabled]]→[[hints.rules]] - All hint configuration sections now use
hints.rules.*instead ofhints.enabled.* - Functionality remains the same, only the configuration key names changed
- Update your configuration:
0.2.23
- Fix some rendering regressions introduced by 0.2.21.
- Improve performance by stopping locking on rendering run steps.
- Fix: X11: WM_CLASS has an empty string property.
0.2.22
- Fix some regressions introduced by 0.2.21.
0.2.21
- Breaking:
navigation.use-current-directoryhas been renamed tonavigation.current-working-directory.
Performance Optimizations
- Major: Implemented efficient CVDisplayLink-based VSync synchronization for macOS
- Perfect frame timing aligned with display hardware refresh cycles
- Eliminates screen tearing and stuttering through hardware VSync synchronization
- Adaptive refresh rate support: automatically handles 60Hz, 120Hz, ProMotion displays
- Multi-display support: adapts when windows move between displays with different refresh rates
- Grand Central Dispatch (GCD) integration for thread-safe cross-thread communication
- Smart rendering: Only renders when content actually changes using dirty flag system
- Power efficient: skips unnecessary redraws when content is static, reducing CPU usage
- Professional rendering quality with smooth, tear-free visual updates
- CVDisplayLink runs on dedicated background thread, never blocking UI operations
- macOS VSync Optimization: Disabled redundant software-based vsync calculations on macOS
- CVDisplayLink already provides hardware-synchronized VSync timing
- Eliminates unnecessary frame timing calculations and monitor refresh rate queries
- Reduces CPU overhead and improves rendering performance
- Software vsync logic remains active on other platforms for compatibility
- Major: Implemented a new text run caching system replacing line-based caching
- Up to 96% reduction in text shaping overhead for repeated content
- Individual text runs (words, operators, keywords) cached and reused across frames
- 256-bucket hash table with LRU eviction for optimal memory usage
- Cache Warming: Pre-populate cache with 100+ common terminal patterns on startup
- Programming keywords:
const,let,function,class,import,export, etc. - Indentation patterns: 4/8/12/16 spaces, single/double/triple tabs
- Shell commands:
ls,cd,git,npm,cargo,sudo, etc. - Operators & punctuation:
=,==,=>,();,{},[], etc. - File extensions:
.js,.ts,.rs,.py,.json,.md, etc. - Error/log patterns:
Error:,[INFO],FAILED,SUCCESS, etc. - Immediate cache hits eliminate cold start shaping delays
- Programming keywords:
- SIMD-Optimized Whitespace Detection: Multi-tier optimization for indentation processing
- AVX2: 32 bytes per instruction (x86-64 with AVX2 support)
- SSE2: 16 bytes per instruction (x86-64 with SSE2 support)
- NEON: 16 bytes per instruction (ARM64/aarch64)
- Optimized scalar: 8-byte chunks (universal fallback)
- Up to 32x performance improvement for long indentation sequences
- Critical for Python, nested JavaScript/TypeScript, YAML, and heavily indented code
- Memory Pool for Vertices: High-performance vertex buffer pooling system
- Size-categorized pools: Small (64), Medium (256), Large (1024), XLarge (4096) vertices
- Zero allocation overhead through buffer reuse across frames
- LRU management with automatic cleanup when pools reach capacity
- Thread-safe concurrent access with performance monitoring
- Eliminates GC pressure and improves frame rate consistency
- Background Font Operations: Non-blocking font management
- Font data release and cleanup in dedicated background thread
- System font scanning and preloading without blocking main thread
- Prevents frame rate drops during font operations
- Occlusion-Based Rendering: Skip rendering for occluded windows/tabs
- Automatically detects when windows are completely hidden by other windows
- Skips rendering for occluded windows to save GPU resources and improve performance
- Renders one frame when window becomes visible again to ensure display is updated
- Configurable via
[renderer] disable-occluded-render = true(enabled by default) - Significantly improves performance when running multiple tabs or windows
Other Improvements
- Optimize the character cluster cache for wide space characters.
- New font atlas, more efficient.
- Implemented around 75% Memory Reduction: Text glyphs now use R8 (1 byte) instead of RGBA (4 bytes).
- Hint Label Damage Tracking: Improved hint label rendering performance with proper damage tracking
- Hint label areas are now properly marked for re-rendering when cleared
- Eliminates visual artifacts when hint labels are removed
- Optimized rendering to only update affected screen regions
- IME Cursor Positioning: Added configurable IME cursor positioning based on terminal cell coordinates
- IME input popups now appear precisely at the cursor position
- Improves input experience for CJK languages (Chinese, Japanese, Korean)
- Configurable via
[keyboard] ime-cursor-positioning = true(enabled by default)
- Shift+Click Selection: Added Shift+click support for expanding text selections
- Shift+clicking now extends the current selection to the clicked cell
- Provides standard terminal selection behavior expected by users
- Regular clicking without Shift still clears selection and starts new one as before
- CLI accepts relative paths for working directory CLI argument: When invoking rio from other terminals using
rio --working-dir=<path>, a relative path is now correctly processed
Bug Fixes
- Cursor Damage Tracking: Fixed cursor rendering issues after
clearcommand and during rapid typing- Replaced complex point-based damage tracking with simplified line-based approach
- Eliminates edge cases where cursor updates were missed during fast typing sequences
- Improved reliability by always damaging entire lines instead of tracking column ranges
- Aligns with modern terminal design principles for more robust damage calculation
- Selection Rendering: Fixed selection highlight not appearing on first render
- Selection changes now properly trigger damage tracking and rendering
- Optimized selection damage to only redraw affected lines for better performance
- Selection highlights now appear immediately when making selections
- Text Selection: Fixed selection behavior during input and paste operations
- Selection properly clears when typing or pasting text (both bracketed and regular paste)
- Selection coordinates remain stable during viewport scrolling
- Prevents selection from being lost unexpectedly during normal terminal usage
- Auto-scroll on Input: Fixed issue where typing after scrolling up wouldn't automatically scroll to bottom
- Now properly scrolls to bottom for both keyboard input and IME/paste operations
- Ensures cursor remains visible when typing new content
- Scroll Performance: Improved scrolling performance by optimizing render event handling
- Moved scroll display offset update before mouse cursor dirty event
- Removed redundant render calls during scroll operations
- Implemented centralized damage-based rendering in event loop for better performance
- macOS IME Improvements: Fixed emoji input and IME stability issues
- Resolved
IMKCFRunLoopWakeUpReliableerrors when using emoji picker - Improved coordinate validation and error handling for IME positioning
- Better handling of direct Unicode input (emoji picker, character viewer)
- Added throttling to prevent excessive IME coordinate updates
- Resolved
- Documentation: Added comprehensive manual pages (man pages) for Unix-like systems
man rio- Main Rio terminal manual page with command-line optionsman 5 rio- Complete configuration file format documentationman 5 rio-bindings- Key bindings reference and customization guide- Available in
extra/man/directory with build instructions
- Terminfo Compatibility: Improved terminal compatibility by adding
xterm-rioterminfo entry- Added
xterm-rioas primary terminfo entry withrioas alias for better application compatibility - Applications that look for "xterm-" prefixed terminals (like termwiz-based apps) now work correctly
- Maintains
TERM=rioenvironment variable for consistency with terminal identity - Fixes crashes with applications like
gituand other termwiz-based terminal programs - Follows same pattern as other modern terminals (Alacritty, Ghostty) for maximum compatibility
- Added
Technical Details
The performance optimizations in this release represent a significant architectural improvement to Rio's text rendering pipeline:
- Text Run Caching: Replaces line-based caching with individual text run caching. Each unique text sequence (word, operator, keyword) is shaped once and reused across all occurrences.
- SIMD Implementation: Platform-adaptive SIMD instructions automatically detect and use the best available CPU features (AVX2 > SSE2 > NEON > optimized scalar) for maximum performance across different architectures.
- Memory Management: The vertex pool system uses size-categorized buffers with LRU eviction, eliminating allocation overhead while preventing memory bloat.
- Cache Strategy: Two-level caching (render data + text runs) with 256-bucket hash table using FxHasher for optimal lookup performance.
- Compatibility: All optimizations maintain full backward compatibility with existing Rio APIs and configurations.
These changes are particularly beneficial for:
- Programming workflows with repetitive code patterns
- Terminal sessions with heavy indentation (Python, nested JS/TS, YAML)
- Long-running sessions where cache warming provides sustained performance benefits
- Systems with limited memory where reduced allocation overhead improves overall responsiveness
Bug Fixes
- Backspace Key Compatibility: Fixed backspace key not working properly in vim when
TERM=xterm-256color- Changed backspace key bindings to send BS (0x08) instead of DEL (0x7F)
- Updated Rio terminfo and termcap entries to match actual key behavior
- Updated XTGETTCAP response to return
^Hforkbscapability - Ensures compatibility with applications expecting xterm-256color backspace behavior
- Fixes issue where vim would display
^?instead of performing backspace operation
0.2.20
- Performance: Implemented SIMD-accelerated UTF-8 validation throughout Rio terminal using the
simdutf8crate.- Architecture support: AVX2/SSE4.2 (x86-64), NEON (ARM64), SIMD128 (WASM)
- Automatic optimization: Runtime detection selects fastest implementation available
- Support for XTGETTCAP (XTerm Get Termcap) escape sequence for querying terminal capabilities.
- Font library is now under a RWLock instead of Mutex to allow multiple tabs readings same font data.
- Fix: crash on openSUSE Tumbleweed #1160.
0.2.19
- Reduced the bundle size by ~20.81% (MacOS, Linux, BSD).
- Performance: stop saving empty images in the image cache.
- Fix: On MacOS, keybind definition to ignore cmd-w does not work #879.
- Fix: Build for MacOS 26 Tahoe.
- Fix:
Enter,Tab,Backspacenot disambiguated withshiftin kitty keyboard's disambiguate mode. - Fix: line-height adds small gaps for box-drawing characters #1126.
- Search matching a wrapping fullwidth character in the last column.
- Update Rust to 1.87.0.
0.2.18
- Fix image display crashing the application whenever f16 is available.
0.2.17
- Breaking: Decorations as
Enabledis default on MacOS (instead ofTransparent). - F16 Texture supports whenever is available.
- Clear font atlas whenever the font is changed.
- Skip passing sandbox env in Flatpak, fixes user environment in spawned shell #1116 by @ranisalt.
- On Windows, fixed crash in should_apps_use_dark_mode() for Windows versions < 17763.
0.2.16
- Breaking: support reading from config directory using
$XDG_CONFIG_HOMEon Linux #1105 by @ranisalt. - Fix: Crash on whenever attempting to clean an invalid line index.
- Add metainfo and screenshots for appstream by @ranisalt.
0.2.15
- Fix: In some cases, the first typed character doesn't display until after a delay, or until another key is hit #1098.
- Fix: Anomalous behavior occurs with the Bookmark tab style in the new versions 0.14 and 0.13. #1094.
0.2.14
- Fix: panic and crash of terminal window during sudo apt update #1093.
0.2.13
- Breaking change: For Windows and Linux users, hyperlink trigger whenever hovering a link was changed from
alttoshift. - Fix dimension for whenever a new tab is created from a view with splits.
- Drop subtables with empty coverage by @xorgy.
- Fix font size affecting tabs size.
- Support to drawable characters by using
fonts.use-drawable-chars = true. - Fix: Wrong unicode character alignment #616.
- Fix: Built-in font for box drawing #974 #974.
- Fix: U+E0B6 and U+E0B4 Unicode with different sizes #895.
- Update wgpu to v25.
- Fix: Custom rendering (alignment) of Braille symbols #1057.
- Fix: Drawing char ⡿ in column 1 causes the entire terminal to stutter #1033.
- Fix: Some glyphs (e.g. braille symbol) are rendered with gaps in between #930.
- Introduce
fonts.disable-warnings-not-foundto disable warning regarding fonts not found. - Fix: Request: silently ignore missing fonts from fonts.family and fonts.family.extras #1031.
- Fix: Add branch drawing symbols to box characters #761.
- Fix: macOS: fallback for missing font glyph? #913.
- Fix: FPS calculation, before it was rendering avg 48 on 60fps screen, however it was due to wrong frame scheduling computations, now it's up to 56-58.
- Fix: Shift+Tab event is doubled, as if hit twice #1061.
- Fix: Request: Option to change click-link modifier key #1059.
- Fix: Unexpected tmux previous-window #1062.
- Rewrite the way Rio deals with line diff and updates computation.
- Support for setting a custom config directory using
$RIO_CONFIG_HOME - Support for additional font dirs using
fonts.additional-dirs - Rio's MSRV is 1.85.0.
- Support to Sextants.
- Fix: Octant support #814.
- Fix: Issue regarding split not updating opacity style when getting unfocused.
- Add support for custom parsing of APC, SOS and PM sequences.
0.2.12
- Fix crash regarding fonts not found whenever trying to run Rio.
0.2.11
- Fix filter scanlines not appearing.
- rt(wgpu): clamp texture size to device limits by @chyyran.
- Support to builtin filters:
newpixiecrtandfubax_vr. - Fix dimension computation whenever resizing Rio.
- Removed
fonts.uiproperty, now Rio will always use primary font for UI. - Removed Text renderer mod by migrating to RichText renderer.
- Breaking:
renderer.strategy = "Continuous"was renamed torenderer.strategy = "Game" - Fix search bar can't show chinese #844.
0.2.10
- Fix computation of lines on screen.
- Fix dimension of the first tab whenever TopTab or BottomTab is created.
- Fix flaky test issue, test_update_title_with_logical_or failing randomly on aarch64 #994.
- Support to
navigation.unfocused_split_opacity, default is0.5. - Sugarloaf: Fix foreground color opacity not being computed.
0.2.9
- Support to symbol map configuration:
fonts.symbol-map:
# covers: '⊗','⊘','⊙'
fonts.symbol-map = [{ start = "2297", end = "2299", font-family = "Cascadia Code NF" }]
- Add Switch to Next/Prev Split or Tab command by @vlabo.
- Fix issue whenever the first main font cannot be found.
0.2.8
- Support to
.rpmfiles! (thanks @vedantmgoyal9 and @caarlos0) - OSC 7 Escape sequences to advise the terminal of the working directory.
- Use GoReleaser to build & release Rio (#921), thanks @caarlos0 and @vedantmgoyal9
- Cache GSUB and GPOS features independently.
- Updated
windows-systov0.59.- To match the corresponding changes in
windows-sys, theHWND,HMONITOR, andHMENUtypes now alias to*mut c_voidinstead ofisize.
- To match the corresponding changes in
0.2.7
- Shifted key reported without a shift when using kitty keyboard protocol.
- fix: Set cursor color via ANSI escape sequence #945.
- fix: Can the "base 16" colors be changed at runtime through Ansi escape sequences? #188
- fix: Changing release and nightly build Ubuntu runners for x86 (
ubuntu-latesttoubuntu-22.04) and arm (ubuntu-24.04-armtoubuntu-22.04-arm)
0.2.6
- Fix: 0.2.5 doesn't render grey scale font on macOS #937.
- fix: fix duplicate tab_id by monotonic counter for unique tab IDs by @hilaolu.
- Add backslash to invalid characters for URL regex.
- fix regression introduced by 0.2.5 on light colors.
- fix: CMD+W open new tab but not new window occasionally #756.
- fix: Error getting window dimensions on Wayland #768.
0.2.5
- Introduced
draw-bold-text-with-light-colorsconfig, default isfalse. - If light or dark colors are not specified Rio will try to convert it based on the regular color.
- Fix: Block writing to the shell when rendering the
Assistantroute. - Fix: Immediately render the
Terminalroute when switching from theAssistant,ConfirmToQuitorWelcome, thus avoiding the need to double pressEnter. - Fix: MacOS Unable to type Option + Number for special characters #916.
- Fix: Looking forward to having a color converter #850.
- Fix: Unexpected basic 16 terminal colors displayed on some apps #464.
0.2.4
- Breaking: Rio now doesn't allow anymore disable kitty keyboard protocol.
- Fullwidth semantic escape characters.
- Fix: report of Enter/Tab/Backspace in kitty keyboard.
- Fix: use-kitty-keyboard-protocol = true doesn't work with tmux #599.
- Fix: use-kitty-keyboard-protocol breaks F[5-12] on macOS #904.
- Downgrade MSRV to 1.80.1
- Update wgpu to 24.0.0.
0.2.3
- Rio now allows you to configure window title through configuration via template. Possible options:
TITLE: terminal title via OSC sequences for setting terminal titlePROGRAM: (e.gfish,zsh,bash,vim, etc...)ABSOLUTE_PATH: (e.g/Users/rapha/Documents/a/rio)
COLUMNS: current columnsLINES: current lines- So, for example if you have:
{{COLUMNS}}x{{LINES}}would show something like88x66.
- So, for example if you have:
- Perf improvement on text selection #898 by @marc2332.
- Window title is now updated regardless the Navigation Mode.
- Performance: Background and foreground data are only retrieved if is asked (either color automation is enabled or
window.titlecontains any request for it). - Fixed: Nix build #853.
- Support to
window.macos-use-shadow(enable or disable shadow on MacOS). - Support to
window.windows-corner-preference(options:Default,DoNotRound,RoundandRoundSmall). - Support to
window.windows-use-undecorated-shadow(default is enabled). - Support to
window.windows-use-no-redirection-bitmap(This setsWS_EX_NOREDIRECTIONBITMAP). - Minimal stable rust version 1.84.0.
- Support for Unicode 16 characters.
- Support to line height.
- Renamed
--titleto--title-placeholderon CLI. - Fixed: Deb package name 'rio' conflicts with existing one in Ubuntu #876.
- Fixed: Unremovable bottom padding when using line-height #449.
- On macOS, fixed undocumented cursors (e.g. zoom, resize, help) always appearing to be invalid and falling back to the default cursor.
- Introduce
SwitchCurrentTabToPrevandSwitchCurrentTabToNextactions #854 by @agjini. - On X11, Wayland, Windows and macOS, improved scancode conversions for more obscure key codes.
- On macOS, fixed the scancode conversion for audio volume keys.
- On macOS, fixed the scancode conversion for
IntlBackslash.
- Kitty keyboard protocol is now enabled by default.
- Allow
Rendererto be configured cross-platform byPlatformproperty. - Add
ToggleFullscreento configurable actions. - Escape sequence to move cursor forward tabs ( CSI Ps I ).
- Always emit
1for the first parameter when having modifiers in kitty keyboard protocol. - Microsoft Windows: fix the event loop not waking on accessibility requests.
- Wayland: disable title text drawn with crossfont crate, use ab_glyph crate instead.
- Sugarloaf: Expose wgpu.
0.2.2
- Fix iterm2 image protocol.
- Allow setting initial window title #806 by @xsadia.
- Fix runtime error after changing to a specific retroarch shader on windows #788 by @chyyran.
- Makes editor.args and shell.args optional in config.toml #801 by @Nylme.
- Introduce
navigation.open-config-with-split.
0.2.1
- Fix: Search seems broken in 0.2.0 #785.
- Regular font is now 400 as default weight.
- Support to chooseing font width #507.
- Support to multiconfiguration. Rio now allows you to have different configurations per OS, you can write ovewrite
Shell,NavigationandWindow.
Example:
[shell]
# default (in this case will be used only on MacOS)
program = "/bin/fish"
args = ["--login"]
[platform]
# Microsoft Windows overwrite
windows.shell.program = "pwsh"
windows.shell.args = ["-l"]
# Linux overwrite
linux.shell.program = "tmux"
linux.shell.args = ["new-session", "-c", "/var/www"]
- Fix: Grey triangle in the titlebar #778
- Update window title straight away (#779 by @hunger)
- Always update the title on windows and MacOS (#780 by @hunger)
0.2.0
- Note: The migration from 0.1.x to v0.2.x changed considerably the renderer source code, although it was tested for 3 weeks it's entirely possible that introduced bugs (hopefully not!).
- Performance gains!
- Sugarloaf: Major rewrite of font glyph logic.
- Sugarloaf: Removal of some unnecessary processing on shaping logic.
- Sugarloaf: Rewrite/Change of render architecture, now sugarloaf does not have any reference to column/lines logic.
- Breaking: Minimum MacOS version went from El Captain to Big Sur on ARM64 and Catalina on Intel x86.
- Microsoft Windows: Rio terminal is now available on WinGet packages.
- Microsoft Windows: Rio terminal is now available on MINGW packages.
- Microsoft Windows: Rio support on ARM architecture by @andreban.
- Allow MacOS automation via events.
- MacOS: Support titlebar unified:
window.macos-use-unified-titlebar = false, - Support disable font hinting:
fonts.hinting = false. - Fix: Configuration updates triggered multiple times on one save.
- Support to RetroArch shaders @igorsaux.
- Fix: Set notepad as a default editor on Windows by @igorsaux.
- Increased Linux font fallbacks list.
- Early initial split support (this feature is not yet stable).
- Fix: Preserve current working directory when opening new tabs #725.
- Added
SplitDown,SplitRight,CloseSplitOrTab,SelectNextSplitandSelectPrevSplitactions. - Fix: Window doesn't receive mouse events on Windows 11 by @igorsaux.
- Support to hex RGBA (example:
#43ff64d9) on colors/theme by @bio on #696. - Introduced
renderer.strategy, options areEventsandContinuous. - Microsoft Windows: make
ControlFlow::WaitUntilwork more precisely usingCREATE_WAITABLE_TIMER_HIGH_RESOLUTION. - Fix: Window output lost when rio loses focus #706.
- Updated wgpu to
23.0.0.
0.1.17
- Fix flash of white during startup on Microsoft Windows #640.
- Add DWMWA_CLOAK support on Microsoft Windows.
- VI Mode now supports search by @orhun.
- Use max frame per seconds based on the current monitor refresh rate.
- breaking
renderer.max-fpshas been changed torenderer.target-fps. - Fix background color for underline and beam cursors when using transparent window.
- Fix IME color for underline and beam cursors.
- Add default for Style property on Sugarloaf font.
0.1.16
- Support auto bold on fonts.
- Support auto italic on fonts.
- Reduced default regular weight to 300 instead of 400.
- MacOS: Add dock menu.
- MacOS: Add Shell and Edit menu.
- MacOS: Support to native modal that asks if wants to close app.
- MacOS: Fix
confirm-before-quitproperty.
0.1.15
- Introduce
cursor.blinking-interval, default value is 800ms. - Fix blinking cursor lag issue.
- performance: Use
Vec(std based) instead of ArrayVec for copa. - Fix adaptive theme background color on macos.
- Decorations as
Transparentis default on MacOS. - Navigation mode as
NativeTabis default on MacOS. keyboard.use-kitty-keyboard-protocolis nowfalseby default.- Add support for msys2/mingw builds release #635 by @Kreijstal.
0.1.14
developer.log-filehas been renamed todeveloper.enable-log-file.- breaking:
CollapsedTabhas been renamed toBookmark. - Memory usage reduced by 75% (avg ~201mb to 48mb on first screen render).
- Implemented font data deallocator.
- Reduced font atlas buffer size to
1024. - Added lifetimes to application level (allowing to deallocate window structs once is removed).
- Migrated font context from
RwLocktoArc<FairMutex>. - MacOS does not clear with background operation anymore, instead it relies on window background.
- Background color has changed to
#0F0D0E. - Fix font emoji width.
- Fix MacOS tabbing when spawned from a new window.
0.1.13
- Support to iTerm2 image protocol.
- Fix: Issue building rio for Void Linux #656.
- Fix: Adaptive theme doesn't appear to work correctly on macOS #660.
- Fix: Image background support to OpenGL targets.
- Fix: Unable to render images with sixel protocol & ratatui-image #639.
- Implement LRU to cache on layout and draw methods.
- Reenable set subtitle on MacOS native tabs.
0.1.12
- Introduce:
renderer.max-fps. - Fix: Cursor making text with ligatures hidden.
- Fix: Underline cursor not working.
- Fix: sixel: Text doesn't overwrite sixels #636.
- Initial support to Sixel protocol.
- Support to
fonts.emoji. You can also specify which emoji font you would like to use, by default will be loaded a built-in Twemoji color by Mozilla.
In case you would like to change:
# Apple
# [fonts.emoji]
# family = "Apple Color Emoji"
# In case you have Noto Color Emoji installed
# [fonts.emoji]
# family = "Noto Color Emoji"
- Support to
fonts.ui. You can specify user interface font on Rio.
Note: fonts.ui does not have live reload configuration update, you need to close and open Rio again.
[fonts.ui]
family = "Departure Mono"
- breaking: Revamp the cursor configuration
Before:
cursor = '▇'
blinking-cursor = false
After:
[cursor]
shape = 'block'
blinking = false
0.1.11
- Experimental support to Sixel protocol.
- Clipboard has been moved to Application level and shared to all windows.
- Replace
runwithrun_app. - Support CSI_t 16 (Report Cell Size in Pixels).
- Support CSI_t 14 (Report Terminal Window Size in Pixels).
- Fix on all the issues regarding whenever the font atlas reaches the limit.
- breaking change: collapsed tabs use now
tabs-active-highlightinstead oftabs-active. - Default font for UI has changed to DepartureMono.
- Performance: drop extra texture creation and manipulation.
- Fix on windows: If editor is not found, the app panics #641.
- Improvements on
window.background-imageas respect width and height properties if were used. - Macos: remove grab cursor when dragging and use default instead.
- Fix
tabs-active-highlightconfig key #618. - Add
tabs-active-foregroundconfig key #619. - Add
tabs-foregroundconfig key. use-kitty-keyboard-protocolis nowtrueas default.- Remove tokio runtime.
- Allow configuring with lowercase values for enums.
- Rename
hide-cursor-when-typingtohide-mouse-cursor-when-typing. - Cleanup selection once happens a resize.
- Windows: Reduce WM_PAINT messages of thread target window.
0.1.10
- Refactor/Simplify close tabs logic internally.
- Fix: NativeTab margin top when
hide-if-singleis true. - Fix: Search bar width on 1.0 dpi screens.
- Fix: Windows - The behavior of using a complete shell command and a shell command with parameters is inconsistent #533.
- X11: Replace libxcursor with custom cursor code.
- Fix: Kitty keyboard protocol shifted key codes are reported in wrong order #596.
- Fix: Mouse pointer hidden (Ubuntu Wayland) / Cursor icon not changing #383.
- Enable search functionality as default on Linux.
- Enable search functionality as default on Microsoft Windows.
- Add command for closing all tabs except the current one (
CloseUnfocusedTabs)
0.1.9
- Search support.
- New theme properties
search-match-background,search-match-foreground,search-focused-match-backgroundandsearch-focused-match-foreground. - Fix bug Tab indicator doesn't disappear #493.
- Fix color automation on tabs for linux.
- Update tabs UI styles (make it larger and able to show more text when necessary).
- Corrections on underline render proportions for different DPIs.
- Support writing the config to a custom/default location via
--write-config(Ref: #605). - Fix scale update on transitioning between screens with different DPI.
- Support a short variant (
-w) for--working-dirargument.
0.1.8
- breaking: Introduced a new property in theme called
tabs-active-highlight, default color is#ff00ff. - breaking: Removed breadcrumb navigation.
- breaking: Introduced a new property in theme called
bar, default color changed is#1b1a1a. - breaking:
CollapsedTabis now default for all platforms. - Tab UI got some updates.
- Introduce
navigation.hide-if-singleproperty (Ref: #595). - Performance update: Remove lock dependencies on render calls.
- Performance update: Render repeated styled fragments as one rect.
- Sugarloaf API has changed from
Sugarprimitives toContent. - Fix:
[editor]overshadow headerless parameters in default config. (Ref: #601)
0.1.7
Breaking
Editor property have changed from String to allow input arguments as well.
Before:
editor = "vi"
Now:
[editor]
program = "code"
args = ["-w"]
- Fix: editor doesn't handle arguments #550.
- Fix: Weird rendering behaviour on setting padding-x in config #590.
- Upgrade Rust to 1.80.1.
0.1.6
- Support custom colors on all underlines.
- Support for advaned formatting (squiggly underline?) #370
- Performance improvements!
- Cache strategy has improved to cover any line that have been previously rendered.
- Render backgrounds and cursors in one pass.
- Update tokio
0.1.5
- Fix Bug cell disappearance #579.
- Fix Bug Rendering problem with TUIs using cursor movement control sequences in rio (v0.1.1+) #574.
- Changed default font family to Cascadia Code.
- Changed default width to 800 and default height to 500.
0.1.4
- Fix Bug Text Rendering Bug #543.
- Fix Abnormal font display and incomplete Navigation content display #554.
- Fix Bug switch tabs doesn't work #536.
- Update Cascadia Code to 2404.23.
- Change Cascadia builtin font from ttf to otf.
- Improvements for mouse selection.
- Performance improvements for background renders for all navigations besides
PlainandNativeTab. - Fix Cursor blinking is triggered by changes in inactive tabs #437.
- Fix key bindings when key is uppercased (
altorshiftis inputted along). - Support to padding-y (ref: #400)
Define y axis padding based on a format [top, bottom], default is [0, 0].
Example:
padding-y = [30, 10]
- Update swash (0.1.18), ab_glyph (0.2.28) and remove double hashmap implementation.
0.1.3
- Added support to font features (ref: #548 #551)
[fonts]
features = ["ss01", "ss02", "ss03", "ss04", "ss05", "ss06", "ss07", "ss08", "ss09"]
Note: Font features do not have support to live reload on configuration, so to reflect your changes, you will need to close and reopen Rio.
- fix: Wayland - No input after first run #566.
- fix: Mouse pointer location differs from selected text #573.
- fix: IO Safety violation from dropping RawFd (fatal runtime error: IO Safety violation: owned file descriptor already closed).
- Upgrade to Rust 1.80.0.
0.1.2
- Upgrade wgpu to v22.0.0.
- Restrict of cells width.
- Wayland: update dependencies.
- Wayland: avoid crashing when compositor is misbehaving. (ref: raphamorim/winit 22522c9b37e9734c9a2408fae8d34b2599ff4574).
- Performance upgrades for lines rendered previously.
0.1.1
- Fix the validation errors whenever a surface is used with the vulkan backend.
- Clean up weak references to texture views and bind groups to prevent memory leaks.
- Fix crashes whenever reading binary files.
- Improvements on font loader (avoid set weight or style in the lookup if isn't defined).
- Fallbacks fonts doesn't trigger alerts anymore.
0.1.0
Breaking change: Opacity API has changed
background-opacityhas been renamed toopacity. It sets window background opacity.- Removed
foreground-opacityproperty. - Removed support to DX11.
Example:
[window]
opacity = 0.8
- Major rewrite on sugarloaf.
- New rendering architecture.
- Sugarloaf now uses same render pass for each render.
- Ignore equal renderers.
- Compute layout updates only if layout is different.
BottomTabnavigation is now default for Linux and Windows.- Support to font ligatures.
- Support bluetooth access on MacOs.
- Upgraded wgpu to 0.20.0.
- Support "open here" for Microsoft Windows.
- Fixes on font search for Microsoft Windows.
- Open Url support for MacOS.
- All tabs/window instances now use same font data.
- Disabled
line-heightconfiguration in this version (it will be re added eventually). - Updated ttf-parser and memmap2 on sugarloaf.
Bug fixes
- closed: #514 Odd background transparency on macOS (Intel)
- closed: #398 Neovim and Helix rendering with line spacing
- closed: #512 Visible lines on transparent background
- closed: #491 Noticeable text update
- closed: #476 Glyphs have very weird rendering
- closed: #422 Background opacity
- closed: #355 Issues with double-width chars
- closed: #259 Sugarloaf: Positioning glyphs
- closed: #167 Tab bar overlaps text
- closed: #328 Some font issues
- closed: #225 Doesn't work with touchscreen
- closed: #307 default offset height is above the bottom position since update
- closed: #392 Box drawing issue with Berkeley Mono on MacOS
0.0.39
- Minor fix on fixed transparency on backgrounds for Welcome/Dialog.
0.0.38
- Corrections for transparency and blur for MacOS windows.
- Apply dynamic background logic only for images and keep alpha channel on background.
0.0.37
- Breaking change: Reduced font size to
16.0. - Breaking change: Set
VI modetrigger with CTRL + SHIFT + SPACE on Windows. - Update winit to 0.30.0.
- Update rust version to 1.77.2.
- Initial touch support by @androw #226
0.0.36
- fixes for x11 freeze issue.
- update winit to 0.29.15.
- update wix (toolset that builds Windows Installer) from 4.0.1 to 4.0.4.
0.0.35
- Bump wayland dependencies:
wayland-backend,wayland-client,wayland-cursorandwayland-scanner. - Refactor: disable cursor blink on selection (ref #437) #441 by @hougesen .
- Rewrite hash logic to use
BuildHasher::hash_one. - Report focus change https://terminalguide.namepad.de/mode/p1004/.
- update rust version to 1.75.0.
- update winit to 0.29.11.
0.0.34
- use Fowler–Noll–Vo hash function implementation for sugar cache (more efficient for smaller hash keys)
- update winit to 0.29.9
0.0.33
- Breaking: Removed
macos-hide-toolbar-buttonsin favor ofwindow.decorationsapi. - Fix: Rio failing to draw blur upon launch #379
- Fix: Window transparency does not work on X11 #361
- Added support for path based color automation.
- Added
window.decorationsproperty, available options areEnabled,Disabled,TransparentandButtonless.
0.0.32
- Fix: font order priority.
- Fix: add default values to keyboard config (#382)
0.0.31
-
Breaking: Configuration
performancehas moved torenderer.performance. -
Breaking: Configuration
disable-renderer-when-unfocusedhas moved torenderer.disable-renderer-when-unfocused. -
Breaking: Configuration
use-kitty-keyboard-protocolhas moved tokeyboard.use-kitty-keyboard-protocol. -
Introduction of new configuration property called
keyboard.
[keyboard]
use-kitty-keyboard-protocol = false
disable-ctlseqs-alt = false
-
Introduction of
keyboard.disable-ctlseqs-alt: Disable ctlseqs with ALT keys. It is useful for example if you would like Rio to replicate Terminal.app, since it does not deal with ctlseqs with ALT keys -
Introduction of new configuration property called
renderer.
[renderer]
performance = "High"
disable-renderer-when-unfocused = false
backend = "Automatic"
# backend options:
# Automatic: Leave Sugarloaf/WGPU to decide
# GL: Supported on Linux/Android, and Windows and macOS/iOS via ANGLE
# Vulkan: Supported on Windows, Linux/Android
# DX12: Supported on Windows 10
# DX11: Supported on Windows 7+
# Metal: Supported on macOS/iOS
- Fix: update padding top on config change #378 by @hougesen
- Fixed bug where color automation did not work on Linux because of line ending character.
- Fix: Control + Up/Down don't works as expected on neovim #371
- Fix: remove duplicate kitty backspace keybinds #375 by @hougesen
- Fix: Kitty-keyboard-protocol causes Backspace to delete 2 characters. #344 by @hougesen
0.0.30
- Fix regression with color ansi when transparency is off.
- Breaking: Config
navigation.macos-hide-window-buttonshas moved towindow.macos-hide-toolbar-buttons. - Breaking: Config property
padding-xhas been updated from 5.0 to 0.0 on MacOS.
0.0.29
- Fix compiled binary shows nothing inside the app window #366.
- Fix command key + left and right strange behavior #359.
- New scroll API: Scroll calculation for canonical mode will be based on
(accumulated scroll * multiplier / divider)so if you want quicker scroll, keep increasing the multiplier if you want to reduce you increase the divider. Can use both properties also to find the best scroll for you:
[scroll]
multiplier = 3.0
divider = 1.0
- Corrections for TMUX scroll calculations.
0.0.28
- Breaking: Settings UI has been removed and
editorproperty has been added. - Breaking: default
padding-xfor MacOS has moved from10.0to5.0. - Breaking: Background API has moved to Window
Example:
[window]
width = 600
height = 400
mode = "Windowed"
foreground-opacity = 1.0
background-opacity = 1.0
Using image as background:
[window.background-image]
path = "/Users/rapha/Desktop/eastward.jpg"
width = 200.0
height = 200.0
x = 0.0
y = 0.0
- Breaking: MacOS default navigation mode will become
NativeTab. - Support for blur background.
- Support opacity for foreground and background.
- Cursor hide feature is now behind configuration
hide-cursor-when-typing. - Confirm before quite (it can be disabled through configuration
confirm-before-quit). - Close the last tab in MacOS when using
command + w(Ref: #296) - OSC 8 (Hyperlinks).
- Fix current path on new tab is not working when using Native Tab (Ref #323).
- Change
POLLING_TIMEOUTfor configuration update from 1s to 2s. - Update
.icnsfile with more format and add new icon (Ref: #329) by @nix6839. - Update
.icofiles with more resolution and add new icon (Ref: #329) by @nix6839.
0.0.27
- Activate the hyperlink check whenever a modifier is changed (
altfor windows/linux/bsd andcommandfor macos). - Fix Error when Double click on terminal side (Ref #316).
0.0.26
- Upgrade winit to 0.29.3.
- Support for
Runactions key bindings for Microsoft Windows. - Hyperlink support (Ref #60)
0.0.25
- Upgrade wgpu to 0.18.0.
- Desktop OpenGL 3.3+ Support on Windows through WebGPU.
- Display the shell name on the tab title for MacOS Native Tab (Ref #311 by @eduronqui).
- Fix VI cursor disappearing whenever perform a scroll..
- Fix flagged dimmed colors (cases where it does not comes from rgb index).
- Fix MacOS fullscreen empty space on margin top.
- Upgrade winit to 0.29.2.
0.0.24
- Improvements on selection text for scale factor >= 2.0.
- Improvements on cursor sugar creation, dropped unnecessary usage of clone.
- Colors/Themes got a new property called
vi-cursor, you can specify any color you wish for VI Cursor. - Alacritty's VI Mode.
0.0.23
Breaking changes
navigation.mode = "Plain"now only shutdowns the key bindings related to tab creation/manipulation.ignore-selection-fg-colorhas been renamed toignore-selection-foreground-color.- Kitty keyboard protocol has been disabled by default in this version, for enable it you need to use
use-kitty-keyboard-protocol = true. CollapsedTabis not based on reverse order anymore.- Actions
SelectTab1,SelectTab2, ...,SelectTab9have been removed in favor of the new select tab API:
[bindings]
keys = [
{ key = "1", with = "super", action = "SelectTab(0)" },
{ key = "2", with = "super", action = "SelectTab(1)" },
{ key = "3", with = "super", action = "SelectTab(2)" }
]
- Actions
ScrollLineUpandScrollLineDownhave been removed in favor of the new Scroll API:
[bindings]
keys = [
# Scroll up 8 lines
{ key = "up", with = "super", action = "Scroll(8)" },
# Scroll down 5 lines
{ key = "down", with = "super", action = "Scroll(-5)" }
]
Other changes
- Rendering performance small improvements towards to Sugar text for regular font, dropped in redundancy processing (avg 68ms to 22ms with tests using 155x94 without repetition like
vim Cargo.lock). - Rendering performance small improvements towards to Sugar rect calculation, dropped in redundancy processing. Now Sugarloaf computes better Rects duplication in a line. It gains significant performance for large screens (avg ~12ms).
- Fix Backspace behaviour misplace on Windows (Ref https://github.com/raphamorim/rio/issues/220).
ClearHistorykey binding is available to use per configuration file.- Introduce Alacritty's VI Mode (Ref https://github.com/raphamorim/rio/issues/186).
- Implement
ClearSelectionkey binding action. - Fix Cursor shape isn't restored (Ref https://github.com/raphamorim/rio/issues/279).
- Fix color automation for breadcrumb mode (Ref https://github.com/raphamorim/rio/issues/251).
- Fix text copy (OSC 52) is broken (tmux, zellij) (Ref https://github.com/raphamorim/rio/issues/276).
- Fix lines calculation for different fonts.
- Fix bug whenever is not closing terminal for non native tabs (Ref https://github.com/raphamorim/rio/issues/255).
- Removal of hide cursor functionality when start to type for all platforms besides Apple MacOS.
- Support to new scroll action API key binding.
- Support to new select tab action API key binding.
- Support to execute programs as actions for key bindings:
[bindings]
keys = [
{ key = "p", with = "super", action = "Run(code)" },
{ key = "o", with = "super", action = "Run(sublime ~/.config/rio/config.toml)" }
]
- Upgrade rust to 1.73.0 by @igorvieira.
0.0.22
- Now you can add extra fonts to load:
[fonts]
extras = [{ family = "Microsoft JhengHei" }]
- Added
ScrollLineUp,ScrollLineDown,ScrollHalfPageUp,ScrollHalfPageDown,ScrollToTopandScrollToBottomto bindings. - Fix japanese characters on Microsoft Windows (Ref: https://github.com/raphamorim/rio/issues/266).
- Navigation fonts now use the CascadiaCode built-in font and cannot be changed.
- Proper select adapter with
is_srgbfilter check. - Switched to queue rendering instead of use staging_belt.
- Fixed leaks whenever buffer dropped map callbacks.
- Forked and embedded glyph-brush project to sugarloaf. Glyph-brush was originally created @alexheretic and is licensed under Apache-2.0 license.
- Upgrade wgpu to 0.17.1.
0.0.21
- Hide other applications in MacOS #262 by @sonbui00.
- Implemented
working-dirparameter to cli https://github.com/raphamorim/rio/issues/258. - Remove legacy icns icons from bundle.
0.0.20
- Fix retrieve foreground process name to tabs.
- Fix cursor disappearing in the first tab whenever a new tab is created with NativeTab.
- Fix settings for NativeTabs.
- New docs.
- Removal of RIO_CONFIG environment variable.
- Add ToggleFullscreen Action #229 (Ref: https://github.com/raphamorim/rio/pull/249)
- fix: Command + H can't hide rio on macOS (Ref: https://github.com/raphamorim/rio/pull/244).
- Added fontconfig to font loader.
- New Rio terminal logo.
- Update Rust to 1.72.1 (Ref: https://github.com/raphamorim/rio/pull/238).
- Enable CPU-specific optimizations on aarch64-apple-darwin (Ref: https://github.com/raphamorim/rio/pull/235).
- Use release profile with optimization level as 3 (Ref: https://github.com/raphamorim/rio/pull/236).
- Use fixed dependency versions in sugarloaf
- Added split support along with the following actions
SplitVertically,SplitHorizontallyandClosePane(support to split is still not available).
0.0.19
Breaking change
Configuration properties: window_height, window_width and window_opacity has been moved to a new window/background API:
# Window configuration
#
# • width - define the initial window width.
# Default: 600
#
# • height - define the initial window height.
# Default: 400
#
# • mode - define how the window will be created
# - "Windowed" (default) is based on width and height
# - "Maximized" window is created with maximized
# - "Fullscreen" window is created with fullscreen
#
[window]
width = 600
height = 400
mode = "Windowed"
# Background configuration
#
# • opacity - changes the background transparency state
# Default: 1.0
#
# • mode - defines background mode between "Color" and "Image"
# Default: Color
#
# • image - Set an image as background
# Default: None
#
[background]
mode = "Image"
opacity = 1.0
[background.image]
path = "/Users/rapha/Desktop/eastward.jpg"
width = 200.0
height = 200.0
x = 0.0
- Fix for retrieving shell environment variable when running inside of Flatpak sandbox (Ref: https://github.com/raphamorim/rio/issues/198).
- Rio terminal is now also available in crates.io: https://crates.io/crates/rioterm .
- Added
navigation.mode = "Plain", it basically disables all platform key bindings for tabs, windows and panels creation (Ref https://github.com/raphamorim/rio/issues/213). - Support for blinking cursor (Ref: https://github.com/raphamorim/rio/issues/137) (this option is not enabled by default).
- Migrated font-kit to a custom font loader.
- Support to MacOS tile window positioning feature (left or right).
- Added support to MacOS display native top bar items.
- Support to adaptive theme (theme selection based on user system theme variant
darkorlight). - Implemented
ScrollPageUp,ScrollPageDown,ScrollHalfPageUp,ScrollHalfPageDown,ScrollToTop,ScrollToBottom,ScrollLineUp,ScrollLineDown(Ref: https://github.com/raphamorim/rio/issues/206). - Support to
fonts.family(it overwrites regular, bold, bold-italic and italic font families). - Added a welcome screen UI.
- Added a settings UI.
- Exposes
RIO_CONFIGenvironment variable that contains the path of the configuration. - Rio creates a configuration file with all defaults if does not exist.
- Added
OpenConfigEditorkey binding for all platforms. - Configuration property
editorwas removed. - Created Assistant, Rio terminal UI for display error (Ref: https://github.com/raphamorim/rio/issues/168).
- Fix 'Backspace' keypress triggers Ctrl+h keybinding in Zellij instead of deleting character. (Ref: https://github.com/raphamorim/rio/issues/197).
- Implemented
TERM_PROGRAMandTERM_PROGRAM_VERSION(Ref: https://github.com/raphamorim/rio/issues/200). - Whenever native tabs is on disable macos deadzone logic.
0.0.18
- Upgraded to Rust 1.72.0.
- Fix delete key inputs square character.
- Fix Breadcrumb navigation crash.
0.0.17
Breaking changes
- Configuration
fontdoes not work anymore, a new configuration API of font selection has been introduced.
[fonts]
size = 18
[fonts.regular]
family = "cascadiamono"
style = "normal"
weight = 400
[fonts.bold]
family = "cascadiamono"
style = "normal"
weight = 800
[fonts.italic]
family = "cascadiamono"
style = "italic"
weight = 400
[fonts.bold-italic]
family = "cascadiamono"
style = "italic"
weight = 800
- Action
TabSwitchNextandTabSwitchPrevhas been renamed toSelectNextTabandSelectPrevTab.
Rest of 0.0.17 changelog
- Support to
NativeTab(MacOS only). - Support for kitty's keyboard protocol (
CSI u). Ref: https://sw.kovidgoyal.net/kitty/keyboard-protocol/ - Added new actions for tab selection:
SelectTab1,SelectTab2,SelectTab3,SelectTab4,SelectTab5,SelectTab6,SelectTab7,SelectTab8,SelectTab9,SelectLastTab. - Support lowercased action and fix overwrite for actions in custom key bindings.
- Added action
Minimizefor minimize Rio terminal window. - Added action
ClearHistoryfor clear terminal saved history. - Added action
ReceiveCharfor custom key bindings. - New default key bindings for Linux and Windows so that conflicts with readline key bindings are removed.
- Winit Version 0.29.1-beta.
- Allow paste with the middle mouse of the button (fixes https://github.com/raphamorim/rio/issues/123).
- Support startup notify protocol to raise initial window on Wayland/X11.
- Fix Double-tap by touchpad on the titlebar doesn't maximize/unmaximize the window in GNOME 44, Wayland.
0.0.16
- Fix tab/breadcrumb bug introduced in 0.0.15
- Introduce new configuration property:
navigation.macos-hide-window-button.
0.0.15
- Introduce configurable navigation with the following options:
CollapsedTab(default),Breadcrumb,TopTabandBottomTab.
An example of configuration:
[navigation]
mode = "BottomTab"
use-current-path = true
clickable = false
- Performance improvements with Sugarloaf de-duplication of input data.
- Before:
~253.5µs. - Now:
~51.5µs.
- Before:
- Introduce
navigation.use-current-pathwhich sets if a tab/breacrumb should be open from the current context path. - Fix rendering unicode with 1 width glyphs (fix #160).
- Increased max tabs from 9 to 20.
- Default colors
selection-foregroundandselection-backgroundhas changed. - Default colors
tabandtab-activehas changed.
0.0.14
- Implementation of custom key bindings (#117).
- Fix .deb packing in GH Actions.
- Fix key binding for switch tab next (MacOS only).
- Fix scroll when copying text outside of offset.
- Fix copy key bindings.
0.0.13
- Fix Fuzzy Finder issue (#132).
- Introduce Copa (Alacritty's VTE forked version to introduce new sequences/instructions in next versions).
- Upgraded Winit to 0.29.0-beta.0.
- Support for keybindings with dead keys.
Back/Forwardmouse buttons support in bindings.- Fix unconditional query of xdg-portal settings on Wayland.
- Fix
Maximizedstartup mode not filling the screen properly on GNOME Wayland. - Fix Default Vi key bindings for
Last/Firstactions not working on X11/Wayland. - Set
padding-xto 0 for non-macos. - Set
app_id/WM_CLASSproperty on Wayland/X11.
0.0.12
- Strip binary is on for release builds.
- Each paste or key binding that has writing leads to clear selection and scroll bottom.
- Fixed over-rendering when scrolling.
- Fix selection.
- Support to copy using VIM.
- Fix for MacOS deadzone changing cursor to draggable on window buttons.
- Fix for scroll using tmux.
0.0.11
- Fix for font styles using CachedSugar.
0.0.10
- Major refactor of Sugarloaf.
- Performance improvements around 80-110%.
- Introduced CachedSugar.
- Usage of PixelScale.
- Line-height support.
- Open new tab using the current tab directory.
- Fix some symbols break the horizontal and vertical alignment of lines (ref #148).
- Fix font size configuration is confusing (ref #139).
- Fix Glyph not rendered in prompt (ref: #135).
- Use fork by default in context tests.
- Updated terminfo.
- Increased default font size to 18.
- Move to next and prev tab using keybindings.
- Setting editor by keybindings and new property called
editorin configuration file. - Rio creates
.debpackages (canary and release). - Binary size optimization (ref: #152) by [@OlshaMB]
0.0.9
- Created "rio" terminfo.
- Breaking changes for configuration file regarding
Advanced. The configurationAdvancedhas moved to root level anddisable-render-when-unfocusedrenamed todisable-unfocused-render.
before
theme = "dracula"
[advanced]
disable-render-when-unfocused = true
now
theme = "dracula"
disable-unfocused-render = true
- Support to spawn and fork processes, spawn has became default. Spawn increases Rio compatibility in a broad range, like old MacOS versions (older or equal to Big Sur). However, If you want to use Rio terminal to fork processes instead of spawning processes, enable
use-forkin the configuration file:
use-fork = true
- Introduced
RIO_LOG_LEVELvariable usage. (e.g: RIO_LOG_LEVEL=debug rio -e "echo 1") - Increased max tabs from 6 to 9.
- Fix Incorrect cursor position when using multi-byte characters (Ref: #127)
- Fix bug "black screen with nearly zero interactivity" and new tab hanging.
- Fix cursor disappearing after resize.
- Introduction of
shellandworking_dirin configuration file. - Multi window support #97.
- Corrections on select and scroll experience (it was using wrongly font-bound for line calculation).
- Add selection color to the theme config (closed #125).
- Implemented Inverse (fix #92).
- Proper choose formats that matches with
TextureFormat::is_srgb(it fixed the Vulkan driver, related #122). - Corcovado: Filter windows crate dependency to only Windows targets (related: #119).
- Teletypewriter: Fixes for musl as target_env (related: #119).
- FreeBSD support, implementation by yurivict (Commit, Ref: #115)
0.0.8
- Added generation of
.msiand.exefiles to the release pipeline (stable and canary). - Support to Microsoft Windows.
- Ability to in|decrease font size using keyboard shortcut during session (ref: #109)
- Inverted Canary and Stable icons.
- ANSI mouse reports (e.g: scroll and click working on VIM).
- Scroll and apply selection.
- Semantic and line selection.
- Rio is available in Homebrew casks (ref github.com/Homebrew/homebrew-cask/pull/149824).
- Rio stable versions are notarized now.
- Migration of mio, mio-extras, mio-signal-hook to Corcovado.
- Changed default black color to
#4c4345. - Fix mouse position for when selecting text.
0.0.7
- Breaking changes for configuration file regarding
Styleproperty.
before:
performance = "High"
[style]
font-size = 18
theme = "lucario"
now:
performance = "High"
theme = "lucario"
font-size = 18
- Fix Background color not entirely set on vim #88
- Scroll now works for x11 and wayland.
- No longer renders to macos and x11 windows that are fully occluded / not directly visible.
- Introduced
window-opacityconfig property for WebAssembly and Wayland builds. - Add permissions instructions to Rio macos builds (Fix #99).
- Fixes for x11 and wayland rendering (Related: #98 and #100).
- Performance fixes (Related: #101).
- Sugarloaf WebAssembly support.
- Fixed resize for all contexts: removed the glitch when resizing and switching between tabs.
- Fixed cursor inconsistencies #95.
- Added command line interface support (
--help,--version,-eand--command). - Added a fallback for WPGU request device operation: downlevel limits, which will allow the code to run on all possible hardware.
- Added
padding-xto configuration. - Reload automatically when the configuration file is changed (#69).
- Fix
Ctrl+D. - Fix
exitcommand not closing the app (#87). - Changed default
light-blackcolor.
0.0.6
- Fix: support to clipboard in linux by @joseemds.
- Font style for custom fonts by @OlshaMB (closed #80 and #81)
- Text styles Underline and Strikethrough (closed #79).
- Update default colors for tabs/tabs-active.
- Tabs support.
- Fix rendering tab and hidden chars by replacing to space by @niuez, (closed #56).
- Block cursor hover a character and still allow it to be visible.
- Support to caret Beam and Underline cursor #67 by @niuez.
- Fix panics if custom font is not found #68.
- MacOs ignore alt key in cntrlseq (same behavior as Terminal.app, Hyper, iTerm and etecetera).
0.0.5
- Fix ctlseqs modifiers for bindings.
- Add RioEvent::ColorRequest events to write color updates on pty.
- Fix to render specific 24bit colors (#66) by @niuez.
- Cross build for arm64 and x86
- Bold and Italic support (https://github.com/raphamorim/rio/issues/33).
- Theme support (eae39bc81b5b561882b7a37b2c03896633276c27)
- Fix font-size dependency for serialization (f278102)
- Fix cursor visibility on VI mode and scroll (https://github.com/raphamorim/rio/issues/51)
- Performance fixes for rendering from teletypewriter updates.
- Fix scale issues for 1.0 scale factor or using monitor with different scale factor. (https://github.com/raphamorim/rio/issues/50)
- Improve
make pack-osx-armandmake pack-osx-x86to only contain Rio.app file. (https://github.com/raphamorim/rio/issues/54)
0.0.4
- Fix CPU large usage when scrolling.
- Task scheduler.
- Copy feature.
- Selection feature (selection doesn't work when scrolling yet).
- Change default cursor icon for Text (
winit::window::CursorIcon). - Scroll bottom when display offset is different than zero.
- Fix for user interaction "close Rio terminal" using UI interface (
ExitWithCode(0)). - Hide cursor when typing and make it visible again with scroll and cursor interactions.
- Implementation of paste files to string path.
0.0.3
- Added Input Method Engine (IME) support. Note: only works for preedit with single character now, which means that still need to fix for other keyboards as Japanese, Chinese [...].
- Common Keybindings and keybindings for MacOS.
- Allow to configure
option-as-altfor Winit on MacOs. Issue originally bought by Alacritty on Winit (https://github.com/rust-windowing/winit/issues/768). - Allow to configure environment variables through config file.
- Stabilization of Sugarloaf render on emojis, symbols and unicode.
0.0.2
log-levelas configurable (DEBUG,INFO,TRACE,ERROR,WARNandOFF).OFFby default.- Introduction of rendering engine called Sugarloaf.
- System font loader (tested and implemented for MacOs).
- Font loader with not native emoji font (emojis aren't stable yet).
- Rect renderer based on provided color (text background), stabilized for monospaced fonts.
0.0.1
- Basic move/goto functionalities.
- Initial definition of Rio default colors.
- Set and reset color by ANSI parser.
- Clear/Tabs functionalities.
- Grid introduction.
- Desktop delta scroll (up and down, without scrollbar UI component).
Teletypewriter2.0.0 usage for macos and linux.- Resize support.
- $SHELL login on macos, by default:
/bin/zsh --login(if $SHELL is settled as other could as run/bin/bash --login,/bin/fish --login...). - Cursor initial support (without VI mode).