ratkit
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:
- Define struct implementing
CoordinatorApp - Implement
on_event()to handle events - Implement
on_draw()to render UI - Call
run(app, RunnerConfig::default())
- Define struct implementing
- 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:
- Create app implementing
CoordinatorApp - Create
RunnerConfig::default()or custom - Call
run(app, config)orrun_with_diagnostics(app, config)for debug overlay
- Create app implementing
- 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:
- Implement
Elementtrait for your widget - Define
id(),on_render(),on_keyboard(),on_mouse() - Register with
ElementMetadataand region
- Implement
- 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:
- Create
Button::new("Label") - Call
update_hover(x, y)on mouse move - Call
is_clicked(x, y)on click - Render with
render_with_title()
- Create
- 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:
- Create
Pane::new("Title") - Chain builder methods:
with_icon(),with_padding(),border_style() - Render as widget
- Create
- 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:
- Create
Dialog::new(title, message)or use builder (Dialog::confirm()) - Set buttons with
.buttons(vec!["Yes", "No"]) - Create
DialogState::new()for button selection - Render with
DialogWidget
- Create
- 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:
- Create
ToastManager::new()in app state - Add toasts via
.success(),.error(),.info(),.warning() - Call
cleanup()before render - Render with
render_toasts()
- Create
- 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:
- Build
TreeNodehierarchy - Create
TreeView::new(nodes)with render_fn - Create
TreeViewState::new()for selection/expansion - Use
TreeNavigatorfor keyboard handling
- Build
- 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:
- Create state structs (ScrollState, SourceState, etc.) in app state
- Create
MarkdownWidget::new(content, scroll, source, ...) - Handle keyboard with
handle_key() - 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:
- Create
FileWatcher::for_file()orFileWatcher::for_directory() - Call
watch(path) - Poll
check_for_changes()in event loop - Get changes with
get_changed_paths()
- Create
- 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:
- Create
HotkeyRegistry::new() - Register hotkeys with
Hotkey::new(key, description).scope(scope) - Set active scope with
set_active_scope() - Query with
lookup(key, scope)in event loop
- Create
- 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+