crossterm-rs/crossterm
Cross platform terminal library rust
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 4w ago
- ✓61+ active contributors
- ✓Distributed ownership (top contributor 15% of recent commits)
Show all 6 evidence items →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
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/crossterm-rs/crossterm)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/crossterm-rs/crossterm on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: crossterm-rs/crossterm
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/crossterm-rs/crossterm 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 4w ago
- 61+ active contributors
- Distributed ownership (top contributor 15% of recent commits)
- MIT licensed
- CI configured
- Tests present
<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 crossterm-rs/crossterm
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/crossterm-rs/crossterm.
What it runs against: a local clone of crossterm-rs/crossterm — 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 crossterm-rs/crossterm | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 59 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of crossterm-rs/crossterm. If you don't
# have one yet, run these first:
#
# git clone https://github.com/crossterm-rs/crossterm.git
# cd crossterm
#
# 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 crossterm-rs/crossterm and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "crossterm-rs/crossterm(\\.git)?\\b" \\
&& ok "origin remote is crossterm-rs/crossterm" \\
|| miss "origin remote is not crossterm-rs/crossterm (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 master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/lib.rs" \\
&& ok "src/lib.rs" \\
|| miss "missing critical file: src/lib.rs"
test -f "src/command.rs" \\
&& ok "src/command.rs" \\
|| miss "missing critical file: src/command.rs"
test -f "src/event.rs" \\
&& ok "src/event.rs" \\
|| miss "missing critical file: src/event.rs"
test -f "src/event/sys/unix.rs" \\
&& ok "src/event/sys/unix.rs" \\
|| miss "missing critical file: src/event/sys/unix.rs"
test -f "src/event/sys/windows.rs" \\
&& ok "src/event/sys/windows.rs" \\
|| miss "missing critical file: src/event/sys/windows.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 59 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~29d)"
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/crossterm-rs/crossterm"
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
Crossterm is a pure-Rust, cross-platform terminal manipulation library that abstracts over ANSI escape codes (Unix/Linux) and Windows Console API to provide a unified interface for cursor control, styled text output, event handling, and terminal manipulation. It enables developers to build text-based UIs that work identically on Windows 7+, macOS, Linux, and other UNIX systems without platform-specific code. Modular Rust library with platform-specific code separated into src/cursor/sys/{unix.rs,windows.rs} and src/event/ for input handling. Core abstractions live in src/command.rs (command pattern), src/event.rs (event types), src/terminal.rs (terminal ops). Examples in examples/ and an interactive demo in examples/interactive-demo/ serve as integration tests. Features are gated via Cargo features (events, event-stream, windows, osc52).
👥Who it's for
Rust developers building CLI applications and text-based user interfaces (TUIs) who need cross-platform terminal control without learning separate Windows Console API and ANSI escape code implementations. Primary users include authors of terminal dashboards, interactive CLIs (like ripgrep, bat-style tools), and TUI frameworks.
🌱Maturity & risk
Production-ready and actively maintained. The codebase is ~392K lines of Rust with comprehensive CI via .github/workflows/crossterm_test.yml, detailed docs in docs/CONTRIBUTING.md, and established versioning (currently 0.29.0). The README documents tested compatibility across Windows 10/11, Ubuntu, Arch, Fedora, and other Linux distros, indicating real-world usage.
Low risk for adoption. Minimal dependencies (mio, signal-hook, winapi, parking_lot, bitflags) are well-established crates. Single documented maintainer (T. Post in Cargo.toml) is a minor concentration risk, but the MIT license and GitHub hosting provide community protection. Breaking changes are documented in CHANGELOG.md. Main risk is platform-specific edge cases (not all terminals tested equally).
Active areas of work
Active development maintaining compatibility across Rust versions (MSRV 1.63.0) and terminal emulators. Recent additions likely include osc52 clipboard support and event-stream async integration. The docs/know-problems.md file tracks known limitations, suggesting ongoing triage of platform-specific issues.
🚀Get running
git clone https://github.com/crossterm-rs/crossterm.git
cd crossterm
cargo build
cargo test
cargo run --example event-read
Daily commands:
For examples: cargo run --example event-read or cargo run --example interactive-demo. For the interactive demo specifically: cd examples/interactive-demo && cargo run. Run tests with cargo test --all-features.
🗺️Map of the codebase
src/lib.rs— Entry point and public API surface; defines all top-level modules (event, cursor, terminal, style, command) and feature gates that shape the entire library.src/command.rs— Core traitCommandandExecutableCommandabstraction; the fundamental pattern for all terminal operations in crossterm.src/event.rs— Event system definition includingEventenum and polling/reading API; critical for input handling across all platforms.src/event/sys/unix.rs— Unix-specific event parsing and TTY handling; implements the core polling loop for non-Windows systems.src/event/sys/windows.rs— Windows-specific event polling via ReadConsoleInput; handles platform-specific console I/O differences.src/style.rs— Styling abstraction layer; orchestrates color, attribute, and content rendering across Unix and Windows backends.src/terminal.rs— Terminal manipulation API (enable/disable raw mode, alternate screen, size queries); bridges high-level operations to platform-specific implementations.
🛠️How to make changes
Add a new Command type for a terminal operation
- Define the command struct in the relevant module (e.g.,
src/terminal.rsfor terminal commands) (src/terminal.rs) - Implement the
Commandtrait withexecute()method that dispatches to platform-specific implementations via#[cfg(unix)]/#[cfg(windows)](src/terminal.rs) - Add Unix backend in
src/terminal/sys/unix.rsor extend if it exists (src/terminal/sys/unix.rs) - Add Windows backend in
src/terminal/sys/windows.rswith Windows API calls (src/terminal/sys/windows.rs) - Export the command struct from
src/lib.rsunder the appropriate module and add doc comments with examples (src/lib.rs)
Add support for a new Event type or input capability
- Add the new
Eventvariant to the enum insrc/event.rs(src/event.rs) - Extend Unix parsing logic in
src/event/sys/unix/parse.rsto recognize and tokenize the escape sequences (src/event/sys/unix/parse.rs) - Update Windows parsing in
src/event/sys/windows/parse.rsto translate INPUT_RECORD fields to the new event (src/event/sys/windows/parse.rs) - Test with
examples/event-read.rsor add new example demonstrating the event (examples/event-read.rs)
Add a new Color variant or styling feature
- Extend the
Colorenum insrc/style/types/color.rswith the new variant (src/style/types/color.rs) - Update Windows color mapping logic in
src/style/sys/windows.rsto handle the new color (src/style/sys/windows.rs) - Implement ANSI escape sequence generation for Unix in
src/style.rsor style submodules as needed (src/style.rs) - Add test cases in the interactive demo at
examples/interactive-demo/src/test/color.rs(examples/interactive-demo/src/test/color.rs)
🔧Why these technologies
- Pure Rust (no FFI except Windows API via winapi-util) — Ensures cross-platform consistency, simplifies dependency chain, and avoids C/POSIX binding maintenance burden.
- termios (Unix) vs Windows Console API — Mandatory for platform-specific terminal control; no abstraction layer can hide the fundamentally different I/O models (POSIX tty vs Windows console).
- Command trait pattern (execute on writer) — Allows composable, queued terminal operations without global state; enables both synchronous and async usage patterns.
- Feature-gated event sources (mio vs TTY) — Mio provides efficient async-friendly polling on Unix; TTY fallback ensures compatibility with systems lacking mio or preferring simpler I/O.
⚖️Trade-offs already made
-
Platform-specific code via cfg attributes rather than trait objects
- Why: Reduces runtime dispatch overhead; compile-time elimination of unreachable code per platform.
- Consequence: Code duplication across Unix/Windows paths; requires careful feature testing on both platforms during development.
-
Raw mode vs cooked mode for input capture
- Why: Raw mode enables capturing individual key presses and modifiers; cooked mode would lose precision.
- Consequence: Application must handle echoing, line editing, and signal delivery explicitly; not suitable for simple line-based TUI if raw mode is enabled.
-
Synchronous polling API (read/poll) with optional async streams
- Why: Blocking APIs are simpler for single-threaded TUIs; async streams added as opt-in for integrated tokio/async-std apps.
- Consequence: Two code paths to maintain; users must choose between blocking and async idioms upfront.
-
VT100/ANSI escape sequences on Unix rather than direct terminfo lookups
- Why: Avoids heavyweight terminfo dependency and works across most modern terminals.
- Consequence: Terminal-specific quirks (e.g., color palette differences) not automatically handled; users on niche terminals may need workarounds.
🚫Non-goals (don't propose these)
- Real-time multiplexing or session management (not a tmux alternative)
- Network terminal emulation or remote terminal protocol support
- Pixel-based graphics or image rendering (text-only)
- Full terminfo database integration (intentionally lightweight)
- Authentication or security enforcement (terminal I/O library only)
- Persistent session state or logging (stateless operations only)
🪤Traps & gotchas
- Windows requires
windowsfeature (enabled by default) and winapi dependency; tests may fail without it on Windows. 2) Raw mode (execute!(stdout, EnterRawMode)) disables line buffering and canonical input—must manually handle line reading. 3)EventStreamrequiresevent-streamfeature + async runtime (tokio or async-std); mixing sync polling and async streams can cause hangs. 4) Alt key modifiers differ between terminals—checkdocs/know-problems.mdfor terminal-specific quirks. 5) Cursor positioning may fail on minimal terminals that don't support ANSI; useis_tty()to gate features.
🏗️Architecture
💡Concepts to learn
- ANSI Escape Sequences — Unix/Linux cursor movement and styling are implemented via ANSI codes (e.g.,
\x1b[Hfor cursor home); understanding these is essential to debugsrc/ansi_support.rsand platform-specific rendering issues - Windows Console API (GetConsoleScreenBufferInfo, SetConsoleCursorPosition) — Windows terminal control bypasses ANSI and uses native Console API calls; critical to understanding
src/cursor/sys/windows.rsFFI code and why Windows 10+ ANSI support required separate code paths - Command Pattern — Core crossterm design—all operations (cursor moves, style changes) are
Commandstructs implementingExecutableCommand; enables batching, deferred execution, and platform abstraction insrc/command.rs - Raw Mode (Unbuffered Input) — Unix raw mode (
cfmakeraw()) and Windows console mode disables canonical input processing; essential for interactive key/mouse event reading but breaks normal line editing if not carefully managed - Signal Handling (SIGWINCH, SIGINT) — Unix resize events and Ctrl+C handling require catching terminal signals via
signal-hook; Windows uses console events API; understanding this is critical forsrc/event/cross-platform event dispatch - TTY Detection (isatty) — Crossterm's
is_tty()function determines if stdout is a real terminal vs pipe/file; essential for gracefully degrading styled output in non-interactive contexts (e.g., piped to file) - Bracketed Paste (OSC 52) — Clipboard operations use OSC 52 escape sequence or native APIs; the optional
osc52feature shows how crossterm extends beyond cursor/style into system integration; relevant forsrc/clipboard.rs
🔗Related repos
termion/termion— Rust terminal control library using raw ANSI codes; predecessor/alternative focusing on Unix only, contrasts with crossterm's Windows supportratatui-org/ratatui— TUI framework built on top of crossterm; primary consumer library demonstrating how crossterm abstractions enable rich interactive dashboardsconsole-rs/console— Sibling library in the Rust CLI ecosystem providing styled terminal output; often used alongside crossterm for console I/O in CLIswinapi-rs/winapi-rs— Windows API bindings that crossterm depends on; essential for understanding Windows Console implementation insrc/cursor/sys/windows.rstokio-rs/tokio— Async runtime used by optionalevent-streamfeature for async event polling; required for examples inexamples/event-stream-tokio.rs
🪄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 src/event/sys/unix/parse.rs
The Unix event parsing module (src/event/sys/unix/parse.rs) is critical for handling terminal input sequences, but there are likely minimal unit tests for edge cases like incomplete ANSI escape sequences, malformed input, and various terminal-specific escape codes. This would improve robustness across different Unix terminals and prevent regressions.
- [ ] Create tests/event_parse_unix.rs with unit tests for src/event/sys/unix/parse.rs
- [ ] Add test cases for: incomplete sequences, invalid UTF-8, common ANSI codes (arrows, function keys, mouse events)
- [ ] Add edge case tests for terminal-specific variations (xterm, VT100, xterm-256color)
- [ ] Run tests against the existing event reading examples to ensure compatibility
- [ ] Document any known parsing limitations in docs/know-problems.md if found
Add GitHub Actions workflow for testing Windows-specific terminal features
The repo has .github/workflows/crossterm_test.yml but it likely runs primarily on Linux. Windows terminal features (src/event/sys/windows/, src/cursor/sys/windows.rs, etc.) need dedicated CI testing on actual Windows runners to catch platform-specific bugs, especially around the winapi integration and console input handling.
- [ ] Create .github/workflows/windows-test.yml for Windows-specific testing
- [ ] Configure the workflow to run on windows-latest and test with features: default, event-stream, serde, use-dev-tty
- [ ] Include integration tests from examples/ directory on Windows (event-read.rs, key-display.rs, etc.)
- [ ] Add specific tests for src/event/sys/windows/parse.rs and Windows console event handling
- [ ] Document Windows-specific testing procedures in docs/CONTRIBUTING.md
Add documentation for platform-specific behavior in src/event/source/
The event source abstraction (src/event/source/unix.rs and src/event/source/windows.rs) has significant platform differences, but there's no detailed documentation explaining which event sources are used on each platform, their limitations, and why (e.g., mio vs raw file descriptors, console input vs stdin). New contributors can't understand the architecture.
- [ ] Create docs/event-source-architecture.md explaining the event pipeline: source → internal → filter → Event
- [ ] Document why Unix uses mio/signal-hook (src/event/source/unix/mio.rs) vs tty (src/event/source/unix/tty.rs) and when each is chosen
- [ ] Explain Windows console input handling (src/event/sys/windows/) and how it differs from Unix stdin
- [ ] Add decision tree diagrams showing platform selection logic based on features (events, event-stream, use-dev-tty)
- [ ] Reference this doc from docs/CONTRIBUTING.md and in src/event/source/mod.rs
🌿Good first issues
- Add integration tests for
src/style.rscolor types (RGB, ANSI 256) inexamples/interactive-demo/src/test/color.rsto ensure consistent rendering across Windows 10+, Linux, and macOS terminals. - Document platform-specific behavior matrix in README (create table showing which features work on Windows 7 vs Windows 10+, Console Host vs Windows Terminal) based on test results from
.github/workflows/crossterm_test.yml. - Implement cross-platform tests for mouse event parsing in
src/event/to verify coordinate translation between Windows COORD and Unix terminal pixel ratios, as this is noted indocs/know-problems.mdas fragile.
⭐Top contributors
Click to expand
Top contributors
- @TimonPost — 15 commits
- @joshka — 10 commits
- @the-mikedavis — 5 commits
- @naseschwarz — 3 commits
- @aschey — 3 commits
📝Recent commits
Click to expand
Recent commits
c02a080— fix: open /dev/tty in write mode to query keyboard enhancement flags (#1026) (sandydoo)ccf7075— Support for OSC 8 hyperlinks (#1038) (cammeresi)2df28f7— refactor: improvequeuemacro hygiene (#1040) (dybucc)014db9a— fix: make cursorread_position_rawskip older cursor pos events (#1024) (playwmadness)4f08595— Fix typo in macOS version name in README (#1019) (bnjjo)ee304d3— Remove redundant words in comment (#1005) (pingshuijie)a426737— terminal:remove unused parentheses (#1012) (alexs-sh)6af9116— feat: addtry_readfunction (#1003) (gavincrawford)2ba0160— refactor: move internal items from event to event::internal (#999) (joshka)fab72d1— AddHashderive to style types (#1002) (gavincrawford)
🔒Security observations
The crossterm library demonstrates generally good security practices as a low-level terminal manipulation library. The codebase avoids common web vulnerabilities (SQLi, XSS, CSRF) due to its nature. The primary security concerns are: (1) an incomplete dependency specification that needs correction, (2) complexity in terminal parsing logic that should be fuzzed, (3) platform-specific code (signals on Unix, Windows APIs) that requires careful review for race conditions and improper system call usage, and (4) clipboard handling for potentially sensitive user data. The library's architectural design of being a pure Rust implementation helps mitigate many vulnerability classes. Recommended actions: complete the Cargo.toml dependency specification, conduct fuzzing of input parsers, and maintain regular security audits of platform-specific code.
- Medium · Incomplete Dependency Specification —
Cargo.toml - dependencies section. The parking_lot dependency in Cargo.toml appears to have an incomplete version specification (line shows '"parking_lot" = "0.12' without closing quote or version constraint). This could lead to unintended version resolution and potential security issues if a vulnerable patch is released. Fix: Complete the parking_lot version specification with a proper semver constraint, e.g., 'parking_lot = "0.12"' or 'parking_lot = "0.12.x"' - Low · Base64 Dependency for Clipboard Operations —
Cargo.toml - base64 dependency, src/clipboard.rs. The base64 crate is used for OSC52 clipboard operations. While base64 encoding itself is not cryptographically sensitive, the clipboard feature handles potentially sensitive user data (copy-to-clipboard functionality). If mishandled, this could expose sensitive information. Fix: Ensure clipboard operations properly sanitize and handle sensitive data. Consider warning users about clipboard security implications in documentation. - Low · Terminal Input Parsing Complexity —
src/event/sys/unix/parse.rs, src/event/sys/windows/parse.rs. The codebase includes complex terminal parsing logic (src/event/sys/unix/parse.rs and src/event/sys/windows/parse.rs) for ANSI escape sequences and Windows terminal events. Complex parsing logic can be vulnerable to buffer overflows, denial of service, or escape sequence injection attacks. Fix: Conduct thorough fuzzing of terminal input parsing logic. Validate and sanitize all terminal input. Ensure buffer boundaries are properly checked and no unbounded reads occur. - Low · Platform-Specific Signal Handling —
src/event/sys/unix/, Cargo.toml - signal-hook dependency. The codebase uses signal-hook and signal-hook-mio for Unix signal handling in event processing. Improper signal handling can lead to race conditions or signal handler vulnerabilities. Fix: Review signal handler implementation for race conditions and ensure handlers are async-signal-safe. Use signal-hook's high-level APIs rather than low-level signal manipulation. - Low · Windows API Usage via winapi —
src/cursor/sys/windows.rs, src/event/sys/windows/, Cargo.toml - winapi dependency. The codebase uses the winapi crate for Windows terminal operations. Direct Windows API calls can introduce security risks if not properly validated, particularly around file descriptor operations and system calls. Fix: Ensure all Windows API calls are properly error-checked. Validate all handle operations and file descriptor manipulations. Keep winapi and crossterm_winapi dependencies updated.
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.