# Agent Guide: Using Aisling
Aisling is a Rust crate for embeddable terminal text effects and loader animations. It is designed for TUI apps: it does not own the terminal or run its own event loop. Your app pulls frames from an iterator or asks loaders for the current frame and renders those frames into your UI buffer.
## Add The Crate
From crates.io:
```bash
cargo add aisling
```
Or in `Cargo.toml`:
```toml
[dependencies]
aisling = "0.1"
```
## Minimal Use
```rust
use aisling::{Effect, EffectConfig, EffectKind};
let config = EffectConfig::default()
.with_duration(80)
.with_seed(42);
let effect = Effect::with_config(EffectKind::Matrix, "Hello from Aisling", config);
for frame in effect.iter() {
// Render frame.cells() into your TUI buffer.
// Or use frame.to_ansi_string() for quick terminal demos.
}
```
For tqdm-style downloads or background tasks:
```rust
use aisling::{Loader, LoaderConfig, LoaderKind, LoaderProgress};
let loader = Loader::with_config(
LoaderKind::Tqdm,
LoaderConfig::default()
.with_width(64)
.with_label("download")
.with_unit("B")
.with_fraction(true),
);
let frame = loader.frame(tick, LoaderProgress::from_counts(downloaded, total));
```
## Rendering Frames
Each `Frame` is a fixed-size grid of styled `Cell` values.
```rust
for y in 0..frame.height() {
for x in 0..frame.width() {
let cell = frame.cell(x, y).unwrap();
let ch = cell.ch;
let fg = cell.colors.fg;
let bg = cell.colors.bg;
// Map ch, fg, and bg into your TUI renderer.
}
}
```
Useful helpers:
```rust
let plain = frame.to_plain_string();
let ansi = frame.to_ansi_string();
```
## Loader Animations
Use `Loader::frame(tick, progress)` when progress comes from your app, network transfer, build step, or task queue.
```rust
use aisling::{Loader, LoaderKind};
let loader = Loader::new(LoaderKind::Download);
let frame = loader.frame(tick, 0.42);
```
All loader names:
```text
bar
tqdm
blocks
meter
battery
gauge
dots
pulse
line
bounce
scanner
snake
pong
marquee
steps
download
upload
equalizer
wave
matrix
spark
orbit
brackets
crawl
braided
burn
decrypt
rain
thunderstorm
laseretch
vhstape
blackhole
fireworks
pour
synthgrid
beams
smoke
binarypath
bouncyballs
bubbles
colorshift
crumble
errorcorrect
expand
highlight
middleout
orbittingvolley
overflow
print
randomsequence
rings
scattered
slice
slide
spotlights
spray
swarm
sweep
unstable
waves
wipe
```
Use `Loader::line(tick, progress)` for a quick status string, or `LoaderKind::all()` to show every loader.
Effect-inspired loaders such as `burn`, `decrypt`, `laseretch`, `thunderstorm`, `blackhole`, `rings`, `swarm`, and `bouncyballs` are multi-row status animations. Give them at least five rows when possible.
## Selecting Effects
Use the enum directly:
```rust
let effect = Effect::new(EffectKind::Wipe, "Loading...");
```
Or parse from a command string:
```rust
use std::str::FromStr;
use aisling::EffectKind;
let kind = EffectKind::from_str("laseretch").unwrap();
```
All effect names:
```text
beams
binarypath
blackhole
bouncyballs
bubbles
burn
colorshift
crumble
decrypt
errorcorrect
expand
fireworks
highlight
laseretch
matrix
middleout
orbittingvolley
pour
print
rain
randomsequence
rings
scattered
slice
slide
smoke
spotlights
spray
swarm
sweep
synthgrid
thunderstorm
unstable
vhstape
waves
wipe
```
## What The Effects Do
| `beams` | Horizontal and vertical beams reveal the text. |
| `binarypath` | Binary glyphs move into character positions. |
| `blackhole` | Text collapses toward a center point, then expands back out. |
| `bouncyballs` | Characters fall and bounce into place. |
| `bubbles` | Bubble-like particles float and pop into text. |
| `burn` | Fire, heat, and smoke reveal the final characters. |
| `colorshift` | Existing text cycles through a moving gradient. |
| `crumble` | Text breaks apart, drifts, and reforms. |
| `decrypt` | Cipher characters resolve into final text. |
| `errorcorrect` | Wrong characters correct themselves over time. |
| `expand` | Characters expand outward from the center. |
| `fireworks` | Characters launch and burst into final positions. |
| `highlight` | A bright highlight band sweeps across the text. |
| `laseretch` | A scanning laser etches the text into place. |
| `matrix` | Digital rain resolves into the final text. |
| `middleout` | Text reveals from the middle outward. |
| `orbittingvolley` | Orbiting launchers fire characters inward. |
| `overflow` | Rows overflow and slide before settling. |
| `pour` | Characters pour downward into place. |
| `print` | Text appears like it is being printed. |
| `rain` | Characters rain from above. |
| `randomsequence` | Characters appear in randomized order. |
| `rings` | Characters orbit in rings and then land. |
| `scattered` | Scattered characters move into final positions. |
| `slice` | Text halves slide in from opposite sides. |
| `slide` | Rows slide in with alternating direction. |
| `smoke` | Smoke-like particles reveal the text. |
| `spotlights` | Moving spotlights illuminate the text. |
| `spray` | Characters spray from an origin point into place. |
| `swarm` | Characters swarm around before settling. |
| `sweep` | A two-pass sweep reveals gray then colored text. |
| `synthgrid` | A synth-style grid dissolves into text. |
| `thunderstorm` | Rain and lightning reveal glowing text. |
| `unstable` | Text jitters, explodes, and reassembles. |
| `vhstape` | VHS glitch/noise distortions settle into text. |
| `waves` | Wave motion passes through the characters. |
| `wipe` | A directional wipe reveals the final text. |
## Configuration Cheatsheet
```rust
use aisling::{Color, EffectConfig, Gradient, GradientDirection};
let config = EffectConfig::default()
.with_duration(120)
.with_seed(7)
.with_canvas_size(48, 8)
.with_gradient(
Gradient::new(vec![Color::rgb(255, 170, 60), Color::rgb(80, 110, 95)], 24),
GradientDirection::Horizontal,
);
```
Key fields:
| `duration` | Number of animation frames. |
| `hold_final_frames` | Extra frames to keep the final text visible. |
| `seed` | Deterministic seed for repeatable animation. |
| `gradient` | Color palette for final/effect colors. |
| `gradient_direction` | Horizontal, vertical, diagonal, or radial color mapping. |
| `easing` | Global easing function for movement/reveal timing. |
| `existing_color_handling` | Preserve or ignore ANSI colors from input text. |
| `no_color` | Disable colors. |
| `canvas_width`, `canvas_height` | Fixed frame size. |
| `tab_width` | Tab expansion width. |
## Agent Notes
Use `EffectKind::all()` when you need to show every effect.
Use `Effect::final_frame()` when you only need the completed text state.
Use `Effect::frames()` for short demos or tests. Use `Effect::iter()` in real TUI loops to avoid holding all frames if you do not need them.
For quick local demos in this repository:
```bash
./run.sh list
./run.sh wipe "Hello"
./run.sh showcase
./run.sh showcase --rainbow
./run.sh showcase --theme industrial
./run.sh loader tqdm --label download
./run.sh loaders --seconds 20 --fps 6
./run.sh list-loaders
./test.sh -loaders
./loaders.sh
./loaders.sh --seconds 120 --focus-seconds 8
./story.sh
./story.sh --seconds 90 --fps 12
```
`./run.sh loaders` and `./test.sh -loaders` render every loader in a single grid. `test.sh -loaders` intentionally uses slower playback so the effect-style loaders are readable.
`./loaders.sh` runs the loader command deck. It keeps every `LoaderKind` visible in a catalog strip, gives one loader a large story-style focus pane, keeps six surrounding fake transfer lanes running at different speeds, and supports left/right arrow keys in an interactive terminal.
`./story.sh` runs the composed Knott Dynamics story demo. It loads the text embedded in `test.sh`, then mixes text effects, fake downloads, and exotic loaders in one TUI-style screen.
The showcase defaults to a curated bold palette and a masonry pane layout. Matrix and other wide/tall effects get larger panes when the terminal has enough space. Use `--rainbow` only when you want the old full-spectrum theme.