🎨 Rcolor
High-Performance, Terminal-Aware Color & ANSI Styling Engine for Python
Sample console outputs generated dynamically with Rcolor.
🌟 Introduction
Make your CLI applications look stunning with zero configuration.
Rcolor is an ultra-fast, zero-bloat Python library designed to bring colorful foregrounds, vibrant background highlights, terminal font styles, and per-character rainbow output to your terminal. Equipped with automatic terminal capability detection, Rcolor dynamically detects color depths (TrueColor > 256 colors > 16 colors > Plain Text) and automatically downsamples 256-color palettes to standard ANSI colors on restricted terminals—ensuring your terminal output looks flawless on Linux, macOS, and Windows.
🗺️ Quick Navigation
🚀 Quick Start
Get colorful terminal output in 3 simple commands:
# 1. Install or upgrade Rcolor from PyPI
pip install -U Rcolor
# 2. Print an automatically optimized random colorful message
python -c "import Rcolor; print(Rcolor.auto_fg('✨ Hello Beautiful Terminal! ✨'))"
# 3. Print per-character rainbow output
python -c "import Rcolor; print(Rcolor.rainbow_fg('🌈 Dynamic Rainbow Console Output'))"
✨ Key Features
| Feature | Description | Highlight |
|---|---|---|
| Lightning-Fast Execution | Built on precomputed tuples with zero disk I/O at runtime and $O(N)$ string joins. | ⚡ 1.8 µs per call (~327x faster) |
| Intelligent Terminal Detection | Automatically inspects environment variables, TTY streams, and OS console APIs. | 🧠 Auto TrueColor / 256 / 16 / None |
| Automatic Downgrading | Maps 256-color escape codes to the nearest ANSI 16 color via Euclidean RGB distance. | 🎯 Flawless legacy terminal fallback |
| Contrast Guard | Dynamically enforces WCAG relative luminance contrast ratios ($\ge 4.0:1$) for dual styling. | 👁️ Guaranteed text readability |
| Curated Tone Presets | Filter colors by cohesive aesthetic tones: neon, pastel, warm, and cool. |
🎨 High-end palette curation |
| Smooth Linear Gradients | Linear per-character color interpolation with multi-stop presets and TrueColor depth. | 🌈 Seamless gradient banners |
| Universal Standards Compliance | Respects NO_COLOR, FORCE_COLOR, CLICOLOR, and pipe redirections natively. |
🛡️ Clean CLI & CI logs |
| External JSON Palette | Color definitions stored in Rcolor/data/colors.json, loaded lazily on first access. |
📦 Clean architecture & lazy load |
| Custom Palette Support | Load your own brand or project themes via Rcolor.load_palette(). |
🎨 Full JSON schema flexibility |
| 100% Backward Compatibility | All original v3.0 public APIs remain functional with identical arguments and return types. | 🔒 Zero breaking API changes |
| Fully Typed (PEP 561) | Includes py.typed marker and comprehensive type hints for IDE autocompletion. |
💡 Type checker friendly |
🖥️ Terminal Compatibility Matrix
Rcolor automatically detects console capabilities and delivers optimal rendering:
| Terminal / Platform | TrueColor (24-bit) | 256 Colors (8-bit) | 16 Colors (4-bit) | Notes |
|---|---|---|---|---|
| Windows Terminal | ✅ Full | ✅ Full | ✅ Full | Natively detected via WT_SESSION |
| PowerShell 7+ | ✅ Full | ✅ Full | ✅ Full | Native VT support on modern Windows builds |
| Legacy cmd.exe | 🔄 Auto-Downgraded | 🔄 Auto-Downgraded | ✅ Full | Uses colorama VT initialization when available |
| GNOME Terminal | ✅ Full | ✅ Full | ✅ Full | Detected via COLORTERM=truecolor |
| Konsole (KDE) | ✅ Full | ✅ Full | ✅ Full | Full 24-bit TrueColor rendering |
| iTerm2 (macOS) | ✅ Full | ✅ Full | ✅ Full | Detected via TERM_PROGRAM=iTerm.app |
| Terminal.app (macOS) | 🔄 Auto-Downgraded | ✅ Full | ✅ Full | Detected via TERM_PROGRAM=Apple_Terminal |
| tmux / screen | ✅ Full | ✅ Full | ✅ Full | Handles nested terminal session strings |
| VS Code Terminal | ✅ Full | ✅ Full | ✅ Full | Detected via TERM_PROGRAM=vscode |
| PyCharm / IntelliJ | ✅ Full | ✅ Full | ✅ Full | Detected via PYCHARM_HOSTED / TERMINAL_EMULATOR |
| Jupyter / IPython | 🔄 Auto-Downgraded | ✅ Full | ✅ Full | Native ANSI support in web notebook cells |
CI Logs / Pipes (> file) |
🚫 Disabled | 🚫 Disabled | 🚫 Disabled | Output safely stripped to plain text |
🔍 How Automatic Capability Detection & Fallback Hierarchy Works
Rcolor inspects your execution context using the following deterministic hierarchy:
- Explicit Standards:
NO_COLOR(always plain text) >FORCE_COLOR(0/1/2/3) >CLICOLOR_FORCE>CLICOLOR. - Stream Target:
sys.stdout.isatty()verifies output is attached to an interactive terminal rather than a log file or redirected pipe. - IDE / Notebook Isolation: Detects Jupyter notebooks (
ipykernel) and IDLE (idlelib). - Multiplexers & SSH: Detects
tmux,screen, andSSH_CONNECTIONsessions. - Windows VT Engine: Activates Windows Virtual Terminal Processing on Windows 10/11 or initializes
coloramafallback. - Nearest-Color Downgrade: If 256 colors are requested on an ANSI 16 console, colors are projected into standard 16 space via Euclidean RGB distance ($O(1)$ lookup table).
🧬 Detection & Downgrading Architecture
The ASCII diagram below illustrates how Rcolor determines color capabilities and renders output:
+----------------------------------+
| User calls Rcolor function |
| (e.g., auto_fg, foreground) |
+-----------------+----------------+
|
v
+----------------------------------+
| Check NO_COLOR or stdout != TTY |
+-----------------+----------------+
/ \
YES / \ NO
+--------------+ +-------------------+
| Return plain | | Check FORCE_COLOR |
| text string | | or COLORTERM/TERM |
+--------------+ +---------+---------+
|
+--------------------------+--------------------------+
| | |
v v v
[ TrueColor / 256 ] [ 16-Color ] [ Dumb / None ]
| | |
+----------+----------+ +---------+----------+ +--------+---------+
| Use 256-color code | | Map 256 color to | | Output plain |
| (\033[38;5;{id}m) | | nearest ANSI 16 via| | string without |
| | | RGB Euclidean dist | | ANSI escapes |
+----------+----------+ +---------+----------+ +--------+---------+
| | |
+--------------------------+--------------------------+
|
v
+-------------------------------+
| Append clean '\033[0m' reset |
+-------------------------------+
⚡ Benchmarks
Benchmarks measured on Python 3.14 comparing Rcolor v3.0.1 (legacy) vs Rcolor v3.1.0 (current):
| Metric | Legacy (v3.0.1) | Optimized (v3.1.0) | Speedup Factor |
|---|---|---|---|
| Import Time (fresh) | 0.673 ms | 1.601 ms | Lazy zero-cost imports |
foreground() call latency |
250.91 µs | 1.85 µs | 135.7x faster 🚀 |
rainbow_fg() (1,000 chars) |
147.40 ms | 0.45 ms | 327.1x faster 🚀 |
To reproduce these measurements locally:
python benchmarks/bench.py
⚙️ Benchmark Reproduction & Methodology Details
All benchmarks use Python's built-in timeit module:
- Import Time: Evaluates fresh module imports after removing
Rcolorfromsys.modulesacross 200 iterations. - Function Latency: Evaluates 10,000 iterations of
Rcolor.foreground("Hello, World!"). - Rainbow Throughput: Evaluates 200 iterations of
Rcolor.rainbow_fg("A" * 1000)measuring per-character join performance.
📖 Usage Guide
1. Basic Importing
import Rcolor
# Or import specific functions
from Rcolor import (
foreground,
background,
style,
rainbow_fg,
standard_fg,
standard_bg,
standard_rainbow_fg,
auto_fg,
auto_bg,
foreground_background,
foreground_style,
background_style,
foreground_background_style,
)
2. Automatic Terminal-Aware Colors (auto_fg / auto_bg)
Recommended for general use. Chooses 256-color when available, standard 16-color on restricted consoles, and plain text in non-TTY environments:
import Rcolor
# Automatically styled foreground
print(Rcolor.auto_fg("This text adapts to your terminal capabilities!"))
# Automatically styled background
print(Rcolor.auto_bg("Highlighted text with automatic color selection!"))
3. Extended 256-Color Palette (foreground / background)
Applies a random color from the complete 256-color palette. If executed on a 16-color terminal, Rcolor automatically downsamples to the closest ANSI color:
# Random 256 foreground color
print(Rcolor.foreground("Vibrant 256-color foreground"))
# Random 256 background color
print(Rcolor.background("Vibrant 256-color background"))
4. Standard 16-Color Palette (standard_fg / standard_bg)
Guaranteed compatibility with all legacy ANSI terminals:
# Standard 16 ANSI foreground
print(Rcolor.standard_fg("Standard ANSI foreground color"))
# Standard 16 ANSI background
print(Rcolor.standard_bg("Standard ANSI background color"))
5. Font Styles (style)
Applies ANSI text attributes such as bold, dim, italic, and underline:
# Random text style
print(Rcolor.style("Bold, dim, italic, or underlined text!"))
6. Per-Character Rainbow Effects (rainbow_fg / standard_rainbow_fg)
Colorizes every character in the string individually:
# 256-color rainbow (with auto-downgrade)
print(Rcolor.rainbow_fg("Every single character has a unique random color!"))
# Standard 16-color rainbow
print(Rcolor.standard_rainbow_fg("Standard 16-color rainbow string!"))
7. Composite Styling & Readability Contrast Guard
Apply multiple ANSI attributes simultaneously. foreground_background automatically enforces a Contrast Guard based on WCAG 2.1 relative luminance, ensuring the foreground is always crisp and readable against the chosen background:
# Guaranteed readable foreground on background (min_contrast default is 4.0)
print(Rcolor.foreground_background("Always readable text!"))
# Customize contrast ratio (e.g. 7.0:1 for high contrast)
print(Rcolor.foreground_background("High contrast banner", min_contrast=7.0))
# Foreground + Font Style
print(Rcolor.foreground_style("Random foreground AND font style"))
# Background + Font Style
print(Rcolor.background_style("Random background AND font style"))
# Foreground + Background + Font Style with Contrast Guard
print(Rcolor.foreground_background_style("Full composite random styling!"))
8. Curated Tone Presets (neon, pastel, warm, cool)
Instead of pure white-noise randomness, style your console with cohesive aesthetic color themes:
# Vibrant electric neon tones
print(Rcolor.foreground("Neon cyan, lime, magenta & electric orange", tone="neon"))
# Soft, elegant pastel tones
print(Rcolor.foreground("Soft lavender, mint, pastel pink & baby blue", tone="pastel"))
# Warm sunset and amber tones
print(Rcolor.foreground("Rich red, orange, gold & amber tones", tone="warm"))
# Cool ocean and frost tones
print(Rcolor.foreground("Deep blue, cyan, teal & sapphire tones", tone="cool"))
# Tone presets work with auto_fg, auto_bg, and background too:
print(Rcolor.auto_fg("Automated neon theme", tone="neon"))
print(Rcolor.background("Pastel card background", tone="pastel"))
9. Smooth Linear Gradients & Multi-Stop Rainbow
Generate seamless character-by-character color transitions with TrueColor depth and automatic terminal fallback:
# 2-stop gradient from hex colors
print(Rcolor.gradient_fg("Smooth cyberpunk transition!", start="#ff007f", end="#00f0ff"))
# 2-stop gradient from RGB tuples
print(Rcolor.gradient_fg("Deep blue into lime green", start=(0, 0, 255), end=(0, 255, 0)))
# Built-in multi-stop presets: 'rainbow', 'neon', 'sunset', 'warm', 'cool', 'pastel', 'cyberpunk', 'ocean'
print(Rcolor.gradient_fg("Sunset horizon across characters", preset="sunset"))
print(Rcolor.gradient_fg("Electric cyberpunk aesthetic", preset="cyberpunk"))
# Instant smooth multi-stop rainbow text
print(Rcolor.gradient_rainbow("A gorgeous smooth rainbow gradient banner across your terminal!"))
10. ANSI Strip Utility (strip_color)
Cleanly calculate visible string lengths and align formatted CLI tables or progress boxes:
colored_banner = Rcolor.gradient_rainbow("Hello World")
# Strip ANSI codes for clean length measurement
plain_banner = Rcolor.strip_color(colored_banner)
print(len(plain_banner)) # Correctly prints 11, ignoring escape sequences!
🎨 Custom Palette Support
You can supply custom palettes at runtime using Rcolor.load_palette().
JSON Schema
Custom palettes must adhere to the following schema:
{
"schema_version": 1,
"standard": [
{
"id": 0,
"name": "brand_blue",
"fg": 34,
"bg": 44,
"rgb": [0, 102, 204],
"hex": "#0066cc"
}
],
"extended": [
{
"id": 33,
"name": "brand_accent",
"rgb": [0, 153, 255],
"hex": "#0099ff"
}
],
"styles": {
"bold": 1,
"underline": 4
}
}
Loading a Custom Palette in Python
import Rcolor
# Load palette from a JSON file
Rcolor.load_palette("my_brand_palette.json")
# Or load from an in-memory dictionary
Rcolor.load_palette({
"schema_version": 1,
"standard": [{"id": 0, "name": "primary", "fg": 32, "bg": 42}],
"extended": [{"id": 46, "name": "bright_green"}],
"styles": {"bold": 1}
})
# Reset back to default built-in palette at any time
Rcolor.reset_palette()
print(Rcolor.foreground("Styled with custom palette!"))
📋 Complete Formal JSON Schema for Custom Palettes
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "RcolorPalette",
"type": "object",
"required": ["schema_version", "standard", "extended", "styles"],
"properties": {
"schema_version": { "type": "integer", "enum": [1] },
"standard": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "name", "fg", "bg"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"fg": { "type": "integer" },
"bg": { "type": "integer" },
"rgb": { "type": "array", "items": { "type": "integer" } },
"hex": { "type": "string" }
}
}
},
"extended": {
"type": "array",
"items": {
"type": "object",
"required": ["id"],
"properties": {
"id": { "type": "integer", "minimum": 0, "maximum": 255 },
"name": { "type": "string" },
"rgb": { "type": "array", "items": { "type": "integer" } },
"hex": { "type": "string" }
}
}
},
"styles": {
"type": "object",
"additionalProperties": { "type": "integer" }
}
}
}
📚 API Reference
| Function | Parameters | Return Type | Description |
|---|---|---|---|
auto_fg(*user_input, tone=None) |
*user_input: Any, tone: str | None |
str |
Terminal-aware random foreground color (256/16/None), optional tone preset. |
auto_bg(*user_input, tone=None) |
*user_input: Any, tone: str | None |
str |
Terminal-aware random background color (256/16/None), optional tone preset. |
foreground(*user_input, tone=None) |
*user_input: Any, tone: str | None |
str |
Random 256-color foreground with auto-downgrade, optional tone preset ("neon", "pastel", "warm", "cool"). |
background(*user_input, tone=None) |
*user_input: Any, tone: str | None |
str |
Random 256-color background with auto-downgrade, optional tone preset. |
standard_fg(*user_input) |
*user_input: Any |
str |
Random standard ANSI 16 foreground color. |
standard_bg(*user_input) |
*user_input: Any |
str |
Random standard ANSI 16 background color. |
style(*user_input) |
*user_input: Any |
str |
Random ANSI text style (bold, dim, underline, etc.). |
rainbow_fg(user_input) |
user_input: Any |
str |
Per-character random 256-color rainbow string. |
standard_rainbow_fg(user_input) |
user_input: Any |
str |
Per-character random 16-color rainbow string. |
gradient_fg(user_input, start=..., end=..., preset=None) |
user_input: Any, ... |
str |
Smooth linear color gradient with auto TrueColor/256/16/None fallback. |
gradient_rainbow(user_input) |
user_input: Any |
str |
Smooth multi-stop linear rainbow gradient across text. |
foreground_background(*user_input, min_contrast=4.0) |
*user_input: Any, min_contrast: float |
str |
Combined random fg and bg with WCAG Contrast Guard readability guarantee. |
foreground_style(*user_input) |
*user_input: Any |
str |
Combined random foreground and style. |
background_style(*user_input) |
*user_input: Any |
str |
Combined random background and style. |
foreground_background_style(*user_input, min_contrast=4.0) |
*user_input: Any, min_contrast: float |
str |
Combined random fg, bg, and style with WCAG Contrast Guard. |
strip_color(text) |
text: str |
str |
Strips all ANSI escape sequences for width and alignment calculations. |
contrast_ratio(rgb1, rgb2) |
rgb1: Sequence[int], rgb2: Sequence[int] |
float |
Computes WCAG 2.1 relative contrast ratio between two RGB colors (1.0 to 21.0). |
relative_luminance(rgb) |
rgb: Sequence[int] |
float |
Calculates WCAG relative luminance ($L \in [0.0, 1.0]$). |
load_palette(source) |
source: str | Path | dict |
Palette |
Loads and activates custom color palette. |
reset_palette() |
None | None |
Resets active palette back to default built-in palette. |
detect_color_level() |
None | ColorLevel |
Detects terminal color capability level without caching. |
get_color_level() |
None | ColorLevel |
Returns current terminal color capability level (cached). |
set_color_level(level) |
level: ColorLevel | None |
None |
Manually overrides or resets color level. |
🔍 Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
Output shows raw escape codes like \033[38;5;12m |
Terminal does not interpret ANSI sequences (e.g. Windows legacy cmd without VT). | Ensure colorama is installed, or set environment variable FORCE_COLOR=1. |
| Output appears completely uncolored | NO_COLOR is set, or output is redirected to a file or pipe. |
Check echo $NO_COLOR. If writing to terminal pipes, pass FORCE_COLOR=1 or CLICOLOR_FORCE=1. |
| Colors look washed out or different on remote SSH | Remote terminal reports TERM=xterm instead of xterm-256color. |
Run export TERM=xterm-256color in your remote session. |
| TypeError: Unsupported input type | Non-primitive object (such as None or a list) passed to styling function. |
Ensure inputs are strings, numbers, or booleans. |
🤝 Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository on GitHub.
- Create a branch:
git checkout -b feature/my-feature
- Install development dependencies:
pip install -e .[dev]
- Run the test suite:
python -m unittest discover tests # or pytest
- Run the benchmark:
python benchmarks/bench.py - Commit & Push your changes, then submit a Pull Request.
🧪 Running Tests & Quality Checks Across Toolchains
Run the test suite using standard library unittest (zero third-party dependencies required):
python -m unittest discover tests
Or using pytest:
pytest -v
Lint with ruff and flake8:
ruff check .
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
📷 Visual Assets Required
To complete the visual presentation in the README, please create and place the following image assets into docs/images/:
| Image File Path | Target Dimensions | Description & Content to Show |
|---|---|---|
docs/images/rcolor_banner.png |
1280 x 400 px | Centered project banner featuring modern typographic "Rcolor" logo with vibrant gradient glow on a sleek dark background (#0f172a). |
docs/images/preview_foreground.png |
800 x 480 px | Terminal screenshot demonstrating 8 lines of text generated by Rcolor.foreground() showing diverse 256-color foregrounds. |
docs/images/preview_rainbow.png |
800 x 480 px | Terminal screenshot demonstrating Rcolor.rainbow_fg() showing multi-line vibrant per-character rainbow text. |
docs/images/preview_styles.png |
800 x 480 px | Terminal screenshot demonstrating foreground_background_style() showing bold, underline, and dual-tone color combinations. |
docs/images/preview_gradient.png |
800 x 480 px | Terminal screenshot demonstrating gradient_fg() and gradient_rainbow() showing smooth continuous multi-stop gradients across text. |
📄 License
This project is licensed under the terms of the MIT License.
Metadata
Release files for Rcolor 3.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rcolor-3.1.0.tar.gz | 48.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rcolor-3.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 77.5 kB
Release files / rcolor-3.1.0.tar.gz
| Download URL | rcolor-3.1.0.tar.gz |
|---|---|
| Size | 48.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
758c81b895c5bf49a40c9461efd5362c80718e9d00b22a00f5ca5963c6b69791
|
|
BLAKE2b-256 checksum How to use checksums |
628809fbdf4d02843499fd72f21d1d9a46fd7b61f925a88930a65c2930e0f74b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / rcolor-3.1.0-py3-none-any.whl
| Download URL | rcolor-3.1.0-py3-none-any.whl |
|---|---|
| Size | 29.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
456c08aab0de2bf4ac53afe29ea1d44bb20fe87125fdd2a70bf7830ee424e396
|
|
BLAKE2b-256 checksum How to use checksums |
a1f5b2d4a8b62afb36deaff32b624fbbc729fe89dfcb52750a6613c4fffd33c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log