Every module in a CLI codebase ends up inventing its own way to print "success" or "error." One file uses green text, another uses an emoji, a third does both differently. Output looks inconsistent, breaks in CI, and nobody notices until a log line leaks a password.
# before
print("\033[32mSuccess\033[0m")
# after
print(paint("Success", intent="success"))RazTint defines a fixed mapping from intent (success, danger, warning, …) to color and icon once, and every call site reuses that same mapping instead of picking its own.
A simulated production log stream 9 secrets detected, 9 secrets redacted, 0 leaked to the terminal.
- When to Use RazTint
- Installation
- Quick Start
- How It Compares
- Features
- Logging Integration Example
- Documentation
- Known Limitations
- Contributing
- License
Reach for it if your CLI prints more than a couple of message types and you want them to look the same across modules, or you need output that renders correctly in CI, on Windows, and on terminals without a Nerd Font.
For a single colored print() in a one-off script, plain ANSI codes or termcolor are simpler and enough.
Requires Python 3.10+.
pip install raztintFrom source:
git clone https://github.com/razbuild/raztint.git
cd raztint
uv syncfrom raztint import ok, paint
print(f"{ok()} File saved.")
print(paint("Connection failed.", color="red", icon="err"))
# intent sets color + icon together from one semantic name
print(paint("Deployment complete.", intent="success"))
# redact masks secrets before the string is printed
print(paint("password=1234", intent="debug", redact=True)) # password=****Redaction on its own, without formatting:
from raztint import redact
print(redact("password=supersecret api_key=ghp_abc123"))
# password=**** api_key=****More examples in Getting Started.
| Capability | colorama / termcolor | rich | RazTint |
|---|---|---|---|
| ANSI color support | ✅ | ✅ | ✅ |
| Terminal UI components | ❌ | ✅ | ❌ |
| Semantic logging intents | ❌ | ❌ | ✅ |
| Automatic icon fallback | ❌ | ✅ | |
| Secret masking | ❌ | ❌ | ✅ |
| Extra dependencies | None | Several | None |
RazTint isn't a rich replacement for dashboards or tables, it solves the narrower problem of making ok/err/warn/info messages consistent and safe by default.
- Intents: presets (
success,danger,warning,debug, …) that separate meaning from styling paint(): one call for color, background, styles, and icons- Status icons:
ok(),err(),warn(),info(), each with the three-tier fallback - Redaction: pattern-based masking (
key=valuepairs likepassword=,api_key=,token=) applied as part of the formatting call, not a separate logging step; patterns are configurable, see Security & Redaction - Environment detection: Nerd Font → Unicode → ASCII, cached; configurable via
NO_COLOR,RAZTINT_FORCE_COLOR - Typed:
py.typed, full public API type hints - Low-level escape hatch: raw 16-color, 256-color, and 24-bit True Color support, plus bold/dim/italic/underline/strikethrough, for when intents aren't enough
RazTint only returns a formatted string, it doesn't hook into logging or replace a handler. Pass that string to print(), a logger, or anything else that accepts a string.
import logging
from logging import Logger, getLogger
from raztint import paint
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
logger: Logger = getLogger(__name__)
logger.info(paint("Database migration completed.", intent="success", icon=None))
logger.warning(paint("Disk usage above 90%.", intent="warning", icon=None, styles="dim"))
logger.error(
paint("Authentication failed for token=abc123", intent="danger", redact=True, icon=None)
)| Guide | Description |
|---|---|
| Getting Started | Functional usage, paint(), and the tint instance |
| API Reference | Colors, styles, icons, and RazTint class methods |
| Intents | Semantic presets for common CLI messages |
| Security & Redaction | Masking tokens, credentials, and custom rules |
| Icons & Detection | Icon modes and environment/font/color detection logic |
| Configuration | Environment variables and runtime toggles |
| Development | Local setup, tests, and linting |
| Tutorial | Philosophy, detection walk-through, and best practices |
| Script | Description |
|---|---|
examples/basic_usage.py |
Colors, styles, icons, intents, and redaction in one script |
examples/paint_demo.py |
Every color, style, and icon mode |
examples/real_world_cli.py |
Simulated file-processor CLI |
- Python 3.10+ only.
- Font detection relies on OS tools (
fc-liston Linux,system_profileron macOS, PowerShell on Windows). SetRAZTINT_SKIP_SYSTEM_FONT_SCAN=1in sandboxed environments. - When
NO_COLORis set, all color output is suppressed regardless of other settings.
PRs and issues are welcome. Open an issue first to discuss before starting work on a feature. See CONTRIBUTING.md for setup and guidelines.
