madcatter🎩
Quick Start
# Mac:
# # Required for quick install.
# brew install uv
# Ubuntu/Debian:
# # Required for quick install.
# sudo apt-get install -y curl
# curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install madcatter
mdcat README.md
# As a library dependency: uv add madcatter
# Alternatively: python -m pip install madcatter
madcatter is a Rich-based Markdown renderer for the
terminal. It exists because cat-ing a Markdown file dumps raw #/**/``` noise, and most
"pretty cat" tools stop at syntax highlighting: madcatter also expands :shortcode: emoji,
converts LaTeX math to Unicode, extracts a table of contents or a single section, validates links,
diffs two documents, and can tail a growing file the way tail -F tails a log. The package is
called madcatter; it installs a CLI called mdcat.
If you like reading Markdown in the terminal and want it actually rendered — emoji, math, tables, syntax highlighting — instead of dumped raw.
The same file (docs/assets/sample.md), dumped raw with cat (left)
and rendered by mdcat (right): an emoji shortcode, $...$ math, a highlighted code block, and
a table.
Example
mdcat README.md # render a file
mdcat - # render stdin
echo '# hi :wave:' | mdcat - # emoji shortcodes are expanded
echo '$e^{i\pi}+1=0$' | mdcat # best effort LaTeX: eⁱ⁽π⁾+1=0
mdcat --toc README.md # render just the table of contents
mdcat -c foo.md | less -R # ANSI colored pipes.
Features
- Left-justified headings (Rich's default
Markdowncenters them;madcatterdoesn't). :shortcode:emoji expansion, skipped inside fenced/indented code.- LaTeX-to-Unicode math for
$...$and$$...$$, also skipped inside code. - Syntax-highlighted fenced code blocks via Pygments themes, plus a code-only extraction mode.
- Table-of-contents rendering and single-section extraction by heading name.
- Link extraction and live link validation (HTTP HEAD checks).
- Unified diff rendering between two Markdown files.
--watch(re-render on change) and--follow/-f/-F(tail -Fsemantics: emit only new lines, survive atomic rewrites).- ASCII-only, HTML, and ANSI export.
- YAML frontmatter stripping.
Usage cookbook
All examples below use real mdcat flags; run mdcat --help for the complete list.
Basic render
mdcat README.md # render a file
mdcat - # render stdin
mdcat a.md b.md --separator # render several files, with a rule between them
Style profiles (--style, one of dark, light, dracula, solarized)
mdcat --style dracula doc.md
Table of contents
mdcat --toc README.md
Single section by heading name
mdcat --section Install README.md
Links: list or validate
mdcat --links README.md # list every URL found in the document
mdcat --check-links README.md # also issue a live HTTP HEAD request to each http(s) link
Code blocks only, optionally filtered by language (--code-lang implies --code-only)
mdcat --code-only README.md
mdcat --code-lang python README.md
Diff two Markdown files
mdcat old.md --diff new.md
Watch vs. follow — both require a single real file path (stdin - is rejected), and the two
are mutually exclusive with each other:
mdcat --watch notes.md # re-render the whole file whenever its mtime changes
mdcat -f log.md # tail -F semantics: emit only new lines, re-anchor across rewrites
mdcat -n 20 -f log.md # on first attach/reopen, show only the last 20 lines
Export
mdcat --export-html out.html README.md
mdcat --export-ansi out.and README.md
ASCII-only output (no ANSI codes, no Unicode — box-drawing, bullets, arrows, etc. are transliterated)
mdcat --ascii README.md
Strip YAML frontmatter before rendering — useful for notes that start with a --- metadata
block
mdcat --no-frontmatter note-with-frontmatter.md
Library
The preprocessing helpers are importable directly:
from madcatter.markdown import process_math_blocks, strip_frontmatter
from madcatter.latex import latex2unicode
from madcatter.emoji import resolve
process_math_blocks(
"area is $\\pi r^2$"
) # -> unicode-rendered math, code blocks left intact
strip_frontmatter(["---", "title: x", "---", "body"]) # -> ["body"]
latex2unicode("x^2 + y_i") # -> "x² + yᵢ"
resolve("wave") # -> "👋" (or None if unknown)
Development
Requires Python 3.12 and uv.
uv sync --all-groups
uv run pytest
Tests are organized into tiers via pytest markers (see pyproject.toml). The default run
(uv run pytest) excludes the slower/networked tiers — ci_smoke, cuda, integration,
performance, cluster, and slow — so opt in explicitly when needed, e.g.:
uv run pytest -m ci_smoke # package/CLI smoke tests
uv run pytest -m integration # tests needing networking or external CLIs
Before opening a pull request, run the same checks CI runs in package-validation.yml:
uv run ruff check --no-fix --no-cache .
uv run ruff format --check --no-cache .
uv run codespell .
uv run ty check
uv run basedpyright madcatter
uv run pytest
uv build
See also
Sibling libraries in the rekursiv-ai family:
- sagent — The self-mutating multi-provider coding-agent CLI and typed Python library.
- trackinizer — Centralized agent database for tracking inquiries, work, and the evidence behind conclusions.
- wesearch — Web search, resilient page fetch, and scholarly-paper lookup without a browser stack.
- priml — Composable PyTorch building blocks: models, optimizers, losses, and a step-based training loop.
- configgle — Hierarchical experiment configuration in typed pure-Python dataclasses instead of YAML.
License
Apache License 2.0
Release files for madcatter 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| madcatter-0.1.1.tar.gz | 313.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| madcatter-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 388.2 kB
Release files / madcatter-0.1.1.tar.gz
| Download URL | madcatter-0.1.1.tar.gz |
|---|---|
| Size | 313.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
93c240590b4d05f813a35f3e8f8ac3033495d428fc47f18e3d8607de97505ed7
|
|
BLAKE2b-256 checksum How to use checksums |
fce368dff3af77c687513d1a67e08648ae096ffc3be9e8d71f57e9629ca84e12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.
Transparency logRelease files / madcatter-0.1.1-py3-none-any.whl
| Download URL | madcatter-0.1.1-py3-none-any.whl |
|---|---|
| Size | 74.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1dd4ef1b11eb39e6a2ead3f76d850b53df30b61f463dc7efb4df294d34c4fda
|
|
BLAKE2b-256 checksum How to use checksums |
593449a251070bddacfc3993a5d514f4cda79caf6030c417aa7c2272f024714b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.
Transparency log