# owo-colors gives Rust terminals colour without allocating or depending on std

> owo-colors is a MIT licensed Rust crate for terminal colour that works in no_std environments, allocates nothing, supports every standard formatter trait, and can decide at runtime whether the output stream deserves colour at all. Its current version is 4.4.0, its MSRV is Rust 1.83, and it carries no dependencies unless you opt in to terminal detection.

**owo-colors/owo-colors** — A zero-allocation no_std-compatible zero-cost way to add color to your Rust terminal

- Repository: https://github.com/owo-colors/owo-colors
- Website: https://docs.rs/owo-colors
- Stars: 814 · Forks: 41
- Language: Rust
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/owo-colors-owo-colors

## Zero allocation, and no_std as a first class target

owo-colors is described as a zero-allocation, no_std compatible, zero-cost way to add colour to a Rust terminal, and the package categories say the same thing more formally, with command-line-interface and no-std::no-alloc listed.

That combination is the reason the crate exists and the reason it is shaped the way it is. The usual terminal colour crates build a String, push escape sequences into it, and hand that String to the formatter, which means an allocation on every coloured value. owo-colors avoids that by writing the escape sequences straight into the formatter's output stream, so the cost of colouring a number is the bytes themselves and nothing else.

The no_std support follows from the same design. A crate that can only be used with the standard library cannot be used in a kernel, in a bootloader, in firmware, or in a constrained embedded binary, and the README makes that point with a line about embedded systems deserving to be pretty too.

The dependency situation is part of the design as well. The README lists dependency-less by default among the supported features, and the manifest carries no required dependencies, so a plain owo-colors = "4" line in a Cargo.toml pulls in nothing else. Colour detection is opt-in through the supports-colors feature, which the manifest explains in a comment: the crate enables conversions from all versions of supports-color but only uses the latest to decide whether colours are supported, and it deliberately avoids the older dep:supports-color because a broken crate in the wild uses that nonfunctional feature name.

That is the kind of detail that only appears in a manifest comment after a real incident, and it is a good sign about the maintainer.

## Every formatter trait, not just Display

The supported list is the clearest statement of the crate's scope, and it is longer than the usual one.

The README marks as supported all the std and core formatters: Display, Debug, Octal, LowerHex, UpperHex, Pointer, Binary, LowerExp and UpperExp. That is the difference between a crate you can bolt onto your existing types and one that only works if you call its own wrapper.

The example shows the intended shape.

```rust
use owo_colors::OwoColorize;

fn main() {
    // Foreground colors
    println!("My number is {:#x}!", 10.green());
    // Background colors
    println!("My number is not {}!", 4.on_red());
}
```

Because the colour is applied through a trait on the value itself rather than through a wrapper type, it composes with format strings, and the alternate form works, with the hex formatting specifier, on a coloured value.

Styling is on the same trait.

```rust
use owo_colors::OwoColorize;

println!("{}", "strikethrough".strikethrough());
```

And the crate also positions itself against the older colored crate, describing itself as more or less a drop-in replacement for colored that additionally allows colored to work in a no_std environment.

The style names are hand picked for the ANSI 4-bit and Xterm 8-bit palettes, and the crate adds RGB colour support and the styling variants such as underline and strikethrough on top of the basic normal and bright variants, the 256 colour Xterm mode and the 48-bit truecolor mode.

## Compile time generics or runtime values

There are two ways to pick a colour, and the crate supports both because the two suit different programs.

At compile time, the colour is a generic parameter, and the example shows the pattern.

```rust
use owo_colors::OwoColorize;
use owo_colors::colors::*;

fn main() {
    // Generically color
    println!("My number might be {}!", 4.fg::<Black>().bg::<Yellow>());
}
```

Here Black and Yellow are types rather than values, so the colour is fixed when the code is compiled and the formatter can emit the exact bytes every time.

At runtime, the colour is a value, which is what you need when the colour comes from configuration, from a command line flag, or from a theme. The repository's examples directory makes the range of the API visible, with separate files for all_xterm_colors, banner, colors, const_colors, custom_colors, dyn_colors, extra_colors, override and supports_color.

The const_colors and dyn_colors examples are the pair that matters, because they show the same colour expressed as a compile time constant and as a runtime value, and the difference in cost between them is the thing the crate is built around. The README also notes that most functions are const, so a colour can be baked into a constant in a program that never allocates.

The custom_colors example covers defining your own colour, which is what you reach for when you need a specific RGB value rather than one of the named palette entries.

## Whether to print colour at all is a separate decision

The optional colour detection is the part of the API that most affects how a command line tool behaves in practice, and the README describes it in detail.

The checking is enabled for CI, because a build server capturing output is usually a context where colour is wanted, and disabled by default for non-terminal outputs, so a program that is piped into a file or another program does not spray escape sequences into it. It is overridable through the NO_COLOR and FORCE_COLOR environment variables, and overridable programmatically through set_override.

There is a helper for the common case.

