termcolor adds ANSI colors to Python terminal output with a minimal API. pip install termcolor. Basic: from termcolor import colored, cprint. colored("text", "red") → ANSI-colored string. cprint("text", "red") → prints directly. Colors: “red” “green” “yellow” “blue” “magenta” “cyan” “white” “light_red” “light_green” “light_yellow” “light_blue” “light_magenta” “light_cyan” “light_white”. Background: colored("text", on_color="on_red") — on_red on_green on_yellow on_blue on_magenta on_cyan on_white on_light_*. Attrs: colored("text", attrs=["bold"]). attrs=["bold","underline"]. “bold” “dark” “underline” “blink” “reverse” “concealed” “strike”. Combined: colored("error", "red", attrs=["bold"]). colored("bg", "white", "on_red", ["bold"]). cprint stderr: cprint("error", "red", file=sys.stderr). NO_COLOR: set env NO_COLOR=1 to disable (termcolor respects the standard). FORCE_COLOR=1 forces colors even when not TTY. f-string: f"{colored('OK', 'green')}: {msg}". Print list: [cprint(item, "cyan") for item in items]. Logging: colored(record.getMessage(), color_map[record.levelno]). All COLORS: termcolor.COLORS dict. All HIGHLIGHTS: termcolor.HIGHLIGHTS dict. Claude Code generates termcolor print helpers, colored log formatters, and styled CLI output functions.
CLAUDE.md for termcolor
## termcolor Stack
- Version: termcolor >= 2.4 | pip install termcolor
- Basic: colored("text", "green") | cprint("text", "red", attrs=["bold"])
- Colors: red green yellow blue magenta cyan white + light_* variants
- Background: on_color="on_red" | on_green on_yellow on_blue on_magenta on_cyan
- Attrs: attrs=["bold"] | ["bold","underline"] | ["reverse"] | ["strike"]
- CI: NO_COLOR=1 disables output | FORCE_COLOR=1 forces it
- stderr: cprint("error", "red", file=sys.stderr) for error messages
termcolor Styled Output Pipeline
# app/term_colors.py — termcolor styled output, logging formatter, and CLI helpers
from __future__ import annotations
import logging
import sys
from typing import Any
from termcolor import COLORS, HIGHLIGHTS, colored, cprint
# ─────────────────────────────────────────────────────────────────────────────
# 1. Semantic wrappers
# ─────────────────────────────────────────────────────────────────────────────
def success(msg: str) -> str:
"""Green bold — successful operations, passing tests."""
return colored(f"✓ {msg}", "green", attrs=["bold"])
def error(msg: str) -> str:
"""Red bold — errors, failures, exceptions."""
return colored(f"✗ {msg}", "red", attrs=["bold"])
def warning(msg: str) -> str:
"""Yellow — warnings, deprecations, soft failures."""
return colored(f"⚠ {msg}", "yellow")
def info(msg: str) -> str:
"""Cyan — informational messages, status updates."""
return colored(f"→ {msg}", "cyan")
def muted(msg: str) -> str:
"""Dark (dim) — secondary info, timestamps, metadata."""
return colored(msg, "white", attrs=["dark"])
def highlight(msg: str) -> str:
"""Bold white — headings, section titles."""
return colored(msg, "white", attrs=["bold"])
# ─────────────────────────────────────────────────────────────────────────────
# 2. Direct print helpers
# ─────────────────────────────────────────────────────────────────────────────
def print_success(msg: str) -> None:
cprint(f"✓ {msg}", "green", attrs=["bold"])
def print_error(msg: str) -> None:
cprint(f"✗ {msg}", "red", attrs=["bold"], file=sys.stderr)
def print_warning(msg: str) -> None:
cprint(f"⚠ {msg}", "yellow")
def print_info(msg: str) -> None:
cprint(f"→ {msg}", "cyan")
def print_header(title: str, width: int = 60) -> None:
bar = "─" * width
cprint(bar, "blue", attrs=["bold"])
cprint(f" {title}", "blue", attrs=["bold"])
cprint(bar, "blue", attrs=["bold"])
def print_kv(key: str, value: Any, key_width: int = 24) -> None:
"""Key in cyan, value in white."""
k = colored(f"{key:<{key_width}}", "cyan")
v = colored(str(value), "white")
print(f"{k}: {v}")
# ─────────────────────────────────────────────────────────────────────────────
# 3. Status table
# ─────────────────────────────────────────────────────────────────────────────
_STATUS_COLOR: dict[str, str] = {
"ok": "green",
"pass": "green",
"success": "green",
"error": "red",
"fail": "red",
"warn": "yellow",
"warning": "yellow",
"skip": "magenta",
"info": "cyan",
}
_STATUS_ATTRS: dict[str, list[str]] = {
"error": ["bold"],
"fail": ["bold"],
"ok": [],
}
def print_status_table(rows: list[dict], columns: list[str] | None = None) -> None:
"""Print rows, coloring each based on the 'status' column value."""
if not rows:
return
columns = columns or list(rows[0].keys())
col_w = 18
# Header
header = " ".join(colored(f"{c:<{col_w}}", "cyan", attrs=["bold"]) for c in columns)
print(header)
print(colored("─" * ((col_w + 2) * len(columns)), "blue"))
# Rows
for row in rows:
status = str(row.get("status", "")).lower()
color = _STATUS_COLOR.get(status, "white")
attrs = _STATUS_ATTRS.get(status, [])
cells = " ".join(
colored(f"{str(row.get(col, '')):18}", color, attrs=attrs)
for col in columns
)
print(cells)
# ─────────────────────────────────────────────────────────────────────────────
# 4. Test result reporter
# ─────────────────────────────────────────────────────────────────────────────
def print_test_result(
name: str,
passed: bool,
duration_ms: float | None = None,
error_msg: str | None = None,
) -> None:
"""
Print a single test result with pass/fail coloring.
Used in custom test runners or CI output scripts.
"""
tick = colored("PASS", "green", attrs=["bold"]) if passed else colored("FAIL", "red", attrs=["bold"])
dur = f" {colored(f'{duration_ms:.1f}ms', 'white', attrs=['dark'])}" if duration_ms else ""
print(f" {tick} {name}{dur}")
if error_msg:
for line in error_msg.splitlines():
print(f" {colored(line, 'red')}")
def print_test_summary(passed: int, failed: int, skipped: int = 0) -> None:
"""Print a test suite summary line with color-coded counts."""
parts = []
if passed:
parts.append(colored(f"{passed} passed", "green", attrs=["bold"]))
if failed:
parts.append(colored(f"{failed} failed", "red", attrs=["bold"]))
if skipped:
parts.append(colored(f"{skipped} skipped", "yellow"))
total = passed + failed + skipped
print(f"\n {', '.join(parts)} — {total} total")
# ─────────────────────────────────────────────────────────────────────────────
# 5. Colored logging formatter
# ─────────────────────────────────────────────────────────────────────────────
_LOG_COLORS: dict[int, str] = {
logging.DEBUG: "blue",
logging.INFO: "green",
logging.WARNING: "yellow",
logging.ERROR: "red",
logging.CRITICAL: "red",
}
_LOG_ATTRS: dict[int, list[str]] = {
logging.CRITICAL: ["bold"],
logging.ERROR: ["bold"],
logging.DEBUG: ["dark"],
}
class TermcolorFormatter(logging.Formatter):
"""
Apply termcolor to the level name portion of log records.
Attach to a StreamHandler to get colored console logs.
"""
def format(self, record: logging.LogRecord) -> str:
color = _LOG_COLORS.get(record.levelno, "white")
attrs = _LOG_ATTRS.get(record.levelno, [])
record.levelname = colored(f"{record.levelname:<8}", color, attrs=attrs)
return super().format(record)
def make_colored_logger(name: str = __name__, level: int = logging.DEBUG) -> logging.Logger:
logger = logging.getLogger(name)
logger.setLevel(level)
if not logger.handlers:
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(
TermcolorFormatter("%(asctime)s %(levelname)s %(name)s %(message)s")
)
logger.addHandler(handler)
return logger
# ─────────────────────────────────────────────────────────────────────────────
# 6. Argument parser with colored usage/error
# ─────────────────────────────────────────────────────────────────────────────
def color_diff(added: list[str], removed: list[str], context: list[str]) -> str:
"""
Simple colored diff output — added lines green, removed red, context white.
Useful for displaying configuration changes or migration previews.
"""
lines = []
for line in removed:
lines.append(colored(f"- {line}", "red"))
for line in added:
lines.append(colored(f"+ {line}", "green"))
for line in context:
lines.append(colored(f" {line}", "white", attrs=["dark"]))
return "\n".join(lines)
# ─────────────────────────────────────────────────────────────────────────────
# 7. All available termcolor colors/attributes
# ─────────────────────────────────────────────────────────────────────────────
def demo_palette() -> None:
"""Print all available foreground colors and attributes."""
print(colored("=== Foreground colors ===", "white", attrs=["bold"]))
for name in sorted(COLORS):
print(f" {colored(f'{name:20}', name)} {name}")
print(colored("\n=== Backgrounds ===", "white", attrs=["bold"]))
for name in sorted(HIGHLIGHTS):
key = name.replace("on_", "")
bg = name
try:
print(f" {colored(f'{bg:20}', 'black', bg)}", end=" ")
except Exception:
pass
print()
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print_header("termcolor Demo")
print("\n=== Semantic helpers ===")
print_success("Build completed in 2.3s")
print_error("ImportError: No module named 'numpy'")
print_warning("Config file not found — using defaults")
print_info("Listening on http://0.0.0.0:8000")
print("\n=== Key/Value ===")
print_kv("python", "3.12.1")
print_kv("environment", "production")
print_kv("workers", 4)
print("\n=== Status table ===")
services = [
{"name": "postgres", "status": "ok", "uptime": "99.9%"},
{"name": "redis", "status": "ok", "uptime": "100%"},
{"name": "celery", "status": "warn", "uptime": "97.2%"},
{"name": "s3", "status": "error", "uptime": "0%"},
]
print_status_table(services)
print("\n=== Test results ===")
print_test_result("test_login", True, 12.4)
print_test_result("test_signup", True, 8.1)
print_test_result("test_payment", False, 301.5, "AssertionError: expected 200 got 500")
print_test_result("test_profile", True, 5.2)
print_test_summary(3, 1)
print("\n=== Colored diff ===")
diff = color_diff(
added=["DATABASE_URL=postgresql://localhost/newdb", "WORKERS=4"],
removed=["DATABASE_URL=sqlite:///dev.db", "WORKERS=1"],
context=["DEBUG=false", "PORT=8000"],
)
print(diff)
print("\n=== Colored logging ===")
log = make_colored_logger("demo")
log.debug("Cache miss for key user:42")
log.info("Request GET /api/users 200 OK")
log.warning("Rate limit approaching: 950/1000 req/min")
log.error("Database connection pool exhausted")
For the colorama alternative — colorama’s primary value is Windows ANSI translation: colorama.init() patches stdout so that ANSI escape sequences work on Windows cmd.exe and PowerShell, which do not interpret them natively; if your tool only runs on Linux/macOS, colorama adds no functional benefit over termcolor, and termcolor’s colored(text, color, on_color, attrs) API is slightly simpler because it wraps text and resets in a single call without requiring an init() call. For the rich alternative — Rich’s [bold red]text[/] markup and console objects are the right choice for complex terminal UIs (tables, panels, trees, spinners, progress bars), while termcolor is the right choice when you need a thin, zero-config wrapper around ANSI codes for existing print() and logging calls — pip install termcolor and colored("ok", "green") is the minimal integration that adds color without restructuring your output code. The Claude Skills 360 bundle includes termcolor skill sets covering colored() with color/on_color/attrs, cprint() for direct printing, semantic success/error/warning/info helpers, print_kv for key-value display, print_status_table with status-based color mapping, print_test_result and print_test_summary for test runners, TermcolorFormatter for logging.Formatter subclass, make_colored_logger setup, color_diff for change visualization, demo_palette for COLORS/HIGHLIGHTS enumeration, and NO_COLOR/FORCE_COLOR environment variable behavior. Start with the free tier to try terminal color styling code generation.