Beautiful Terminal Output with Rich

· 4 min read · Updated March 14, 2026 · beginner
python rich cli libraries

Rich is a Python library that lets you build rich terminal output with colors, styles, tables, progress bars, syntax highlighting, and markdown rendering. It works on Linux, macOS, and Windows, and automatically handles terminal capabilities.

Why Rich?

Standard print statements are plain and utilitarian. Rich makes your CLI applications look professional with minimal effort:

from rich.console import Console

console = Console()
console.print("Hello, [bold red]World![/bold red]")

That one line produces bold red text in any terminal that supports colors.

Installation

Install Rich with pip:

pip install rich

That’s it. No configuration needed.

Getting Started

The Console object is your main entry point:

from rich.console import Console

console = Console()

# Basic colored text
console.print("[bold blue]This is bold blue[/bold blue]")
console.print("[italic green]This is italic green[/italic green]")
console.print("[underline yellow]This is underlined yellow[/underline yellow]")

# Combine styles
console.print("[bold cyan]Bold cyan[/bold cyan] with [inverse]inverse[/inverse]")

Rich uses a simple markup syntax similar to BBCode. Wrap text in square brackets with style names.

Available Colors

Rich supports 8-bit, true color (24-bit), and terminal default colors:

# Standard colors
console.print("[red]Red[/red]")
console.print("[blue]Blue[/blue]")
console.print("[green]Green[/green]")

# Bright variants
console.print("[bright_red]Bright Red[/bright_red]")
console.print("[bright_cyan]Bright Cyan[/bright_cyan]")

# 256-color (0-255)
console.print("[color(202)]Copper orange[/color(202)]")

# True color (RGB)
console.print("[rgb(255,128,0)]Orange[/rgb(255,128,0)]")

Text Styles

Beyond colors, Rich provides numerous text styles:

console.print("[bold]Bold text[/bold]")
console.print("[dim]Dim text[/dim]")
console.print("[italic]Italic text[/italic]")
console.print("[underline]Underlined text[/underline]")
console.print("[strike]Strikethrough[/strike]")
console.print("[blink]Blinking text[/blink]")
console.print("[reverse]Reversed colors[/reverse]")
console.print("[conceal]Hidden text[/conceal]")

Not all terminals support all styles—Rich gracefully degrades when they don’t.

Tables

Rich can render beautiful ASCII tables:

from rich.console import Console
from rich.table import Table

console = Console()

table = Table(title="Programming Languages")

table.add_column("Language", style="cyan", no_wrap=True)
table.add_column("Creator", style="magenta")
table.add_column("Year", justify="right", style="green")

table.add_row("Python", "Guido van Rossum", "1991")
table.add_row("JavaScript", "Brendan Eich", "1995")
table.add_row("Rust", "Graydon Hoare", "2010")
table.add_row("Go", "Robert Griesemer", "2009")

console.print(table)

The output looks like a proper terminal table with borders and aligned columns.

Table Styles

Customize table appearance:

table = Table(show_header=True, header_style="bold magenta")
table.add_column("Name", style="cyan")
table.add_column("Status", justify="center")

# Different row styles
table.add_row("Task 1", "[green]✓ Complete[/green]")
table.add_row("Task 2", "[yellow]⟳ In Progress[/yellow]")
table.add_row("Task 3", "[red]✗ Failed[/red]")

console.print(table)

You can also use Table.row_styles for alternating row colors.

Progress Bars

Rich includes built-in progress tracking:

from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn

with Progress(
    TextColumn("[progress.description]{task.description}"),
    BarColumn(),
    TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
) as progress:
    
    task = progress.add_task("[cyan]Processing...", total=100)
    
    for i in range(100):
        progress.update(task, advance=1)

For multiple concurrent tasks:

from rich.progress import Progress

with Progress() as progress:
    task1 = progress.add_task("[red]Downloading...", total=100)
    task2 = progress.add_task("[blue]Installing...", total=100)
    
    for i in range(100):
        progress.update(task1, advance=1)
        
    for i in range(100):
        progress.update(task2, advance=0.5)
        progress.update(task2, advance=0.5)

Track Function

For simple progress tracking, use track:

from rich.progress import track

for i in track(range(100), description="Processing..."):
    do_work()

Logging

Rich can replace or augment Python’s logging:

from rich.logging import RichHandler
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(message)s",
    handlers=[RichHandler(rich_tracebacks=True)]
)

logger = logging.getLogger(__name__)
logger.info("This is an info message")
logger.warning("This is a warning")
logger.error("This is an error")

The RichHandler adds color-coded log levels and optionally includes tracebacks.

Syntax Highlighting

Rich includes a syntax highlighter using the same themes as VS Code:

from rich.syntax import Syntax
from rich.console import Console

code = """
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

for i in range(10):
    print(f"F({i}) = {fibonacci(i)}")
"""

syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
console.print(syntax)

Available themes include monokai, github-dark, dracula, and many more.

Markdown

Render Markdown directly in the terminal:

from rich.markdown import Markdown
from rich.console import Console

console = Console()

markdown = """
# Heading 1

This is **bold** and *italic* text.

## Code Blocks

````python
print("Hello")

This is a quote

  • Item 1
  • Item 2 """

console.print(Markdown(markdown))


## Panels

Group content in boxes:

```python
from rich.panel import Panel
from rich.console import Console

console = Console()

console.print(Panel("[bold cyan]Welcome![/bold cyan]", expand=False))
console.print(Panel("This is a simple panel"))
console.print(Panel.fit("[green]Fit to content[/green]"))

console.print(Panel("ASCII", border_style="ascii"))
console.print(Panel("Double", border_style="double"))
console.print(Panel("Rounded", border_style="rounded"))

Trees

Display hierarchical data:

from rich.tree import Tree
from rich.console import Console

console = Console()

tree = Tree("📁 project/")
tree.add("📄 README.md")
tree.add("📁 src/")
tree.add("📁 tests/")
subtree = tree.add("📁 lib/")
subtree.add("📄 utils.py")

console.print(tree)

Status Indicators

Show temporary status messages:

from rich.console import Console

console = Console()
with console.status("[bold cyan]Loading data...") as status:
    do_time_consuming_work()
    status.update("[bold green]Done!")

This displays a spinner while your code runs.

Live Updates

Use Live for real-time terminal updates:

from rich.live import Live
from rich.console import Console

console = Console()

with Live("Initializing...", console=console) as live:
    for i in range(10):
        live.update(f"Step {i+1}/10")
        # Do work here

Combining Everything

Here’s a more complete example combining several features:

from rich.console import Console
from rich.table import Table
from rich.panel import Panel

console = Console()

# Welcome panel
console.print(Panel.fit(
    "[bold cyan]Welcome to MyApp v1.0[/bold cyan]",
    border_style="cyan"
))

# Status table
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Component", style="cyan")
table.add_column("Status", justify="center")
table.add_row("Database", "[green]● Connected[/green]")
table.add_row("Cache", "[green]● Active[/green]")
table.add_row("API", "[yellow]● Rate limited[/yellow]")

console.print(table)
console.print()
console.print("[bold]Server running at[/bold] [link=http://localhost:8000]http://localhost:8000[/link]")

See Also