```rust
use owo_colors::{OwoColorize, Stream::Stdout};

println!(
    "{}",
    "colored blue if a supported terminal"
        .if_supports_color(Stdout, |text| text.bright_blue())
);
```

The README explains what the check actually does: it supports the NO_COLOR and FORCE_COLOR environment variables, checks if the output is a tty, checks if it is running in CI, and therefore likely supports colour, and checks which terminal is being used. The last of those requires the supports-colors feature, which is why the Cargo.toml marks the supports_color and override examples as requiring that feature.

The design choice here is that detection is not automatic but opt-in, so the default build has no dependencies and the detection cost is paid only by programs that want it.

## A conservative MSRV policy and a scripted release

Two pieces of project policy in the repository are worth reading, because they say how the project treats its users over time.

The first is the MSRV policy. The minimum supported Rust version of owo-colors is Rust 1.83, and the README says the library has a conservative MSRV policy: Rust versions from the last twelve months will be supported, the MSRV will only be bumped if required, and if it is bumped it will always occur with a new minor version. The manifest matches with rust-version = 1.83 and edition 2021, and the badge in the README header says the same.

For a library that other people's build systems depend on, a published promise about the floor is more useful than a low number, and this one is spelled out in prose rather than left in a manifest field.

The second is the release tooling. The manifest carries a package.metadata.release block with pre-release replacements that edit the CHANGELOG.md as part of the release: the Unreleased heading is turned into a version heading, the ReleaseDate placeholder becomes the date, and a link to the release tag is inserted. The repository also has a release.toml file at the root. The docs.rs metadata sets all-features = true and passes --cfg doc_cfg to rustdoc, so the full API including the feature gated parts appears in the online documentation.

The release history shows the cadence: v4.4.0 on 2026-08-27, v4.3.0 on 2026-02-22 and v4.2.3 on 2025-09-29, with the last push to the repository on 2026-08-27.

## Where owo-colors is the wrong choice

Three situations rule it out.

The first is a program that needs a themed palette. owo-colors gives you direct access to named ANSI colours, Xterm indices and RGB values, and it is deliberately thin. If your application wants a theme file, a light and dark variant, and a single call that picks the right colour for the current context, you will write that layer, and other crates exist that put it in the crate instead of in your code.

The second is a program that colours formatted output it does not control. The trait based approach means the colour has to be applied at the call site, on the value, inside the format string. If the value comes from a library that prints it for you, there is nowhere to attach the colour, and the whole design does not help.

The third is a case where you need runtime terminal detection but cannot afford the dependency. The supports-colors feature pulls in supports-color, and while the crate is careful about which version of it it uses, the dependency is still there. A program with a hard no-dependency rule is better served by checking a tty once at startup and passing a boolean down.

For everything else, the crate is a small, safe, allocation free way to make a terminal program readable, and the fact that it supports no_std means the same code can run on a device with no allocator at all.

## Conclusion

owo-colors fits a Rust command line tool that wants coloured output, and especially one that has to build in a no_std or no-alloc environment, since the crate itself carries no dependency and allocates nothing by default. It is the wrong choice if you want a design system for a terminal application with themes and a palette abstraction, because the API here is direct styling rather than a themed layer. Before adopting it, decide whether you want colour decided at compile time or at runtime, and read the MSRV policy note, since the crate promises to support Rust versions from the last twelve months and only bumps the floor when required.

## FAQ

### What does owo-colors do and what does it avoid?

It adds colour to Rust terminal output without allocating and without depending on the standard library, so it works in no_std and no-alloc environments. The README lists zero allocation, no_std compatibility, 100 percent safe code and dependency-less by default among its supported features.

### How do I add owo-colors to a Cargo project?

Add owo-colors = "4" to the dependencies in your Cargo.toml, then import the OwoColorize trait and call the style methods such as 10.green() or "strikethrough".strikethrough() on the values you want coloured.

### How does owo-colors decide whether to print colour?

Through the optional supports-colors feature, which checks the NO_COLOR and FORCE_COLOR environment variables, whether the output is a tty, whether it is running in CI, and which terminal is in use. It can also be overridden programmatically with set_override, and the if_supports_color helper applies a style only when the stream supports colour.

### What is the minimum supported Rust version for owo-colors?

Rust 1.83. The README describes a conservative MSRV policy where versions from the last twelve months are supported, the floor is only bumped when required, and any bump happens with a new minor version.

### Does owo-colors have any dependencies?

Not by default. The manifest lists no required dependencies, and the terminal detection support comes from the optional supports-colors feature, which the manifest says uses the latest supports-color release, deliberately avoiding an older feature name that a broken crate in the wild uses.

## Sources

- [License: MIT](https://github.com/owo-colors/owo-colors/blob/main/LICENSE)
- [owo-colors/owo-colors on GitHub](https://github.com/owo-colors/owo-colors)
- [Project website](https://docs.rs/owo-colors)
- [README](https://github.com/owo-colors/owo-colors/blob/main/README.md)
- [Releases](https://github.com/owo-colors/owo-colors/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/owo-colors-owo-colors
