A streaming markdown renderer for modern terminals
Project description
termflow 🌊
A streaming markdown renderer for modern terminals
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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file termflow_md-0.1.8.tar.gz.
File metadata
- Download URL: termflow_md-0.1.8.tar.gz
- Upload date:
- Size: 115.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12a4c1665a8cd6fb6755e002b95085f7c60e3cd15783167b3c4638c45dfaf161
|
|
| MD5 |
4f288a2da1e8d2adce699c8b7213a49b
|
|
| BLAKE2b-256 |
baf197836d654623846b9ff452ef0cf75742f27bcaf5a0b893320e6876455c12
|
File details
Details for the file termflow_md-0.1.8-py3-none-any.whl.
File metadata
- Download URL: termflow_md-0.1.8-py3-none-any.whl
- Upload date:
- Size: 57.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b1c8b324b8b15bb919db410636b009d08ff8f3fbf9b365852278c36a760bd08
|
|
| MD5 |
71c3e692e98d872cc40ed07f455717c0
|
|
| BLAKE2b-256 |
8346e0dcf80b4b69a6fcd06c747e82b343643c0d240dd762f1218dc503f8d73b
|