Skip to content

mpfaffenberger/termflow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

33 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

termflow 🌊

A streaming markdown renderer for modern terminals

PyPI version Python versions License: MIT Build status

Perfect for rendering LLM output in real-time.


✨ Features

  • πŸ“‘ Streaming Rendering - Render markdown as it arrives, line by line
  • 🎨 Syntax Highlighting - Beautiful code blocks powered by Pygments
  • πŸ“Š Tables - Full support for GitHub-flavored markdown tables
  • πŸ“ Lists - Ordered, unordered, and nested lists with smart indentation
  • πŸ’» Code Blocks - Fenced code blocks with language detection and clipboard support
  • πŸ’­ Think Blocks - Special rendering for <think> tags (great for LLM chain-of-thought)
  • πŸ”— Hyperlinks - OSC 8 clickable links in supported terminals
  • πŸ“‹ Clipboard - OSC 52 clipboard integration for code blocks
  • πŸŽ›οΈ Configurable - Customize colors, styles, and features via TOML config
  • ⚑ Fast - Lightweight and performant, minimal dependencies

πŸš€ Quick Installation

Using uvx (recommended)

uvx termflow

Using pip

pip install termflow-md

From source

git clone https://github.com/your-username/termflow.git
cd termflow
pip install -e ".[dev]"

πŸ“– Usage

Command Line

# Render a file
tf README.md

# Pipe markdown content
echo "# Hello World" | tf

# Pipe from LLM output
curl -s https://api.example.com/chat | tf

# Set terminal width
tf -w 100 document.md

# Use a color preset
tf --style dracula README.md

# Use a syntax highlighting theme
tf --syntax-style nord file.md

# Disable clipboard integration
tf --no-clipboard document.md

# List available syntax styles
tf --list-syntax-styles

CLI Options

usage: tf [-h] [-w N] [-c PATH] [--style {default,dracula,nord,gruvbox}]
          [--syntax-style NAME] [--list-syntax-styles] [--no-clipboard]
          [--no-hyperlinks] [--no-pretty] [-V]
          [file]

options:
  -h, --help            show this help message and exit
  -w, --width N         Terminal width (default: auto-detect)
  -c, --config PATH     Path to config file
  --style PRESET        Color style preset (default, dracula, nord, gruvbox)
  --syntax-style NAME   Pygments syntax highlighting style
  --list-syntax-styles  List available syntax highlighting styles
  --no-clipboard        Disable OSC 52 clipboard for code blocks
  --no-hyperlinks       Disable OSC 8 hyperlinks
  --no-pretty           Disable pretty code block borders
  -V, --version         show program's version number and exit

Programmatic Usage

from termflow import Parser, Renderer, render_markdown

# Quick rendering to stdout
render_markdown("# Hello World!")

# Render to a file or buffer
from io import StringIO

output = StringIO()
render_markdown("# Hello\n\nThis is **bold** text.", output=output)
print(output.getvalue())

Streaming Mode

For real-time rendering of streaming content (e.g., LLM responses):

from termflow import Parser, Renderer
import sys

# Create parser and renderer
parser = Parser()
renderer = Renderer(output=sys.stdout, width=80)

# Process markdown line by line as it streams in
for line in markdown_stream:
    events = parser.parse_line(line)
    renderer.render_all(events)

# Finalize to close any open blocks
renderer.render_all(parser.finalize())

Custom Styling

from termflow import Renderer, RenderStyle, RenderFeatures
from io import StringIO

# Use a preset style
style = RenderStyle.dracula()  # or .nord(), .gruvbox()

# Or create a custom style
style = RenderStyle(
    bright="#87ceeb",   # Main accent color
    head="#98fb98",     # Heading color
    symbol="#dda0dd",   # Bullets, borders
    link="#87cefa",     # Link color
)

# Configure features
features = RenderFeatures(
    clipboard=True,     # OSC 52 clipboard support
    hyperlinks=True,    # OSC 8 clickable links
    pretty_pad=True,    # Pretty code block borders
)

# Create renderer with custom config
output = StringIO()
renderer = Renderer(
    output=output,
    width=100,
    style=style,
    features=features,
)

πŸ”§ Configuration

Create a config file at ~/.config/termflow/config.toml:

# Terminal width (null = auto-detect)
width = null
max_width = 120

# Pygments syntax highlighting style
syntax_style = "monokai"

# Color scheme
[style]
bright = "#87ceeb"    # Main accent color
head = "#98fb98"      # Heading color  
symbol = "#dda0dd"    # Bullets, table borders, code block borders
grey = "#808080"      # Muted text
dark = "#404040"      # Dark accents
mid = "#a0a0a0"       # Medium text
light = "#d0d0d0"     # Light accents
link = "#87cefa"      # Hyperlink color
error = "#ff6b6b"     # Error messages

# Feature toggles
[features]
clipboard = true      # OSC 52 clipboard for code blocks
hyperlinks = true     # OSC 8 clickable links
pretty_pad = true     # Pretty unicode borders on code blocks

You can also set the config path via environment variable:

export TERMFLOW_CONFIG=/path/to/config.toml

🎨 Style Presets

termflow includes several built-in color presets:

Preset Description
default Soft pastel colors
dracula Purple-tinted dark theme
nord Arctic, bluish color palette
gruvbox Retro, earthy colors

Use them via CLI:

tf --style dracula README.md

Or programmatically:

from termflow import RenderStyle

style = RenderStyle.dracula()
style = RenderStyle.nord()
style = RenderStyle.gruvbox()

πŸ’­ Think Block Support

termflow has special support for <think> blocks, commonly used in LLM chain-of-thought prompting:

<think>
Let me reason through this step by step...
1. First, I'll analyze the problem
2. Then, I'll formulate a solution
</think>

Here's my answer based on my reasoning above.

Think blocks are rendered with a distinct style to visually separate the model's reasoning from its final response.

πŸ¦€ Origin

termflow is a Python port of streamdown-rs, a high-performance streaming markdown renderer written in Rust. This project brings the same streaming rendering capabilities to the Python ecosystem with a clean, Pythonic API.

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

# Clone and install for development
git clone https://github.com/your-username/termflow.git
cd termflow
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run linter
ruff check .
ruff format .

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


Made with ❀️ for the terminal

About

Streaming markdown renderer for Python CLIs

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages