CLI tool
sharkdp/pastel avatar
sharkdp/pastel

pastel turns color conversion into a pipe between small subcommands

A command-line tool to generate, analyze, convert and manipulate colors

6,546 stars139 forksRustApache-2.0

At a glance

What is it?
pastel is a Rust command line tool for colors that reads names, hex, bare digits and function syntax, and treats every operation as a filter you can chain. Its man pages and shell completions are compiled from the same argument definition, and its install surface spans ten package managers.
Who is it for?
Reach for pastel when a shell script needs a readable foreground color, a named color for a chart, or a set of visually distinct values, and when you would rather pipe than open an editor. Leave it out when you need palette editing, theme files or contrast scoring against a design system.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • sharkdp/pastel6,546 ★ · +41
Star history
Repository2026-09-232026-11-14
sharkdp/pastel6.5k6.5k

41 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Running the binary with no arguments is how you discover the commands

There is no long option index to memorise. Running the binary on its own prints the list of subcommands, which covers saturate, mix and paint among others:

code
pastel

For a single subcommand you have two spellings of the same thing, `pastel mix -h` and `pastel help mix`. The commands themselves fall into groups that map onto the way people actually work with color: converting (format), inspecting (color), generating (random, distinct), naming (format name), sampling the screen (pick), listing the name table (list), and painting text (paint, textcolor). All of them are subcommands, not flags on one verb, which is why the composition model in the next section works at all.

Seven accepted color spellings, and a dash that means read from stdin

The parser is the widest part of the tool. A single color can be a name, a quoted hex string, a bare hex number, a short three digit form, an rgb function, bare comma separated channels, or an hsl function:

code
lightslategray
'#778899'
778899
789
'rgb(119, 136, 153)'
'119,136,153'
'hsl(210, 14.3%, 53.3%)'

Names and numbers work as positional arguments, so one command can touch several colors at once:

code
pastel lighten 0.2 orchid orange lawngreen

The same list can arrive on standard input, which is what `printf "%s\n" orchid orange lawngreen | pastel lighten 0.2` does. When only some colors should come from the pipe, a bare dash marks the slot explicitly, and that dash is read from standard input:

code
pastel color red | pastel mix - blue

So `red` is the piped color and `blue` is the one on the command line. The color grammar is parsed with nom, and the parse path is the one part of the codebase with a benchmark attached to it.

Composition is the design: generate, mix, lighten, convert

The tutorial states the rule in one line, and that line is the whole mental model:

code
pastel random | pastel mix red | pastel lighten 0.2 | pastel format hex

Four stages, three pipes, no intermediate file. The README says many pastel commands can be composed by piping the output of one command to another. Conversion on its own is the shortest case, `pastel format hsl ff8000` turns a hex value into HSL, and naming works through the same verb, `pastel format name 44cc11`. Two commands exist purely to produce or select colors: `pastel distinct 8` generates a set of eight visually distinct colors, and `pastel pick` grabs a color from somewhere on screen. `pastel list` prints the whole X11 and CSS name table, which is the fastest way to find out what the tool will accept.

textcolor is the piece that matters inside a shell script

The output side is where the tool earns its place in scripts. `pastel textcolor` takes a background and returns a foreground, and `pastel paint` applies a color to text with attributes:

code
bg="hotpink"
fg="$(pastel textcolor "$bg")"

pastel paint "$fg" --on "$bg" "well readable text"

The attribute flags are what turn it into a log formatter, and they compose with piped input:

code
pastel paint -n black --on red --bold "   ERROR!   "
pastel paint -n black --on yellow --bold "  WARNING!  "
pastel paint -n black --on limegreen --bold "    INFO    "
echo -n " Informational message with a "
echo -n "highlighted" | pastel paint -n default --underline
echo " word"

Note the last two lines: the word being underlined is streamed through stdin while the surrounding echo calls build the sentence, so the escape codes wrap only the fragment you pipe.

Man pages and completions are built from the argument definition itself

The build dependencies in Cargo.toml are the interesting part of the design. clap_mangen and clap_complete sit alongside clap in [build-dependencies], next to once_cell and output_vt100, and build.rs is the script that consumes them. Man pages and shell completions are therefore generated from the same clap 4 definition that the binary parses at runtime, which removes the usual drift between a subcommand's flags and its documented flags. The clap features are suggestions, color, wrap_help and cargo, so the help text itself is colored and wraps to the terminal.

