ratkit
Comprehensive Rust TUI component library built on ratatui 0.29, providing 21 feature-gated modules (primitives, widgets, services) for building rich terminal applications.
This file provides a complete reference for working with the ratkit codebase. The repository is organized as a single crate at the root level with feature-based modularity. Use this guide to understand component relationships, find APIs, and follow established patterns when implementing new features.
Agent Operating Rules
- Single crate at root: All code is in
src/with 21 feature flags (e.g.,button,pane,markdown-preview) - Enable features explicitly: No default features; add required features to Cargo.toml (e.g.,
features = ["button", "dialog"]) - Cross-feature dependencies: Some features auto-enable others (e.g.,
tree-viewenableswidget-event,repo-watcherenablesfile-watcherandgit-watcher) - Use
justfor all operations: Build (just build), test (just test), check (just check), demos (just demo) - Run examples with
--featuresflag: Examples require their specific features (e.g.,--features markdown-preview) - Import from crate root: All public APIs are re-exported from
ratkit::(e.g.,use ratkit::Button) - StatefulWidget pattern: Complex widgets require separate state structs persisted in app state
- Event loop polling: Services require regular
check_for_changes()calls in the event loop - Mouse capture required: Enable crossterm mouse capture for interactive widgets
- Persist widget state: Never create widget state in render loops - store in app struct
- Validate before commits: Run
just check(format + lint + test) before committing - Verify feature flags: Compilation errors often indicate missing feature flags in Cargo.toml
Environment and Version Constraints
- Rust 1.70+ required (workspace.rust-version in Cargo.toml)
- ratatui 0.29 as the underlying rendering library
- crossterm 0.28 for terminal input/events
- tokio for async runtime
- Single crate at root with 21 feature flags (no workspace members)
- 23 examples in
examples/(moved fromcrates/ratkit/examples/) - Optional external deps: notify (file watching), reqwest (ai-chat), pulldown-cmark/syntect (markdown), similar (code-diff)
Quick Task Playbooks
Run an example
- Where to edit: N/A
- Related files:
examples/ - Validation:
cargo run --example button_button_demo --features button
Run with just
- Where to edit: N/A
- Related files:
justfile - Validation:
just demo(interactive picker) orjust demo-md,just demo-term, etc.
Build with specific features
- Where to edit:
Cargo.toml(root level) - Related files: Feature definitions
- Validation:
cargo build --features "button,pane,dialog"
Build all features
- Where to edit: N/A
- Related files: All source files
- Validation:
cargo build --all-features
Run full verification
- Where to edit: N/A
- Related files: All source files
- Validation:
just check(runs fmt-check, lint, test)
Getting Started
# Cargo.toml - enable specific features
[dependencies]
ratkit = { version = "0.2", features = ["button", "dialog", "pane"] }use ratkit::prelude::*;
use ratatui::Frame;
struct MyApp;
impl CoordinatorApp for MyApp {
fn on_event(&mut self, event: CoordinatorEvent) -> LayoutResult<CoordinatorAction> {
match event {
CoordinatorEvent::Keyboard(keyboard) => {
if keyboard.is_escape() {
return Ok(CoordinatorAction::Quit);
}
}
_ => {}
}
Ok(CoordinatorAction::Continue)
}
fn on_draw(&mut self, frame: &mut Frame) {
// Render your UI here
}
}
fn main() -> std::io::Result<()> {
let app = MyApp;
run(app, RunnerConfig::default())
}Workspace Overview
The ratkit workspace contains a single crate with 21 feature-gated modules organized into:
- Primitives (11 modules): Core UI building blocks in
src/primitives/
- button, pane, dialog, toast, statusline, scroll, menu_bar, resizable_grid, tree_view, widget_event, termtui
- Widgets (6 modules): Higher-level composite widgets in
src/widgets/
- markdown_preview, code_diff, ai_chat, hotkey_footer, file_system_tree, theme_picker
- Services (4 modules): Background monitoring services in
src/services/
- file_watcher, git_watcher, repo_watcher, hotkey_service
- Core Runtime (1 module): Application lifecycle in
src/core/
All modules follow feature-gated compilation. Enable only what you need.
Core Runtime
The core runtime provides the application lifecycle, event routing, and element management for terminal UI applications.
Key Components
- CoordinatorApp trait: Applications implement this to receive events and render
- run() / run_with_diagnostics(): Entry points to start the event loop
- Element trait: Implement for custom widgets that integrate with the coordinator
- RunnerConfig: Configuration for tick rate, layout debounce, mouse capture
Architecture
- Three-region layout: Top, Center, Bottom
- Focus management with stack and traversal
- Mouse routing with z-order hit testing
- Element registry with weak references
UI Primitives
Core UI building blocks for TUI applications, located in src/primitives/.
Feature Flags
Each primitive has an individual feature flag:
button,pane,dialog,toast,statusline,scrollmenu-bar(enableswidget-event)resizable-gridtree-view(enableswidget-event)widget-eventtermtui
Common Patterns
- Builder pattern with
new()andwith_*methods - StatefulWidget pattern for complex state
- Event emission via
WidgetEvent - Mouse/keyboard interaction support
Complex Widgets
Higher-level composite widgets in src/widgets/.
Feature Flags
markdown-preview- Most complex (syntax highlighting, TOC, themes, selection)code-diff- VS Code-style diff viewerai-chat- AI chat interface (requires reqwest, serde)hotkey-footer- Keyboard shortcut footerfile-system-tree- File browser with deviconstheme-picker- Theme selector with 25+ themes
External Dependencies
| Widget | Dependencies |
|---|---|
| ai-chat | reqwest, serde, serde_json |
| markdown-preview | pulldown-cmark, syntect, syntect-tui, notify, arboard, dirs |
| code-diff | similar |
| file-system-tree | devicons |
Services
Background monitoring services in src/services/.
Feature Flags
file-watcher- Watch files/directories for changesgit-watcher- Monitor git repository staterepo-watcher- Combined file + git watching (enables file-watcher and git-watcher)hotkey-service- Global hotkey registration and management
Common Dependencies
All watcher services use the notify crate for filesystem events.
Usage Cards
CoordinatorApp
- Use when: Building any ratkit TUI application
- Enable/Install: Core runtime, no feature flag needed
- Import/Invoke:
use ratkit::prelude::*; - Minimal flow:
1. Define struct implementing CoordinatorApp 2. Implement on_event() to handle events 3. Implement on_draw() to render UI 4. Call run(app, RunnerConfig::default())
- Key APIs:
on_event(),on_draw(),on_layout_changed() - Pitfalls: Runner takes ownership; wrap shared state in
Arc<RwLock<>> - Source:
src/coordinator.rs,src/runner_helper.rs
run()
- Use when: Starting the main application event loop
- Enable/Install: Core runtime, no feature flag
- Import/Invoke:
use ratkit::{run, run_with_diagnostics}; - Minimal flow:
1. Create app implementing CoordinatorApp 2. Create RunnerConfig::default() or custom 3. Call run(app, config) or run_with_diagnostics(app, config) for debug overlay
- Key APIs:
run(),run_with_diagnostics(),RunnerConfig - Pitfalls: Blocks until exit; handles terminal init/cleanup
- Source:
src/runner_helper.rs
Element
- Use when: Creating custom widgets that integrate with coordinator
- Enable/Install: Core runtime
- Import/Invoke:
use ratkit::Element; - Minimal flow:
1. Implement Element trait for your widget 2. Define id(), on_render(), on_keyboard(), on_mouse() 3. Register with ElementMetadata and region
- Key APIs:
id(),on_render(),on_keyboard(),on_mouse(),on_focus_gain(),on_focus_loss(),on_tick() - Pitfalls: Registry stores weak refs - keep strong refs in app state; return
truewhen handling events - Source:
src/registry.rs
Button
- Use when: Clickable button with hover states
- Enable/Install:
features = ["button"] - Import/Invoke:
use ratkit::Button; - Minimal flow:
1. Create Button::new("Label") 2. Call update_hover(x, y) on mouse move 3. Call is_clicked(x, y) on click 4. Render with render_with_title()
- Key APIs:
new(),normal_style(),hover_style(),update_hover(),is_clicked() - Pitfalls: State must persist in app struct
- Source:
src/primitives/button/widget.rs
Pane
- Use when: Styled panel container with title/icon/padding
- Enable/Install:
features = ["pane"] - Import/Invoke:
use ratkit::Pane; - Minimal flow:
1. Create Pane::new("Title") 2. Chain builder methods: with_icon(), with_padding(), border_style() 3. Render as widget
- Key APIs:
new(),with_icon(),with_padding(),with_uniform_padding(),border_style() - Pitfalls: Padding reduces inner content area
- Source:
src/primitives/pane/mod.rs
Dialog
- Use when: Modal dialogs for confirmation/information
- Enable/Install:
features = ["dialog"] - Import/Invoke:
use ratkit::{Dialog, DialogState, DialogType}; - Minimal flow:
1. Create Dialog::new(title, message) or use builder (Dialog::confirm()) 2. Set buttons with .buttons(vec!["Yes", "No"]) 3. Create DialogState::new() for button selection 4. Render with DialogWidget
- Key APIs:
new(),info(),warning(),error(),success(),confirm(),buttons() - Pitfalls: DialogState must persist; uses StatefulWidget pattern
- Source:
src/primitives/dialog/
Toast
- Use when: Auto-dismissing notifications
- Enable/Install:
features = ["toast"] - Import/Invoke:
use ratkit::{ToastManager, ToastLevel}; - Minimal flow:
1. Create ToastManager::new() in app state 2. Add toasts via .success(), .error(), .info(), .warning() 3. Call cleanup() before render 4. Render with render_toasts()
- Key APIs:
ToastManager::new(),.add(),.success(),.error(),.cleanup() - Pitfalls: Must call
cleanup()to remove expired; doesn't auto-expire - Source:
src/primitives/toast/
TreeView
- Use when: Hierarchical data with expand/collapse/selection
- Enable/Install:
features = ["tree-view"](auto-enables widget-event) - Import/Invoke:
use ratkit::{TreeNode, TreeView, TreeViewState, TreeNavigator}; - Minimal flow:
1. Build TreeNode hierarchy 2. Create TreeView::new(nodes) with render_fn 3. Create TreeViewState::new() for selection/expansion 4. Use TreeNavigator for keyboard handling
- Key APIs:
TreeNode::new(),TreeView::new(),TreeViewState::new(),TreeNavigator::new() - Pitfalls: TreeViewState must persist; TreeNavigator handles all keyboard nav
- Source:
src/primitives/tree_view/
MarkdownWidget
- Use when: Rendering markdown with syntax highlighting, TOC, themes
- Enable/Install:
features = ["markdown-preview"](complex dependencies) - Import/Invoke:
use ratkit::widgets::markdown_preview::{MarkdownWidget, ScrollState, SourceState,...}; - Minimal flow:
1. Create state structs (ScrollState, SourceState, etc.) in app state 2. Create MarkdownWidget::new(content, scroll, source,...) 3. Handle keyboard with handle_key() 4. Render with ratatui
- Key APIs:
new(),handle_key(),handle_mouse(),.show_toc(),.show_scrollbar() - Pitfalls: Requires mouse capture enabled; state must persist across renders
- Source:
src/widgets/markdown_preview/widgets/markdown_widget/
FileWatcher
- Use when: Detecting file/directory changes
- Enable/Install:
features = ["file-watcher"](uses notify crate) - Import/Invoke:
use ratkit::services::file_watcher::FileWatcher; - Minimal flow:
1. Create FileWatcher::for_file() or FileWatcher::for_directory() 2. Call watch(path) 3. Poll check_for_changes() in event loop 4. Get changes with get_changed_paths()
- Key APIs:
for_file(),for_directory(),watch(),check_for_changes(),get_changed_paths() - Pitfalls: Must poll regularly;
get_changed_paths()clears queue; debounced (100ms/200ms) - Source:
src/services/file_watcher/
HotkeyService
- Use when: Centralized hotkey management with scope filtering
- Enable/Install:
features = ["hotkey-service"] - Import/Invoke:
use ratkit::services::hotkey_service::{Hotkey, HotkeyRegistry, HotkeyScope}; - Minimal flow:
1. Create HotkeyRegistry::new() 2. Register hotkeys with Hotkey::new(key, description).scope(scope) 3. Set active scope with set_active_scope() 4. Query with lookup(key, scope) in event loop
- Key APIs:
HotkeyRegistry::new(),register(),lookup(),set_active_scope() - Pitfalls: Uses
&'static strfor scopes; must handle crossterm events separately - Source:
src/services/hotkey_service/
API Reference
Core Runtime
| Component | Key APIs |
|---|---|
| CoordinatorApp | on_event(), on_draw(), on_layout_changed() |
| run | run(), run_with_diagnostics() |
| Element | id(), on_render(), on_keyboard(), on_mouse(), on_focus_gain(), on_focus_loss(), on_tick() |
| RunnerConfig | tick_rate, layout_debounce, mouse_router_config |
Primitives
| Primitive | Key APIs |
|---|---|
| Button | new(), normal_style(), hover_style(), update_hover(), is_clicked() |
| Pane | new(), with_icon(), with_padding(), with_uniform_padding(), border_style() |
| Dialog | new(), info(), warning(), error(), success(), confirm(), buttons() |
| Toast | ToastManager::new(), .add(), .success(), .error(), .cleanup() |
| TreeView | TreeNode::new(), TreeView::new(), TreeViewState::new(), TreeNavigator::new() |
| Scroll | calculate_scroll_offset() |
Services
| Service | Key APIs |
|---|---|
| FileWatcher | for_file(), for_directory(), watch(), check_for_changes(), get_changed_paths() |
| GitWatcher | new(), with_config(), watch(), check_for_changes() |
| RepoWatcher | new(), with_config(), watch(), check_for_changes(), get_change_set() |
| HotkeyRegistry | new(), register(), lookup(), set_active_scope() |
Common Pitfalls
Feature Flags
- No default features: Must explicitly enable every feature you use
- Cross-feature deps:
tree-viewenableswidget-event;repo-watcherenablesfile-watcherandgit-watcher - Missing feature errors: "unresolved import" usually means missing feature flag
State Management
- StatefulWidget pattern: Complex widgets require persistent state in app struct
- Never create state in render: Always store widget state in app struct
- Weak references: Element registry stores weak refs - keep strong refs in app
Event Handling
- Return values: Return
truewhen consuming events,falseto propagate - Mouse capture: Must enable crossterm mouse capture for interactions
- Poll services: Must call
check_for_changes()regularly on watchers
Examples
- Feature flags required: Examples need their specific features:
--features markdown-preview - Just commands: Use
just demofor interactive picker orjust demo-*for specific demos
Optional
Additional Resources
- Examples: 23 examples in
examples/ - Just commands: Run
just helpfor all available commands - Build:
just buildorcargo build -p ratkit --all-features - Test:
just test
Version
- Current: 0.2.5
- Rust: 1.70+