sharkdp/pastel
A command-line tool to generate, analyze, convert and manipulate colors
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 1w ago
- ✓26+ active contributors
- ✓Distributed ownership (top contributor 38% of recent commits)
Show all 6 evidence items →Show less
- ✓Apache-2.0 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/sharkdp/pastel)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/sharkdp/pastel on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: sharkdp/pastel
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/sharkdp/pastel 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 1w ago
- 26+ active contributors
- Distributed ownership (top contributor 38% of recent commits)
- Apache-2.0 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 sharkdp/pastel
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/sharkdp/pastel.
What it runs against: a local clone of sharkdp/pastel — 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 sharkdp/pastel | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | 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 ≤ 37 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of sharkdp/pastel. If you don't
# have one yet, run these first:
#
# git clone https://github.com/sharkdp/pastel.git
# cd pastel
#
# 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 sharkdp/pastel and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "sharkdp/pastel(\\.git)?\\b" \\
&& ok "origin remote is sharkdp/pastel" \\
|| miss "origin remote is not sharkdp/pastel (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 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/types.rs" \\
&& ok "src/types.rs" \\
|| miss "missing critical file: src/types.rs"
test -f "src/parser.rs" \\
&& ok "src/parser.rs" \\
|| miss "missing critical file: src/parser.rs"
test -f "src/cli/cli.rs" \\
&& ok "src/cli/cli.rs" \\
|| miss "missing critical file: src/cli/cli.rs"
test -f "src/cli/commands/mod.rs" \\
&& ok "src/cli/commands/mod.rs" \\
|| miss "missing critical file: src/cli/commands/mod.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 37 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~7d)"
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/sharkdp/pastel"
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
pastel is a Rust CLI tool for generating, analyzing, converting, and manipulating colors across multiple color spaces (RGB, HSL, CIELAB, CIELCh) and formats (hex, CSS names, ANSI 8/24-bit). It enables composable color operations via Unix pipes, letting users chain commands like pastel random | pastel mix red | pastel lighten 0.2 | pastel format hex to transform colors. Modular binary-centric design: src/cli/main.rs is the entry point, with src/cli/cli.rs defining the clap argument parser. Commands live in src/cli/commands/* (gradient.rs, sort.rs, distinct.rs, etc.). Core color logic lives in src/ as libraries: colorspace.rs handles RGB/HSL/Lab conversions, parser.rs parses color strings (via nom), named.rs maps X11 color names, and delta_e.rs computes perceptual distance. The types.rs and helper.rs provide shared utilities.
👥Who it's for
Terminal-based developers, shell script authors, and data visualization engineers who need programmatic color manipulation without leaving the command line. Specifically: system administrators automating colored terminal output, designers building color palettes via CLI, and developers who need color format conversion and perceptual color operations (like ΔE color distance).
🌱Maturity & risk
Production-ready. The project is at v0.12.0 with a stable Rust 1.83.0 MSRV, comprehensive CI/CD via GitHub Actions (CICD.yml), dual MIT/Apache-2.0 licensing, and evidence of active maintenance (benches/, build.rs for completions). The codebase is well-structured with clear command separation and meaningful abstractions around color spaces.
Low risk. Dependencies are minimal and stable (nom 7.1.3 for parsing, clap 4 for CLI, rand 0.9 for generation)—all widely-used crates. Single maintainer (sharkdp) is a known Rust community contributor, but no open issue/PR data provided to assess backlog. No breaking changes visible in recent structure. The LTO + strip release profile suggests production maturity.
Active areas of work
No specific PR/milestone data visible, but the repo structure shows mature feature completeness: color picking (colorpicker.rs using hdcanvas.rs for terminal canvas rendering), gradient generation, color distinctness algorithms (distinct.rs), colorcheck command (colorcheck.rs), and paint/format utilities. The benches/parse_color.rs benchmark suggests ongoing optimization of the nom-based parser.
🚀Get running
git clone https://github.com/sharkdp/pastel.git
cd pastel
cargo build --release
./target/release/pastel --help
Or install from crates.io: cargo install pastel.
Daily commands:
cargo build
cargo run -- --help
cargo run -- random | cargo run -- lighten 0.2 | cargo run -- format hex
cargo test
cargo bench --bench parse_color
🗺️Map of the codebase
src/lib.rs— Core library export point; defines public API for color types, parsing, and manipulation—essential for understanding what functionality is exposedsrc/types.rs— Defines the Color struct and core color space representations (RGB, HSL, CIELAB, CIELCh); foundational to all color operationssrc/parser.rs— Nom-based parser for multiple color formats; critical for input handling and format conversionsrc/cli/cli.rs— CLI argument parsing and main entry point using Clap; routes all user commands to subcommand handlerssrc/cli/commands/mod.rs— Command module coordinator; re-exports all available commands (saturate, mix, paint, gradient, etc.)src/colorspace.rs— Color space conversion algorithms (RGB↔HSL, RGB↔CIELAB, etc.); mathematical core of color transformationssrc/delta_e.rs— Delta E color difference calculations; used for color analysis and distinction algorithms
🛠️How to make changes
Add a new color manipulation command
- Create a new command module in src/cli/commands/ (e.g., src/cli/commands/my_command.rs) (
src/cli/commands/my_command.rs) - Implement pub fn run(color: Color, args: MyCommandArgs) -> Result<Color> with your transformation logic (
src/cli/commands/my_command.rs) - Add the module to src/cli/commands/mod.rs with pub mod my_command; (
src/cli/commands/mod.rs) - Add a new subcommand struct and case in src/cli/cli.rs to wire Clap arguments (
src/cli/cli.rs) - Dispatch the command in src/cli/main.rs within the Commands enum match block (
src/cli/main.rs)
Add support for a new color format
- Add a new variant to the ColorSpace enum in src/types.rs (e.g., ColorSpace::MyFormat) (
src/types.rs) - Extend the Color impl in src/types.rs with conversion methods (to_my_format, from_my_format) (
src/types.rs) - Add parsing rule(s) to src/parser.rs using Nom combinators (
src/parser.rs) - Add formatting case to src/cli/commands/format.rs Display impl (
src/cli/commands/format.rs) - Update src/colorspace.rs with conversion logic to/from standard RGB and other spaces (
src/colorspace.rs)
Add a new color analysis/metrics command
- Implement analysis logic in a new module (e.g., src/analysis.rs or extend src/delta_e.rs) (
src/delta_e.rs) - Create command handler in src/cli/commands/ (e.g., src/cli/commands/analyze.rs) (
src/cli/commands/analyze.rs) - Wire command into src/cli/cli.rs with Clap argument definitions (
src/cli/cli.rs) - Dispatch in src/cli/main.rs and format output via src/cli/output.rs (
src/cli/main.rs)
🔧Why these technologies
- Nom parser combinator library — Efficient, composable parsing of multiple color format grammars (hex, rgb(), hsl(), lab(), named colors) in a single unified parser
- Clap CLI framework — Declarative argument parsing with automatic help generation, suggestions, and subcommand routing; reduces boilerplate for complex CLI structure
- CIELAB/CIELCh/Delta E — Perceptually uniform color space enables accurate color difference metrics for distinct color generation and accessibility analysis
- Rand crate for random color generation — Provides cryptographically sound randomness for color generation without external dependencies
⚖️Trade-offs already made
-
Pure Rust, no C bindings for color math
- Why: Simplifies build, portability, and memory safety
- Consequence: Color space conversions are pure functions but slightly slower than SIMD-optimized C libraries; adequate for interactive use
-
Single-threaded command execution
- Why: Simplifies state management and piping; CLI tools typically run short-lived, single operations
- Consequence: Batch operations (e.g., gradient with 1000 colors) are not parallelized; acceptable for typical use but limits throughput
-
Pipe-based composition over config files
- Why: Aligns with Unix philosophy; commands compose naturally via stdout/stdin
- Consequence: Complex multi-step workflows require shell piping; no persistent state or saved presets
🚫Non-goals (don't propose these)
- Interactive GUI—pastel is CLI-only (except pick command which uses terminal UI)
- Real-time color picking from screen (pick command is interactive terminal input, not screen capture)
- Network/online color palette services
- Plugin/extension system
- Batch image processing or image file manipulation
🪤Traps & gotchas
Color space conversions assume sRGB (no profile handling for wide gamut). Parser is strict: whitespace in rgb() matters (nom is position-sensitive). ANSI detection via output_vt100 requires TTY detection—piped output may disable color. Terminal color picking (pick command) uses raw mode and may leave terminal in a bad state if interrupted ungracefully. No caching of parsed colors—each parse is fresh (nom does not memoize). Bench baseline missing: benches/parse_color.rs exists but Criterion baseline data is not in the repo, so relative performance changes won't show without running locally.
🏗️Architecture
💡Concepts to learn
- Color Space Conversion (RGB ↔ HSL ↔ Lab) — pastel's core feature; understanding sRGB → XYZ → Lab conversions is essential to modify colorspace.rs and understand why certain operations (lighten, saturate) work differently in different spaces
- CIE ΔE (Delta E) Color Distance — Used in distinct.rs and sort.rs to measure perceptual color similarity; critical for the distinct command's algorithm and color comparison logic
- ANSI 256-Color & Truecolor (24-bit) — pastel must map RGB colors to terminal capabilities via src/ansi.rs; understanding ANSI escape codes is necessary to debug output or add new formatting modes
- Parser Combinators (nom) — src/parser.rs uses nom's combinator API to handle diverse color input formats; modifying or extending color parsing requires understanding nom's declarative parsing model
- sRGB Gamma Correction — RGB values must be gamma-corrected before Lab conversion; omitting this causes incorrect perceptual results in colorspace.rs
- Unix Pipe Composition (Streaming Design) — pastel's entire value proposition relies on composability—each command reads stdin and writes stdout; understanding how colors flow through piped commands is essential to design new operations
- Clap Declarative CLI Parsing — src/cli/cli.rs defines all arguments, subcommands, and help text via clap macros; adding new flags or commands requires understanding clap's builder API
🔗Related repos
BurntSushi/ripgrep— Similar Rust CLI philosophy: single-purpose, composable, focus on performance and UX; sharkdp also authored fd which ripgrep inspiredsharkdp/fd— Same author, same ecosystem; parallel tool for file finding vs. color manipulation, shows pastel author's pattern of Rust CLI excellencesharkdp/bat— Same author; cat clone with syntax highlighting that pairs well with pastel for colorized output pipelinesolimorris/colorbuddy.nvim— Neovim color picker and palette tool; complementary for developers who want terminal + editor color workflowstermstandard/colors— ANSI color standard reference; relevant for understanding the 8-bit/24-bit ANSI output targets in src/ansi.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 integration tests for all color command subcommands in src/cli/commands/
The repo has tests/integration_tests.rs but analyzing the file structure shows 11+ command modules (format.rs, gradient.rs, gray.rs, distinct.rs, paint.rs, random.rs, sort.rs, colorcheck.rs, pick.rs, etc.) with no visible corresponding test coverage. Adding comprehensive integration tests for each command's various flag combinations and color input formats would improve reliability and prevent regressions.
- [ ] Review existing integration_tests.rs to understand current test patterns
- [ ] Add integration tests for src/cli/commands/gradient.rs covering gradient generation with different color stops
- [ ] Add tests for src/cli/commands/sort.rs with various sort criteria (hue, saturation, lightness)
- [ ] Add tests for src/cli/commands/distinct.rs validating color distinctness calculations
- [ ] Add tests for src/cli/commands/paint.rs with different ANSI color modes
- [ ] Run
cargo test --test integration_teststo verify all tests pass
Add benchmark suite for color parsing and manipulation operations in benches/
The repo has a parse_color.rs benchmark but only tests parsing. Given the performance-sensitive nature of color operations (mixing, conversion, delta-e calculations), adding benchmarks for src/delta_e.rs, src/colorspace.rs conversion functions, and src/distinct.rs distinctness calculations would help maintainers catch performance regressions and optimize hot paths.
- [ ] Create benches/colorspace_conversion.rs to benchmark RGB↔HSL↔CIELAB conversions from src/colorspace.rs
- [ ] Create benches/delta_e_calculations.rs to benchmark ΔE calculations from src/delta_e.rs
- [ ] Create benches/color_mixing.rs to benchmark color mixing operations
- [ ] Run
cargo benchand document baseline performance numbers in CHANGELOG.md - [ ] Add benchmark comparisons to CI/CD workflow to prevent performance regressions
Document color format specifications and conversion algorithms in doc/
The repo supports multiple color spaces (RGB, HSL, CIELAB, CIELCh, ANSI) as stated in README, but doc/ only contains colorcheck.md and demo scripts. Adding technical documentation for supported formats would help contributors understand the color space implementations in src/colorspace.rs, src/parser.rs, and src/delta_e.rs.
- [ ] Create doc/color-formats.md documenting all supported formats (hex, rgb, hsl, lab, lch, ansi, named colors) with examples
- [ ] Create doc/color-spaces.md explaining CIELAB vs CIELCh vs HSL conversion algorithms with references to src/colorspace.rs implementations
- [ ] Create doc/delta-e.md documenting Delta E color difference calculations referenced in src/delta_e.rs
- [ ] Add examples of edge cases (e.g., grayscale handling in HSL, achromatic colors in CIELAB)
- [ ] Update README.md with links to the new documentation files
🌿Good first issues
- Add integration tests in tests/ directory for the round-trip conversions (e.g., parse hex → convert to HSL → convert back to RGB → format hex, verify byte-for-byte match). Currently, colorspace.rs has unit tests but no end-to-end format stability tests.
- Extend src/named.rs CSS color name list: verify all X11 + CSS3 named colors are present, add missing ones with tests. Current scope is unclear from file; cross-check against web standards and file a PR with additions.
- Add --profile flag to pastel pick command to preview colors under different simulated color blindness modes (protanopia, deuteranopia, tritanopia) using existing ΔE + Lab conversions. Code structure in delta_e.rs and colorspace.rs is already there.
⭐Top contributors
Click to expand
Top contributors
- @dependabot[bot] — 38 commits
- @sharkdp — 17 commits
- [@David Peter](https://github.com/David Peter) — 7 commits
- @sameoldlab — 4 commits
- @joveian — 3 commits
📝Recent commits
Click to expand
Recent commits
01d4252— Bump actions/upload-artifact from 6 to 7 (dependabot[bot])426ec9e— Bump regex from 1.12.2 to 1.12.3 (dependabot[bot])18b9cf9— Bump clap_complete from 4.5.65 to 4.5.66 (dependabot[bot])314ba4c— Bump clap from 4.5.56 to 4.5.60 (dependabot[bot])5e9f9c0— Bump to v0.12.0 (sharkdp)3121f6c— Add ANSI 8-bit parsing (sharkdp)74a0fc8— Fix #289 (sharkdp)7b9335f— Update cargo_bin call, closes #288 (sharkdp)616bdd5— Bump actions/checkout from 5 to 6 (dependabot[bot])15cee26— Replace atty dependency with std::io::IsTerminal (breaking) (musicinmybrain)
🔒Security observations
The pastel codebase demonstrates good security practices overall. As a command-line color utility written in Rust, it has minimal attack surface. No hardcoded secrets, injection vulnerabilities, or critical issues were identified. The main areas for improvement are: (1) adding automated dependency vulnerability scanning to CI/CD, (2) reviewing the usage of the 'rand' crate to ensure it's appropriate for the use case, and (3) maintaining regular updates to dependencies and Rust version. The project uses standard security practices including Cargo.lock, multiple licensing options, and LTO/stripping in release builds.
- Low · Outdated Rust MSRV —
Cargo.toml. The project specifies rust-version = '1.83.0', which is relatively recent but should be regularly reviewed. While not a direct vulnerability, using very old MSRV can expose the project to known compiler bugs. Fix: Maintain the MSRV as a reasonable balance between compatibility and access to compiler improvements. Consider updating documentation on why this specific version is required. - Low · Dependency on 'rand' crate —
Cargo.toml, src/random.rs. The project uses 'rand' crate version 0.9 for random color generation. While rand is a well-maintained crate, ensure it's being used appropriately (i.e., not for cryptographic purposes where rand::rngs::OsRng should be used). Fix: Review usage in src/random.rs to ensure rand is appropriate for the use case. If used for non-cryptographic color generation, current usage is acceptable. Add comments clarifying this is not for security-sensitive operations. - Low · Incomplete dependency audit trail —
.github/workflows/CICD.yml. While Cargo.lock is present (good practice), the project does not appear to have security audit tooling configured in CI/CD (no cargo-audit or cargo-deny in visible workflow files). Fix: Add 'cargo audit' or 'cargo-deny' checks to the CI/CD pipeline to automatically detect known vulnerabilities in dependencies.
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.