The rest of the manifest is small and deliberate: nom for the parser, rand for the random and distinct generators, and regex marked as a binary only dependency. The binary target is src/cli/main.rs, dev dependencies add criterion 0.7 with a parse_color benchmark and assert_cmd for running the binary inside tests, and the release profile sets lto, strip and codegen-units = 1. A [lints.rust] section declares the cfg name pastel_normal_build as expected.

Ten routes in, and only the source route names a Rust version

The installation section is the longest part of the README, and that is a fact about packaging rather than about difficulty. On Debian based systems you can take the release artifact and install it with dpkg:

code
wget "https://github.com/sharkdp/pastel/releases/download/v0.12.0/pastel_0.12.0_amd64.deb"
sudo dpkg -i pastel_0.12.0_amd64.deb

The same section also covers `sudo apt install pastel` from the official Debian repositories, currently in testing and unstable, `sudo pacman -S pastel` from Arch Extra, `nix-env --install pastel`, `brew install pastel` on macOS, `scoop install pastel` and `winget install sharkdp.pastel` on Windows, `sudo snap install pastel`, and `pkgin install pastel` on NetBSD. NetBSD has a second route from source: cd /usr/pkgsrc/graphics/pastel followed by make install. Everything else is told to check the release page for binary builds.

Only the cargo route carries a version requirement. The README asks for Rust 1.83 or higher, and Cargo.toml pins rust-version = 1.83.0 with edition 2021. Two spellings exist there, `cargo install pastel` from the registry, or a clone followed by `cargo install --path ./pastel`. The registry route is the only one that needs no checkout.

It writes escape sequences, it does not restyle anything else

The boundary of the tool is worth stating plainly, because the name invites more than it delivers. pastel produces text: color escapes for a terminal, a hex or HSL string, a name, a set of distinct values. It does not edit theme files, it does not keep a palette library, and it has no notion of a design system to validate against. Converting a color is one command, and so is naming one, but the README shows no command for contrast ratios, for checking a palette against a threshold, or for rewriting a stylesheet.

The second limit is about input. `pastel pick` samples a color from somewhere on screen, which is the one interactive step in the whole tool and the only place where a human has to intervene. Everything else is meant to run unattended in a script, which is also why standard input handling and the dash placeholder matter more here than they would in a graphical editor.

Release dates sit unevenly, and the newest commit is 2026-05-01

Three tagged releases define the cadence: v0.10.0 on 2024-09-06, v0.11.0 on 2025-10-19 and v0.12.0 on 2026-02-14. That is a gap of more than a year, then about four months, then about two and a half months before the last push on 2026-05-01. The project is not archived, and the changelog lives in CHANGELOG.md at the root, so a release is not a prerequisite for using the tool: the clone-and-install route builds from the repository and the release page carries the tagged binaries.

Licensing has a small wrinkle worth knowing before you vendor it into a product. The repository metadata says Apache-2.0, while Cargo.toml says license = "MIT/Apache-2.0" and the README offers either licence at your option, with LICENSE-APACHE and LICENSE-MIT both present at the root.

Editorial conclusion

Reach for pastel when a shell script needs a readable foreground color, a named color for a chart, or a set of visually distinct values, and when you would rather pipe than open an editor. Leave it out when you need palette editing, theme files or contrast scoring against a design system. Check the Rust 1.83 floor before building from source.

Frequently asked questions

how to install pastel

Package managers cover Debian (dpkg or apt), Arch Extra with pacman, Nix, macOS Homebrew, Windows with Scoop or winget install sharkdp.pastel, snap, and NetBSD pkgin. Building from source goes through cargo install pastel and needs Rust 1.83 or higher.

How does pastel choose a readable text color?

pastel textcolor takes the background and returns a foreground you capture in a variable: bg="hotpink" then fg="$(pastel textcolor "$bg")". pastel paint "$fg" --on "$bg" "well readable text" applies it, and flags such as --bold and --underline style the run.

Which color formats can pastel read?

Names such as lightslategray, '#778899', 778899, the short form 789, 'rgb(119, 136, 153)', '119,136,153' and 'hsl(210, 14.3%, 53.3%)'. The same list can be passed as arguments or piped in from standard input.

What color spaces does pastel convert between?

RGB (sRGB), HSL, CIELAB, CIELCh, and the ANSI 8-bit and 24-bit representations. The format subcommand does the work, for example pastel format hsl ff8000, and pastel format name 44cc11 turns a value into its nearest name.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. sharkdp/pastel on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sharkdp-pastel.svg)](https://hysenlabs.com/projects/sharkdp-pastel)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/sharkdp-pastel.svg)](https://hysenlabs.com/projects/sharkdp-pastel)

Was this useful?