ratkit

SKILL.md

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

  1. Single crate at root: All code is in src/ with 21 feature flags (e.g., button, pane, markdown-preview)
  2. Enable features explicitly: No default features; add required features to Cargo.toml (e.g., features = ["button", "dialog"])
  3. Cross-feature dependencies: Some features auto-enable others (e.g., tree-view enables widget-event, repo-watcher enables file-watcher and git-watcher)
  4. Use just for all operations: Build (just build), test (just test), check (just check), demos (just demo)
  5. Run examples with --features flag: Examples require their specific features (e.g., --features markdown-preview)
  6. Import from crate root: All public APIs are re-exported from ratkit:: (e.g., use ratkit::Button)
  7. StatefulWidget pattern: Complex widgets require separate state structs persisted in app state
  8. Event loop polling: Services require regular check_for_changes() calls in the event loop
  9. Mouse capture required: Enable crossterm mouse capture for interactive widgets
  10. Persist widget state: Never create widget state in render loops - store in app struct
  11. Validate before commits: Run just check (format + lint + test) before committing
  12. 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 from crates/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) or just 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, scroll
  • menu-bar (enables widget-event)
  • resizable-grid
  • tree-view (enables widget-event)
  • widget-event
  • termtui

Common Patterns

  • Builder pattern with new() and with_* 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 viewer
  • ai-chat - AI chat interface (requires reqwest, serde)
  • hotkey-footer - Keyboard shortcut footer
  • file-system-tree - File browser with devicons
  • theme-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 changes
  • git-watcher - Monitor git repository state
  • repo-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 true when 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 str for 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

  1. No default features: Must explicitly enable every feature you use
  2. Cross-feature deps: tree-view enables widget-event; repo-watcher enables file-watcher and git-watcher
  3. Missing feature errors: "unresolved import" usually means missing feature flag

State Management

  1. StatefulWidget pattern: Complex widgets require persistent state in app struct
  2. Never create state in render: Always store widget state in app struct
  3. Weak references: Element registry stores weak refs - keep strong refs in app

Event Handling

  1. Return values: Return true when consuming events, false to propagate
  2. Mouse capture: Must enable crossterm mouse capture for interactions
  3. Poll services: Must call check_for_changes() regularly on watchers

Examples

  1. Feature flags required: Examples need their specific features: --features markdown-preview
  2. Just commands: Use just demo for interactive picker or just demo-* for specific demos

Optional

Additional Resources

  • Examples: 23 examples in examples/
  • Just commands: Run just help for all available commands
  • Build: just build or cargo build -p ratkit --all-features
  • Test: just test

Version

  • Current: 0.2.5
  • Rust: 1.70+
Weekly Installs
8
GitHub Stars
2
First Seen
11 days ago
Installed on
opencode8
gemini-cli3
claude-code3
github-copilot3
codex3
kimi-cli3