tui-shimmer: How a Terminal Learns to Shimmer

A tiny Rust library turns loading text into a moving highlight, with a cosine curve, true-color blending, and a fallback path for older terminals.

8 min read • View on GitHub • More from vinhnx

A wide terminal window sits on a clean white field while a soft diagonal band of brightness moves across several lines of text. The image explains how the library adds motion and polish to a normally static loading state without leaving the terminal's visual language.
The effect is simple to describe and harder to fake well. It has to feel native to a terminal, not borrowed from a browser.

Demo usage from my VT Code coding agent.

vinhnx, Author/Maintainer · tui-shimmer v0.1.3
Key Takeaways

A loading state in a terminal usually does one job: it tells you to wait. tui-shimmer does the same job, but it gives the pause a pulse. That sounds cosmetic until you realize how much trust and clarity live inside a loading animation, especially in a tool that people use all day.

The terminal, but less terminal

Most TUI loading states are functional and forgettable. Spinners spin, progress bars fill, and static placeholders hold space. `tui-shimmer` borrows the emotional signal of web shimmer, then translates it into terminal terms: spans, colors, character positions, and a very small performance budget.

What Vinh Nguyen is really shipping

The crate is maintained by Vinh Nguyen, who also uses the effect in his VT Code agent. That matters because it suggests this is not a novelty extract from a demo reel. It reads like utility that escaped from a real product path and got cleaned up for other Ratatui users.

A WSJ-style hedcut portrait of Vinh Nguyen rendered in black ink on a pure white background. The portrait identifies the maintainer behind tui-shimmer and gives the origin story a human anchor.

How the shimmer is actually built

The implementation is small, but it is not casual. The library takes elapsed time, folds it into a looping phase, turns that phase into a moving center point, then computes character-level intensity around that center. From there it chooses either smooth RGB blending or a discrete ANSI fallback, depending on what the terminal can really do.

The library is easiest to understand as a pipeline. Time becomes phase, phase becomes intensity, and intensity becomes style.

let phase = (elapsed.as_secs_f32() / SHIMMER_SWEEP_SECONDS).rem_euclid(1.0);
let distance = (character_index as f32 - shimmer_center(phase)).abs();
let intensity = intensity_lut(distance);

let style = if supports_true_color() {
    blend_rgb(base_color, Color::White, intensity)
} else {
    ansi_gray_bucket(intensity)
};

append_span_or_merge(text_chunk, style);

Two details make the implementation feel mature. First, the cosine-based look-up table avoids a harsh linear sweep, so the shimmer reads as a soft band rather than a blinking stripe. Second, adjacent characters with the same style are merged into spans, which keeps the rendering path lean instead of spraying the terminal with tiny objects.

Why the fallback path matters

A close-up of a terminal text line with two visual branches beneath it. One branch shows a smooth true-color blend, while the other steps through three ANSI grayscale levels. The image explains that the library is built to degrade gracefully when terminal color support is limited.
The fallback path is not an afterthought. It is the difference between a polished effect and a brittle one.

This is where `tui-shimmer` earns its credibility. It checks the environment, looks for true color support, and still produces a sensible result when the terminal is older or more constrained. That is the real product decision here. A pretty animation that breaks on half the terminals in the wild is not polish, it is fragility.

Compared with the usual loading states

PatternWhat it signalsStrengthWeaknessBest fit
SpinnerWork is ongoingTiny, universal, cheapSays nothing about structure or durationShort waits and background tasks
Progress barA task has measurable completionGreat when the finish line is realMisleading when the endpoint is fuzzyKnown-duration jobs
Static skeletonContent will arrive hereSets layout expectationsFeels frozen rather than aliveFeed and panel placeholders
tui-shimmerWait, but with rhythm and polishAdds motion without leaving the terminalDepends on color capability for its best lookIndeterminate loads in modern TUIs

The comparison is not about feature parity. It is about information quality. A spinner says the system is busy. A shimmer says the UI is alive, the content matters, and the wait itself has been designed.

What this says about TUIs now

`tui-shimmer` is small enough to miss if you only scan for headline features. That would be a mistake. It shows that terminal interfaces are moving past mere utility, toward motion, nuance, and brand texture, while still respecting the terminal as a constrained medium. In other words, polish is no longer a contradiction in TUI design.