LESSOPEN filter for Markdown rendering and syntax highlighting with less
Project description
richless
A LESSOPEN filter for automatically rendering Markdown files and syntax highlighting source code when using less. View your Markdown documents with beautiful formatting and programming language files with syntax highlighting directly in the terminal, without changing how you use less.
Quick Start
# 1. Install richless via Homebrew (macOS or Linux)
brew install DavidJBianco/tools/richless
# 2. Add shell integration to your ~/.bashrc or ~/.zshrc
# (brew will print the exact path after install)
source $(brew --prefix)/share/richless/richless-init.sh
# 3. Reload your shell
source ~/.bashrc # or ~/.zshrc
# 4. Try it!
less README.md # View rendered Markdown
less richless.py # View syntax-highlighted Python
Features
- Seamless Integration: Works transparently with
lessvia LESSOPEN - Automatic Markdown Rendering: Recognizes
.mdand.markdownfiles automatically and renders them beautifully - Rich Terminal Formatting: Beautiful rendering with headers, lists, code blocks, tables, and more
- Data Format Highlighting: Syntax highlighting for JSON, JSONL, YAML, and XML files with automatic detection
- Code Highlighting: Syntax highlighting for 500+ programming languages (Python, JavaScript, Go, Rust, and more)
- Works with Wildcards:
less *.mdorless *.pyjust works - Correct Filenames: Shows actual filenames in less, not temporary files
- Powered by rich and Pygments: Leverages rich for beautiful terminal output and Pygments for syntax highlighting
Installation
Homebrew (Preferred — macOS and Linux)
brew install DavidJBianco/tools/richless
After installation, add the shell integration to your ~/.bashrc or ~/.zshrc:
source $(brew --prefix)/share/richless/richless-init.sh
Then reload your shell:
source ~/.bashrc # or source ~/.zshrc
pip / uv (Alternative)
If you prefer not to use Homebrew, you can install from PyPI:
# With uv
uv tool install richless
# Or with pip
pip install richless
Then copy the shell integration script and source it:
# Download the init script
curl -o ~/.richless-init.sh https://raw.githubusercontent.com/DavidJBianco/richless/main/richless-init.sh
# Add to your ~/.bashrc or ~/.zshrc
echo 'source ~/.richless-init.sh' >> ~/.bashrc # or ~/.zshrc
# Reload your shell
source ~/.bashrc # or source ~/.zshrc
Note: If you see a warning about PATH after uv tool install, run:
export PATH="$HOME/.local/bin:$PATH"
# Add this line to your ~/.bashrc or ~/.zshrc to make it permanent
Shell Integration Options
The shell integration script (sourced above) provides the full-featured transparent wrapper around less. This is the recommended setup and what Quick Start uses.
What you get:
- ✅ Automatic Markdown rendering when you run
less file.md - ✅ Syntax highlighting for programming language source files (Python, JavaScript, etc.)
- ✅ Works with wildcards:
less *.mdorless *.py - ✅ Piped input works:
cat file.md | lessrenders markdown - ✅ Force markdown flag:
less --md document.txtforces rendering - ✅ Auto-detection: Intelligently detects markdown in piped content
- ✅ Backward compatible: Acts like normal
lesswhen not needed
Note: The shell integration file is compatible with sh, bash, and zsh.
Minimal Setup (without shell wrapper)
If you prefer not to use the shell wrapper, you can manually set two environment variables instead. Add these lines to your ~/.bashrc, ~/.zshrc, or ~/.profile:
export LESSOPEN="|richless %s"
export LESS="-R"
This gives you automatic Markdown rendering and syntax highlighting for files, but piped input (cat file.md | less) and the --md flag won't work.
Usage
Once configured, just use less normally! Markdown files will be automatically rendered, and source code files will be syntax highlighted.
Basic Usage (Both Options)
# View a Markdown file (automatically rendered)
less README.md
# View multiple Markdown files
less *.md
# View with wildcards
less docs/**/*.md
# Source code files get syntax highlighting automatically
less script.py # Python
less app.js # JavaScript
less main.go # Go
less config.json # JSON
less styles.css # CSS
# All standard less options work
less -N README.md # Show line numbers
less -i script.py # Case-insensitive search
less +50 README.md # Start at line 50
Additional Features (Option 2 / Quick Start)
If you followed the Quick Start or are using Option 2, you also get these features:
# Force Markdown rendering on non-.md files
less --md document.txt
less -m notes.txt
# Piped input works!
cat file.md | less
echo "# Hello\n**World**" | less --md
# Pipe from other commands
curl https://example.com/README.md | less --md
grep -A 50 "## Section" doc.md | less
# Auto-detection: if piped content looks like markdown, it renders automatically
cat file.md | less # Detects markdown syntax and renders
Direct richless Usage
You can also call richless directly if needed:
# Render and pipe to less
richless document.md | less -R
# Force markdown rendering
richless --md document.txt | less -R
# Read from stdin
cat file.md | richless --md - | less -R
echo "# Test" | richless --md - | less -R
Standard less Commands
All standard less commands work normally inside the pager:
/pattern- Search forward?pattern- Search backwardn/N- Next/previous matchg/G- Go to start/endq- Quith- Help
How It Works
Basic Mode (Option 1):
- When you run
less file.md, theLESSOPENenvironment variable tells less to runrichless file.mdfirst richlessdetects the.mdextension and uses therichlibrary to render the Markdownrichrenders the Markdown to beautifully formatted ANSI text with proper table support- The formatted output is piped to
lessfor viewing - For programming language source files (
.py,.js,.java, etc.),richautomatically provides syntax highlighting using Pygments
Transparent Wrapper (Option 2):
- The shell function intercepts calls to
lessbefore they execute - For regular files, it passes through to the basic LESSOPEN mechanism
- For piped input or when
--mdis specified, it saves the content to a temp file and renders it - Auto-detection checks piped content for markdown patterns (headers, lists, links, etc.)
Troubleshooting
"richless: command not found"
Make sure ~/.local/bin is in your PATH:
export PATH="$HOME/.local/bin:$PATH"
# Add this to your ~/.bashrc or ~/.zshrc
Piped input doesn't work
If you're using Option 1 (Basic LESSOPEN), piped input won't work. Either:
- Switch to Option 2 / Quick Start for piped input support
- Or use:
cat file.md | richless --md - | less -R
Colors don't show up
If you're using Option 1 (manual setup), make sure you have the -R flag set:
export LESS="-R"
The init script (Option 2 / Quick Start) sets this automatically.
Shell function not loading
Make sure you're sourcing the init script, not executing it:
source ~/.richless-init.sh # Correct
./richless-init.sh # Wrong - this won't define the function in your shell
After sourcing, "less file.md" shows an error
Make sure you've reinstalled richless after any updates:
uv tool uninstall richless
uv tool install .
source ~/.richless-init.sh # Re-source to pick up changes
Updating
# Homebrew
brew upgrade richless
# uv
uv tool upgrade richless
Uninstalling
# Homebrew
brew uninstall richless
# uv
uv tool uninstall richless
rm ~/.richless-init.sh
After uninstalling, remove the source ...richless-init.sh line from your ~/.bashrc or ~/.zshrc.
Development
# Clone the repository
git clone https://github.com/DavidJBianco/richless.git
cd richless
# Install dependencies
uv sync
# Install in development mode
uv tool install --editable .
# Make changes, then reinstall
uv tool install --editable . --force
# Test it
less README.md
# Run tests
uv run pytest tests/test_richless.py -v
Dependencies
- rich - Python library for rich terminal output, Markdown rendering, and syntax highlighting
- Pygments - Syntax highlighting library
- Python 3.12+
Comparison to Alternatives
vs. glow / mdcat / bat:
- richless integrates directly with
less, so you use your familiar pager commands - Works transparently - no need to remember a different command
- Supports all standard
lessfeatures (search, navigation, etc.)
vs. vimpager:
- Lighter weight, doesn't require Vim
- Uses rich library's excellent Markdown rendering with full table support
- Simple LESSOPEN integration
License
See LICENSE file for details.
Project details
Release history Release notifications | RSS feed
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 richless-0.2.3.tar.gz.
File metadata
- Download URL: richless-0.2.3.tar.gz
- Upload date:
- Size: 10.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d3640131b213331bcc21838ad0367dd2ecd243b7f1ab51a1c1d4a315310602b
|
|
| MD5 |
fc75a5fac9422c891c5848b5e955d924
|
|
| BLAKE2b-256 |
a80fa48269e327619d9334316322a170d0b9b2fafc81b1e8c91225805d686509
|
Provenance
The following attestation bundles were made for richless-0.2.3.tar.gz:
Publisher:
publish.yml on DavidJBianco/richless
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
richless-0.2.3.tar.gz -
Subject digest:
9d3640131b213331bcc21838ad0367dd2ecd243b7f1ab51a1c1d4a315310602b - Sigstore transparency entry: 1136794925
- Sigstore integration time:
-
Permalink:
DavidJBianco/richless@a1d765a1d98ffe092c16fbf14f495a6a28d9f2a2 -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/DavidJBianco
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a1d765a1d98ffe092c16fbf14f495a6a28d9f2a2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file richless-0.2.3-py3-none-any.whl.
File metadata
- Download URL: richless-0.2.3-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0560b7ec80d3de1ba731fb869a8e601efe4c8e0f540d28045e740ba65433d68e
|
|
| MD5 |
58189d41067482a8475693f35d9d322e
|
|
| BLAKE2b-256 |
79e9aec3569483d9dc1887046dc1d3b0fd8a23cbdc9eaa65d8f61545226d55a8
|
Provenance
The following attestation bundles were made for richless-0.2.3-py3-none-any.whl:
Publisher:
publish.yml on DavidJBianco/richless
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
richless-0.2.3-py3-none-any.whl -
Subject digest:
0560b7ec80d3de1ba731fb869a8e601efe4c8e0f540d28045e740ba65433d68e - Sigstore transparency entry: 1136795026
- Sigstore integration time:
-
Permalink:
DavidJBianco/richless@a1d765a1d98ffe092c16fbf14f495a6a28d9f2a2 -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/DavidJBianco
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a1d765a1d98ffe092c16fbf14f495a6a28d9f2a2 -
Trigger Event:
push
-
Statement type: