Elegant terminal spinners for bash scripts and Lua
Roda (Portuguese for "wheel") is an elegant terminal spinner utility. It can be used as a standalone executable in bash scripts to show progress for long-running commands, or as a pure Lua library.
(Want to create a demo like this? Check out the recording documentation)
- Standalone Executable - perfect for wrapping slow commands in bash scripts
- 16 built-in spinner styles - dots, line, arc, bounce, and more
- Colorized output - 9 terminal colors supported
- Terminal states - succeed, fail, warn, info with symbols
- Dynamic text updates - change text while spinning
- Highly configurable - intervals, colors, prefixes, suffixes
- Minimal dependencies - only requires
luasystemandluv - Asynchronous - non-blocking execution
lx add rodaluarocks install rodaUse Roda to add elegant loading indicators to your bash scripts. Simply wrap your long-running commands with roda:
# Basic usage
roda --title "Installing dependencies..." -- npm install
# Custom spinner style
roda --title "Waiting for database..." --spinner "dots2" -- sleep 5
# Show output of the command (by default output is hidden while spinning)
roda --show-output --title "Building project..." -- make build| Option | Description |
|---|---|
--title TEXT |
Text to display next to the spinner |
--spinner NAME |
Spinner style to use (e.g., dots, line, arc) |
--show-output |
Display the command's stdout/stderr after it finishes |
-- |
Separates roda options from the command to execute |
Roda is compatible with Lua 5.1, 5.2, 5.3, 5.4, and LuaJIT.
local roda = require("roda")
-- Basic usage
local spinner = roda("Loading..."):start()
-- do work
spinner:succeed("Done!")
-- With options
local spinner = roda({
text = "Processing...",
spinner = "dots2",
color = "yellow",
})
spinner:start()
-- do work
spinner:succeed()Roda supports running child processes asynchronously without blocking the Lua runtime.
local roda = require("roda")
local spinner = roda("Installing dependencies...")
-- Execute a command asynchronously
spinner:execute("npm", {"install"})(function(exit_code, output)
if exit_code == 0 then
print("\nOutput:\n" .. output)
end
end)
-- Run the event loop to wait for async tasks
roda.run()Create a new spinner instance.
Parameters:
| Option | Type | Default | Description |
|---|---|---|---|
text |
string |
"" |
Text to display next to spinner |
prefixText |
string |
"" |
Text before spinner |
suffixText |
string |
"" |
Text after spinner text |
spinner |
string|table |
"dots" |
Spinner style name or custom frames |
color |
string|boolean |
"cyan" |
Spinner color, false to disable |
interval |
number |
varies | Milliseconds between frames |
stream |
file |
io.stderr |
Output stream |
hideCursor |
boolean |
true |
Hide cursor while spinning |
indent |
number |
0 |
Spaces to indent |
Returns: Spinner instance
:start(text?)- Start the spinner. Optionally set new text.:stop()- Stop and clear the spinner from the terminal.:succeed(text?)- Stop with green checkmark.:fail(text?)- Stop with red X.:warn(text?)- Stop with yellow warning.:info(text?)- Stop with blue info.:spin()- Render next frame. Call this in a loop for manual animation control.:setText(text)- Update spinner text while spinning.:setColor(color)- Change spinner color.:isSpinning()- Check if spinner is currently active.:stopAndPersist(opts)- Stop with custom symbol and text.:execute(command, args)- Execute a child process asynchronously while spinning. Returns a Thunk that expects anon_completecallback.
roda.run()- Run the libuv event loop. Blocks until all async tasks finish.
EUPL-1.2 (c) TJ Kolleh