opal
๐ Opal
Next-Generation Terminal User Interface (TUI) & CLI DSL Framework for Crystal
Pure Crystal. Zero external C library dependencies (no ncurses). Native Windows, Linux, and macOS support.
๐ What is Opal?
Opal is an all-in-one terminal framework for Crystal designed to build world-class command-line interfaces, micro-interactive prompts, and full-screen terminal applications.
It merges the best paradigms from modern terminal engineering into a cohesive, idiomatic Crystal DSL:
- ๐ต The Elm Architecture (TEA) โ Pure, predictable state management inspired by Bubble Tea.
- ๐จ Declarative Fluent Styling & Themes โ Lipgloss-inspired composable styling, borders, 24-bit TrueColor, visual string width, and curated themes (Catppuccin, Dracula, TokyoNight, Nord, Gruvbox).
- โก Flicker-Free Delta Rendering โ Blessed-inspired double buffering that computes minimal character delta updates for 60fps full-screen performance.
- ๐ ๏ธ Expressive CLI App DSL โ Clap/Commander-style subcommands, typed flags, choices, global flag propagation, and shell completion (
bash,zsh,fish). - ๐ Multi-Field Form & Wizard DSL โ All fields visible simultaneously, tab navigation, live inline validation, and instant submission.
- ๐ Live Fuzzy Search & Filter โ Instant keystroke matching with rune highlighting and split preview pane (
Opal.filter). - ๐ Rich Data Visualizations โ Unicode block Sparklines, horizontal/vertical BarCharts, percentage Gauges, and hierarchical Trees.
- ๐ช Layer Blending, Modals & Toasts โ Buffer
blit, backdrop dimming, centered confirmation dialogs, and non-blocking toast queues. - ๐ Terminal Markdown Viewer โ Styled headers, blockquotes, lists, and syntax colorized code blocks.
- ๐ฎ Ghost-Text Autocomplete & Input DSL โ Modern fish/zsh-style inline ghost text autocomplete on
Tab, flexible interactive line editing, and declarative key bindings. - ๐ฑ๏ธ Hit-Test Mouse Routing DSL โ SGR extended mouse tracking with declarative click, drag, and scroll zones.
- ๐ OSC 8 Links & OSC 52 Clipboard โ Native clickable terminal hyperlinks and desktop clipboard copying across SSH and local sessions.
๐ฆ Installation
Add Opal to your project's shard.yml:
dependencies:
opal:
github: sol-vin/opal
version: ~> 0.1.0
Then install dependencies:
shards install
Require Opal in your Crystal code:
require "opal"
๐ Table of Contents
- Quick Start
- Architecture Overview
- Multi-Field Form & Wizard DSL
- Live Fuzzy Search & Filter
- Data Visualizations
- Buffer Blitting, Modals & Toasts
- Terminal Markdown Viewer
- Theme Engine & Semantic Colors
- Command Palette Overlay
- OSC 8 Hyperlinks & OSC 52 Clipboard
- Animation & Easing Engine
- CLI Application DSL
- Fluent Styling & Layout
- Interactive Prompts
- Autocomplete & Ghost Text DSL
- KeyMap & MouseMap DSLs
- The Elm Architecture (TEA)
- Testing with MockDriver
- Examples
- License
๐ Quick Start
1. Build an Interactive Setup Wizard with Opal.form
require "opal"
result = Opal.form("Project Setup") do |f|
f.text "name", "Project Name:", default: "my-app", required: true
f.password "token", "API Token:", min_length: 8
f.select "db", "Database:", ["PostgreSQL", "SQLite", "MySQL"]
f.multi_select "addons", "Addons:", ["Redis", "Elasticsearch", "GraphQL"]
f.confirm "deploy", "Auto-deploy to staging?", default: true
end
if config = result
puts "Created project #{config["name"]} using #{config["db"]}!"
end
2. Live Fuzzy Filter with Split Preview
require "opal"
branches = ["main", "staging", "feat/auth", "feat/fuzzy-finder", "fix/timeout"]
selected = Opal.filter(
items: branches,
title: "Git Switcher",
preview: ->(b : String) { "Branch #{b}\nStatus: Clean\nUpdated: 5m ago" }
)
puts "Switched to branch: #{selected}" if selected
๐ Multi-Field Form & Wizard DSL
Traditional CLI prompts ask one question at a time and prevent reviewing earlier inputs. Opal.form presents an interactive card where all fields are visible simultaneously, users navigate using Tab / Shift+Tab, and live validation catches mistakes instantly.
result = Opal.form("New Microservice") do |f|
f.text "service", "Service Name:", required: true
f.text "port", "HTTP Port:", default: "8080"
f.password "secret", "Secret Key:", min_length: 6
f.select "tier", "Hosting Tier:", ["Small", "Medium", "Large"]
f.multi_select "plugins", "Plugins:", ["Metrics", "Tracing", "Auth"]
f.confirm "enabled", "Enable service immediately?", default: true
# Custom real-time validation
f.validate "port" do |val|
(val.to_i? && (1024..65535).includes?(val.to_i)) ? nil : "Port must be 1024-65535"
end
end
๐ Live Fuzzy Search & Filter
Fast, keystroke-responsive fuzzy filtering inspired by fzf:
- Instant substring matching with word boundary bonuses.
- Highlights matched characters in bold cyan.
- Split preview pane for viewing item details.
choice = Opal.filter(
items: Dir["src/**/*.cr"],
title: "Fuzzy File Finder",
preview: ->(path : String) { File.read(path).lines.first(15).join("\n") }
)
๐ Data Visualizations
Render rich dashboards and metrics without graphics libraries:
Sparklines
# Output: โโโโโโโโโโ
puts Opal::UI::Sparkline.render_to_string([10.0, 15.0, 25.0, 80.0, 95.0, 60.0])
BarCharts, Gauges & Trees in UI Trees
Opal.render_ui(width: 70, height: 20) do |ui|
ui.vstack(spacing: 1) do |v|
# Percentage Gauge
v.gauge 0.76, label: "Disk Usage", color: :yellow
# Horizontal Bar Chart
v.barchart(title: "Memory Allocation") do |bc|
bc.bar "Web", 420, color: :green
bc.bar "Worker", 850, color: :cyan
bc.bar "DB", 1200, color: :red
end
# Hierarchical Tree
v.tree(title: "Service Graph") do |t|
t.node("API Gateway", icon: "๐") do |gateway|
gateway.add("Auth Service", icon: "๐")
gateway.add("Search Node", icon: "๐")
end
end
end
end
๐ช Buffer Blitting, Modals & Toasts
Floating Modal Dialog
Center a dialog box over any screen buffer with automatic background dimming:
modal = Opal::UI::Modal.new(
title: "Confirm Deletion",
message: "Are you sure you want to drop database 'prod'?",
buttons: ["Cancel", "Confirm Drop"],
selected_button: 1
)
modal.render(buffer, 0, 0, 80, 24)
Toast Notifications
Stack floating alerts in the top-right corner with auto-dismiss timers:
toasts = Opal::UI::ToastManager.new
toasts.add("Build Succeeded", "All 124 tests passed", level: :success, duration_ms: 3000)
toasts.add("Disk Warning", "Free space below 10%", level: :warning)
toasts.render_overlay(buffer, position: :top_right)
๐ Terminal Markdown Viewer
Convert Markdown documents into styled ANSI terminal text:
doc = <<-MD
# Opal Framework v1.0
Welcome to **Opal**! Build *beautiful* CLIs in Crystal.
### Features
- Zero external C dependencies
- 60fps delta rendering
```crystal
require "opal"
puts "Hello world!"
"Simplicity is prerequisite for reliability." MD
puts Opal.render_markdown(doc, width: 80)
---
## ๐จ Theme Engine & Semantic Colors
Opal includes pre-registered designer palettes and semantic color tokens:
```crystal
# Switch theme dynamically
Opal.theme = :catppuccin_mocha # :dracula, :nord, :tokyo_night, :gruvbox, etc.
# Semantic color tokens
theme = Opal.theme
style = Opal.style
.foreground(theme.primary)
.background(theme.surface)
.border_foreground(theme.border)
๐ Command Palette Overlay
Press Ctrl+P or Ctrl+K to summon an instant Spotlight action launcher:
palette = Opal::UI::CommandPalette.new
palette.add("git:commit", "Commit changes", category: "Git", shortcut: "ctrl+c") { commit_flow }
palette.add("file:open", "Open file picker", category: "File", shortcut: "ctrl+o") { open_picker }
๐ OSC 8 Hyperlinks & OSC 52 Clipboard
# Clickable hyperlink in modern terminals
puts Opal.hyperlink("View Source on GitHub", "https://github.com/sol-vin/opal")
# Copy directly to OS desktop clipboard over SSH and local sessions
Opal.copy_to_clipboard("API_KEY_SECRET_12345")
โฑ๏ธ Animation & Easing Engine
Smooth transitions, progress bars, and color interpolation:
# Easing functions
t = Opal::Animation.ease(:ease_in_out_cubic, 0.5)
# Color interpolation (e.g. green to red as CPU load increases)
normal_color = Opal::Color.green
alert_color = Opal::Color.red
current_c = Opal::Color.lerp(normal_color, alert_color, 0.75)
๐ ๏ธ CLI Application DSL
app = Opal.cli("deployer", "Cloud deployment manager", "0.4.0") do
option "-v", "--verbose", "Enable debug logging", type: :bool
command "deploy", "Deploy application containers" do
argument "service", "Service name to deploy"
option "-c", "--concurrency=NUM", "Max concurrency", type: :int, default: 3
run do |ctx|
svc = ctx.argument("service")
puts "Deploying #{svc} (concurrency: #{ctx.int("concurrency")})..."
end
end
end
app.run(ARGV)
๐ต The Elm Architecture (TEA)
Build reactive terminal applications with pure state transitions:
record CounterModel, count : Int32 = 0 do
include Opal::Tea::Model
def init : Opal::Tea::Cmd
Opal::Tea::Cmd.none
end
def update(msg : Opal::Tea::Msg) : {Opal::Tea::Model, Opal::Tea::Cmd}
case msg
when Opal::Tea::KeyMsg
case msg.key
when "up", "k" then {CounterModel.new(count + 1), Opal::Tea::Cmd.none}
when "down", "j" then {CounterModel.new(count - 1), Opal::Tea::Cmd.none}
when "q" then {self, Opal::Tea::Cmd.quit}
else {self, Opal::Tea::Cmd.none}
end
else
{self, Opal::Tea::Cmd.none}
end
end
def view : String
"Counter: #{count} (Press โ/k, โ/j, q to quit)"
end
end
Opal::Tea::Program.new(CounterModel.new).run
๐งช Testing with MockDriver
Test full TUI interactions headlessly without opening an actual terminal:
require "spec"
require "opal"
describe "Counter" do
it "increments on keypress" do
model = CounterModel.new
new_model, cmd = model.update(Opal::Tea::KeyMsg.new("k"))
new_model.as(CounterModel).count.should eq(1)
end
end
๐ Examples
Explore all runnable examples in the examples/ directory:
01_lapis_revamp.crโ Comprehensive CLI developer toolchain with subcommands, typed options, and table reports.02_interactive_prompts.crโ Setup wizard showingask,confirm,select,multi_select,spinner, andprogress.03_tea_counter.crโ Classic Elm Architecture counter application with keyboard controls.04_system_dashboard.crโ Live full-screen system monitor dashboard with charts, tables, and async metrics updates.05_autocomplete_and_input.crโ Interactive REPL showcasing Tab autocompletion, inline ghost-text hints, keymaps, mouse routing, and terminal inspection.06_rich_form_wizard.crโ Multi-field form wizard with live validation, password masking, select menus, and checkboxes.07_fuzzy_finder.crโ Live fuzzy search list with rune highlighting and split preview pane.08_dataviz_dashboard.crโ Rich analytics dashboard with Sparklines, BarCharts, Gauges, Trees, and Themes.09_markdown_and_overlays.crโ Terminal Markdown viewer, Modal dialogs, and floating Toast notifications.
Run any example:
crystal run examples/06_rich_form_wizard.cr
crystal run examples/08_dataviz_dashboard.cr
crystal run examples/09_markdown_and_overlays.cr
๐ Cross-Platform Support
| Platform | Terminal Backend | Colors | Mouse Support |
|---|---|---|---|
| Linux | POSIX termios, VT100, SGR |
TrueColor, 256, ANSI 16 | Yes (SGR 1006) |
| macOS | POSIX termios, VT100, SGR |
TrueColor, 256, ANSI 16 | Yes (SGR 1006) |
| Windows | Win32 Console API (ENABLE_VIRTUAL_TERMINAL_PROCESSING) + ANSI VT100 |
TrueColor, 256, ANSI 16 | Yes (SGR 1006) |
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
opal
- 0
- 0
- 0
- 3
- 0
- about 11 hours ago
- September 29, 2026
MIT License
Tue, 29 Sep 2026 12:40:50 GMT