strip-ansi-escapes

Strips ANSI escape sequences from byte streams so colored terminal output can be logged or shown as plain text.

Library
Cargo
v0.2.1
49stars
Apache-2.0 OR MIT

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
24/100Needs Attention
Development Activity0
Maintenance0
Community24
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture68
Code Quality75
Innovation60
Learning Curve55

strip-ansi-escapes is a small Rust crate that removes ANSI escape sequences from byte sequences, turning color- and cursor-control-laden terminal output into plain text. It exposes a strip function that takes any byte slice and returns a Vec<u8> with escapes removed, plus a strip_str convenience function for UTF-8 strings.

For streaming use cases, the crate provides a Writer<W> type that wraps any std::io::Write implementation and strips escape sequences from data as it is written, buffering output line by line via an internal LineWriter. This makes it straightforward to pipe colored subprocess output (e.g. from cargo build) into a log file or non-terminal destination without hand-parsing ANSI codes.

What You Get

  • strip() function - Takes any AsRef<[u8]> byte slice and returns a Vec<u8> with all ANSI escape sequences removed.
  • strip_str() helper - Convenience wrapper for UTF-8 &str input/output so callers don’t have to convert to and from bytes manually.
  • Writer<W> adapter - A std::io::Write implementation that strips escapes from data as it’s written, letting you pipe streaming output directly into a file or buffer.
  • vte-based parsing - Escape sequence detection is delegated to the vte crate’s real ANSI parser state machine, the same crate used by terminal emulators like Alacritty.

Common Use Cases

  • Logging colored CLI output - Capture a subprocess’s colorized stdout/stderr and write clean, escape-free text to a log file.
  • Terminal output in test assertions - Strip ANSI codes from captured terminal output before comparing it to plain-text expectations in tests.
  • Non-terminal display of terminal output - Show program output in a UI, email, or report that can’t render ANSI escape sequences.
  • Piping build tool output - Clean up compiler or build tool output (e.g. cargo, npm) before further text processing or storage.

Under The Hood

Architecture The crate is a single src/lib.rs file with a clear three-layer data flow: the public API (strip, strip_str, Writer<W>) hands bytes to a private Performer<W> struct, which implements the vte::Perform trait and holds a std::io::LineWriter<W>; a vte::Parser drives that Performer via advance(), calling print() for plain characters and execute() for control bytes like newlines. This keeps parsing (delegated entirely to vte) cleanly separated from output buffering (the LineWriter), with the generic W: Write bound as the only injection point — swapping the underlying writer (Vec<u8>, Stdout, a file) requires no changes to the stripping logic itself.

Tech Stack The crate has exactly one runtime dependency, vte 0.14 (with default features disabled), the same VT100/ANSI parser used by terminal emulators such as Alacritty, plus doc-comment 0.3 as a dev-dependency to doctest the README’s examples against src/lib.rs. There is no build tooling beyond Cargo itself and no async runtime, network, or filesystem dependency — the crate operates purely on in-memory byte streams and anything implementing std::io::Write.

Code Quality Unit tests in src/lib.rs cover simple stripping, newline handling, and multi-line escaped build output; doctests embedded in the public API’s doc comments and in the README (via doc_comment::doctest!) are exercised through cfg(doctest). CI (.github/workflows/rust.yml) runs cargo check, cargo test, cargo fmt --check, and cargo clippy on every push and PR, enforcing both correctness and style. Error handling propagates io::Result through Writer::write, capturing any Performer write error and returning it on the next call; the top-level strip() function calls .expect() only on the documented invariant that writing to an in-memory Vec<u8> cannot fail.

API Design The public surface is intentionally tiny — two functions and one generic type — covering both one-shot (strip, strip_str) and streaming (Writer<W>) use cases with idiomatic Rust naming and a Writer that behaves exactly like any other std::io::Write implementor, so there’s effectively zero boilerplate to start using it. It leans on the well-exercised vte parser rather than inventing its own ANSI-matching logic, trading novelty for correctness and reliability.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search