gyscos/cursive
A Text User Interface library for the Rust programming language
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 4d ago
- ✓18 active contributors
- ✓MIT licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 72% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/gyscos/cursive)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/gyscos/cursive on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: gyscos/cursive
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/gyscos/cursive shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 4d ago
- 18 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 72% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live gyscos/cursive
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/gyscos/cursive.
What it runs against: a local clone of gyscos/cursive — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in gyscos/cursive | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 34 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of gyscos/cursive. If you don't
# have one yet, run these first:
#
# git clone https://github.com/gyscos/cursive.git
# cd cursive
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of gyscos/cursive and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "gyscos/cursive(\\.git)?\\b" \\
&& ok "origin remote is gyscos/cursive" \\
|| miss "origin remote is not gyscos/cursive (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "cursive-core/src/lib.rs" \\
&& ok "cursive-core/src/lib.rs" \\
|| miss "missing critical file: cursive-core/src/lib.rs"
test -f "cursive-core/src/cursive_root.rs" \\
&& ok "cursive-core/src/cursive_root.rs" \\
|| miss "missing critical file: cursive-core/src/cursive_root.rs"
test -f "cursive-core/src/view/view_trait.rs" \\
&& ok "cursive-core/src/view/view_trait.rs" \\
|| miss "missing critical file: cursive-core/src/view/view_trait.rs"
test -f "cursive-core/src/printer.rs" \\
&& ok "cursive-core/src/printer.rs" \\
|| miss "missing critical file: cursive-core/src/printer.rs"
test -f "cursive-core/src/backend.rs" \\
&& ok "cursive-core/src/backend.rs" \\
|| miss "missing critical file: cursive-core/src/backend.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 34 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~4d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/gyscos/cursive"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Cursive is a safe, ergonomic TUI (Text User Interface) library for Rust that allows developers to build rich terminal applications with styled dialogs, text views, selection menus, and event handling. It abstracts over terminal backends (primarily crossterm) to provide high-level widget components like Dialog, TextView, and SelectView that compile to both safe Rust code and functional terminal UIs. Monorepo with Cargo workspace: cursive-core (core/src contains backend.rs, event.rs, style/, printer.rs, traits.rs) is the backend-agnostic foundation; cursive/ wraps it with high-level views; cursive-syntect adds syntax highlighting; cursive-macros provides derive utilities. Style system is hierarchical (style/color.rs, color_pair.rs, color_style.rs, palette.rs, theme.rs) and theming is composable via theme.rs.
👥Who it's for
Rust developers building terminal applications—from CLI tools to interactive dashboards—who want to avoid raw terminal escape codes and need cross-platform TUI widgets with theme support and event-driven architecture. Contributors range from backend engineers maintaining the core abstraction to terminal enthusiasts adding new backends or widgets.
🌱Maturity & risk
Actively maintained and production-ready. The project is at version 0.21 with a published crate, CI/CD via GitHub Actions (rust.yml), semantic versioning, and organized issue templates for bug reports and feature requests. Recent activity visible in CHANGELOG.md and workspace organization suggests regular updates, though the 0.x version number indicates the API may not be frozen.
Low to moderate risk: single-maintainer repo (gyscos) means succession depends on community contributions; however, the modular workspace structure (cursive, cursive-core, cursive-syntect, cursive-macros) reduces coupling. Breaking changes are possible pre-1.0. Dependency on crossterm (external crate) and multiple backends creates maintenance surface. No obvious open critical security issues visible in the file list.
Active areas of work
No specific PR/milestone data visible in the file structure provided, but the presence of builder/resolvable.rs and ongoing test coverage in utils/lines/simple/tests.rs suggests active refinement of UI composition and text layout. CHANGELOG.md would contain version-specific details. The workspace includes examples/ across multiple packages, indicating continued example maintenance.
🚀Get running
Clone and build with Cargo: git clone https://github.com/gyscos/cursive.git && cd cursive && cargo build. Run examples: cargo run --example dialog --manifest-path cursive/Cargo.toml. Tests: cargo test --workspace. The workspace resolver = "2" requires Rust 1.64+.
Daily commands:
cargo run --example dialog (or other examples in cursive/examples/). Dev workflow: cargo build --workspace && cargo test --workspace && cargo doc --open to view local docs.
🗺️Map of the codebase
cursive-core/src/lib.rs— Main library entry point exporting core TUI abstractions; every new view or feature depends on types defined here.cursive-core/src/cursive_root.rs— Root event loop and application state manager; understand this to control lifecycle and event dispatch.cursive-core/src/view/view_trait.rs— Core trait defining the View abstraction that all UI components implement; architectural foundation for the entire system.cursive-core/src/printer.rs— Rendering abstraction that bridges views to backend output; critical for understanding how content reaches the terminal.cursive-core/src/backend.rs— Backend interface trait enabling pluggable terminal rendering (crossterm, ncurses, etc.); essential for multi-backend support.cursive-core/src/event.rs— Event types and handling; defines input model that all views consume and respond to.cursive-core/src/theme.rs— Styling and theming system; controls palette, colors, and visual appearance across all views.
🛠️How to make changes
Add a new custom View component
- Create a new struct implementing ViewTrait in a new file under cursive-core/src/views/ (
cursive-core/src/views/my_view.rs) - Implement required methods: draw, required_size, take_focus, and on_event (
cursive-core/src/views/my_view.rs) - Export the new view type from cursive-core/src/views/mod.rs (
cursive-core/src/views/mod.rs) - Re-export from cursive-core/src/lib.rs in the views module (
cursive-core/src/lib.rs) - Add integration test or example demonstrating usage (
cursive/examples/my_view_example.rs)
Add support for new text markup format
- Create parser module under cursive-core/src/utils/markup/ (
cursive-core/src/utils/markup/my_format.rs) - Implement parser returning Vec<SpannedString> from input text (
cursive-core/src/utils/markup/my_format.rs) - Export from cursive-core/src/utils/markup/mod.rs (
cursive-core/src/utils/markup/mod.rs) - Add tests demonstrating parser correctness (
cursive-core/src/utils/markup/my_format.rs)
Extend theming with new style properties
- Add new field to ColorStyle or define new style type in cursive-core/src/style/ (
cursive-core/src/style/color_style.rs) - Update theme parsing in cursive-core/src/theme.rs to load from config (
cursive-core/src/theme.rs) - Update Printer to apply new style when rendering in cursive-core/src/printer.rs (
cursive-core/src/printer.rs) - Update default theme in Palette struct (
cursive-core/src/style/palette.rs)
Add new backend support
- Create backend crate (e.g., cursive-my-backend) with Cargo.toml (
cursive-my-backend/Cargo.toml) - Implement cursive_core::backend::Backend trait for your terminal library (
cursive-my-backend/src/lib.rs) - Implement required methods: poll_event, print_at, clear, refresh, resize_handler (
cursive-my-backend/src/lib.rs) - Add backend to workspace members in root Cargo.toml (
Cargo.toml)
🔧Why these technologies
- Rust traits (ViewTrait, Backend) — Enable pluggable views and backends without coupling; allow users to extend without modifying core library
- crossterm (default backend) — Cross-platform terminal abstraction; works on Windows, macOS, Linux without ncurses dependency
- Workspace with separate cursive-core crate — Decouple core TUI logic from backend/feature implementations; allows minimal dependency footprint for headless testing
- Builder pattern (cursive-core/src/builder/) — Fluent API for declarative view construction; reduces boilerplate and improves readability
⚖️Trade-offs already made
-
Single-threaded event loop in cursive_run.rs
- Why: Simplifies state management and eliminates race conditions in mutable views; matches terminal I/O blocking model
- Consequence: Long-running callbacks block UI; async operations must spawn threads and use channels to update state
-
View trait requires &mut self for on_event and draw
- Why: Allows views to mutate internal state in response to events; natural Rust ownership model
- Consequence: Cannot render same view instance in multiple places; encourages tree structure with single ownership
-
Size caching in size_cache.rs rather than automatic memoization
- Why: Explicit cache invalidation prevents subtle layout bugs from stale sizes
- Consequence: Views must call invalidate_cache() when content changes; risk of manual invalidation bugs
-
Separate markup parsers (ANSI, Cursup, Markdown) in cursive-core/src/utils/markup/
- Why: Allows users to opt-in to formats they need; avoids hard dependencies on heavy parsers (e.g., syntect)
- Consequence: Code duplication across parsers; maintenance burden when style system changes
🪤Traps & gotchas
Terminal backend assumption: Code defaults to crossterm; if you need a different backend (ncurses, termion, pancurses), check cursive/src/lib.rs for feature flags and backend selection logic. Async event handling: The cursive event loop (cursive-core/src/cursive_run.rs) abstracts async, but not all backends support true async—test on target platform. UTF-8 terminal assumption: cursor positioning and text measurement assume valid UTF-8 in cursive-core/src/utils/lines/—combining marks or double-width characters may cause layout issues. Mutable reference requirement: Many APIs require &mut self; understand the interior mutability pattern used for shared state. No redraw coalescing visible: Printing happens per-frame; performance on very large terminal sizes may degrade without custom optimization.
🏗️Architecture
💡Concepts to learn
- Retained-mode rendering (vs. immediate-mode) — Cursive uses retained-mode (widgets hold state, framework calls render methods) unlike immediate-mode TUIs (ratatui); this affects how you structure view composition and event handling.
- Backend abstraction layer — Cursive isolates terminal I/O (keyboard, mouse, rendering) behind a backend trait in cursive-core/src/backend.rs; understanding this is critical for supporting new terminals or testing.
- View hierarchy and layout algorithms — Recursive layout (parent sizes children, children request sizes back) via Rect and Printer is how Cursive handles responsive terminal UIs; misunderstanding causes layout bugs.
- Event loop and callback closure patterns — Cursive uses closures (|s: &mut Cursive| {...}) to handle button clicks and input; understanding callback injection and mutable access to Cursive root is essential for interactivity.
- Theme composition and color pairs — Cursive separates semantic colors (e.g., 'primary', 'error') from terminal colors (RGB or 256-color palette) via cursive-core/src/style/color_pair.rs and theme.rs; this enables flexible theming and palette switching.
- Interior mutability and Rc<RefCell<T>> — Cursive uses Rc<RefCell<T>> patterns to share mutable state across views without multiple mutable references; understanding borrow-checking workarounds is required for advanced layouts.
- UTF-8 and terminal text measurement — cursive-core/src/utils/lines/ handles text measurement, wrapping, and cursor positioning; terminal width != byte width for multibyte UTF-8, causing subtle layout bugs if ignored.
🔗Related repos
fdehau/tui-rs— Alternative Rust TUI library (now ratatui) with immediate-mode rendering; directly comparable architecture and feature set to Cursive's retained-mode approach.crossterm-rs/crossterm— The primary backend used by Cursive; understanding crossterm's API (keyboard events, terminal raw mode, cursor control) is essential for backend issues.rust-lang/book— Cursive examples and tutorials link heavily to Rust ownership/trait patterns; essential background for understanding safe abstractions in Cursive.gyscos/cursive-syntect— Companion crate within the same org for syntax-highlighted text views; shows how to extend Cursive with specialized widgets.gyscos/cursive-macros— Sibling crate in the workspace providing derive macros for views; demonstrates compile-time metaprogramming patterns used in Cursive.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for cursive-core/src/utils/lines/spans module
The spans module (cursive-core/src/utils/lines/spans/) handles complex text segmentation and styling logic with multiple components (chunk.rs, chunk_iterator.rs, segment.rs, segment_merge_iterator.rs, row.rs). While spans/tests.rs exists, the simple/tests.rs shows a pattern of dedicated test coverage. The spans module lacks comprehensive edge case testing for iterator behavior, segment merging, and span boundary conditions that are critical for text rendering correctness.
- [ ] Expand cursive-core/src/utils/lines/spans/tests.rs with tests for ChunkIterator edge cases (empty spans, single character, overlapping styles)
- [ ] Add tests for SegmentMergeIterator behavior with adjacent and overlapping segments
- [ ] Add tests for Row span calculation with various span widths and positions
- [ ] Test integration between chunk_iterator and segment_merge_iterator with realistic markup scenarios
Add GitHub Actions workflow to test all workspace members with their feature combinations
The .github/workflows/rust.yml exists but the workspace has 4 members (cursive, cursive-core, cursive-syntect, cursive-macros) with potentially different feature flags. Currently there's no explicit CI validation that each member builds independently and that feature combinations work correctly. The workspace's resolver = "2" suggests complex dependency management that needs thorough testing.
- [ ] Examine cursive/Cargo.toml, cursive-syntect/Cargo.toml, and cursive-macros/Cargo.toml for feature flags
- [ ] Add matrix strategy to .github/workflows/rust.yml to test: (a) each workspace member individually with --no-default-features, (b) each member with all features enabled, (c) cursive with each backend option
- [ ] Add clippy and fmt checks to the workflow for consistency across all members
- [ ] Verify dependabot.yml updates are properly tested against all member combinations
Add missing documentation for markup module in cursive-core/src/utils/markup/
The markup module (cursive-core/src/utils/markup/) contains 4 different markup parsers (ansi.rs, cursup.rs, gradient.rs, markdown.rs) but lacks module-level documentation explaining when to use each format, their syntax, and examples. CONTRIBUTING.md and README.md don't reference these features. This is a critical UX gap for new contributors and users.
- [ ] Create comprehensive documentation in cursive-core/src/utils/markup/mod.rs with overview of all 4 markup types
- [ ] Add code examples for each markup parser (ansi, cursup, gradient, markdown) showing input and output
- [ ] Document the differences and use cases (e.g., when to use markdown vs cursup vs gradient markup)
- [ ] Add a section to README.md linking to markup documentation with quick examples
- [ ] Add markup examples to CONTRIBUTING.md as reference for contributors
🌿Good first issues
- Add missing unit tests for cursive-core/src/buffer.rs rendering edge cases (empty strings, long lines exceeding terminal width, ANSI escape sequences). The file has no obvious test module despite being critical for text output.: Buffer is the lowest-level rendering layer; tests prevent regressions in all visual output.
- Document the builder pattern in cursive-core/src/builder/resolvable.rs with inline examples showing how custom widgets can use resolvable for DRY configuration. Currently underdocumented for new contributors.: Resolvable is a key pattern for advanced builders; examples enable more composable widget code.
- Add a comprehensive TUI layout debugging example (in cursive/examples/) that visualizes bounding boxes, print counts, and event flow for complex nested views. Currently hard to diagnose layout issues without reading printer.rs.: New users struggle with layout; a visual debugger example reduces onboarding friction and catches layout bugs early.
⭐Top contributors
Click to expand
Top contributors
- @gyscos — 72 commits
- @dependabot[bot] — 10 commits
- @chet — 2 commits
- @xanderlent — 2 commits
- @badscrew — 1 commits
📝Recent commits
Click to expand
Recent commits
b41c5ad— Add horizontal scroll gesture support (#872) (badscrew)2007031— Address most compiler/clippy warnings (#865) (electricbrass)d3358a3— Fix focus_view for Dialog and LinearLayout (gyscos)0ba3982— Update third-party views in README (#864) (tliron)a1ce0fb— Remove mention of inexistent example (gyscos)6a376c4— Update rand dev-dependency to 0.10 (gyscos)330ee17— Update find-crate requirement from 0.6.3 to 0.7.1 (#858) (dependabot[bot])694802c— Update toml requirement from 0.9 to 1.0 (#860) (dependabot[bot])01632ac— Fix Alt+Shift+Char for crossterm backend (#827) (azat)57b02ac— Update signal-hook requirement from 0.3 to 0.4 (#851) (dependabot[bot])
🔒Security observations
The Cursive TUI library demonstrates generally sound security practices. As a rendering/UI library, the attack surface is limited compared to web frameworks. No obvious hardcoded credentials, SQL injection risks, or configuration vulnerabilities were identified in the provided file structure. Primary security concerns are around dependency management and markup parsing robustness. The codebase would benefit from automated security scanning in CI/CD pipelines and explicit dependency audit processes. The MIT license is appropriate for open-source projects.
- Low · Incremental Compilation Disabled in Development —
Cargo.toml - [profile.dev]. The Cargo.toml workspace configuration explicitly disables incremental compilation for dev builds (incremental = false). While this can be intentional for reproducible builds, it may indicate a workaround for a compiler issue or incremental compilation bug, potentially masking underlying problems. Fix: Document why incremental compilation is disabled. If this was a workaround for a compiler bug, verify the bug is still present in current Rust versions. Consider enabling it for improved development experience if no longer needed. - Low · Workspace Dependency Management —
Cargo.toml and member crates. The workspace contains multiple members (cursive, cursive-core, cursive-syntect, cursive-macros) but the Cargo.toml file shown does not display dependency versions or security audit information. Without visibility into dependencies, transitive vulnerabilities may exist. Fix: Regularly runcargo auditto identify known vulnerabilities in dependencies. Implement dependency scanning in CI/CD pipeline (.github/workflows/rust.yml should include security checks). Usecargo-denyor similar tools to enforce security policies. - Low · Markup Processing Without Clear Input Validation —
cursive-core/src/utils/markup/. The codebase contains multiple markup parsers (ansi.rs, cursup.rs, gradient.rs, markdown.rs) that process user input. Without examining the actual implementation, there's potential risk for injection attacks or DoS through malformed input. Fix: Review markup parsing functions to ensure: 1) Input length limits are enforced, 2) Recursive parsing has depth limits, 3) Special characters are properly escaped/validated, 4) Malformed input is safely handled without panics.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.