mdflow is a true streaming Markdown-to-ANSI renderer for LLM output. It formats Markdown as it arrives, before the response is complete, without waiting for the full input or reparsing everything received so far.
your-llm-command | mdflowBuilt in C with a reworked MD4C parser, mdflow is a lightweight CLI and embeddable library.
Note
This is cjccjj/mdflow, a native C Markdown-to-terminal renderer. It is not
related to similarly named Markdown workflow or agent packages.
- Live output: see formatted Markdown while an LLM response is still arriving.
- Markdown support: CommonMark tested against 652 examples, plus documented GFM features.
- Fast and lightweight: 0.55 s and 2.2 MB peak RAM for the 10 MB benchmark input.
- Easy to embed: a native C CLI and libc-only library.
Compare mdflow with Streamdown, mdcat, and Glow on streaming, Markdown support, speed, memory, and binary size.
| mdflow | streamdown | mdcat | glow (glamour) | ||
|---|---|---|---|---|---|
| Capabilities | Streaming | ✅ | ✅ | ❌ | ❌ |
| Buffering | Single line | Single line | Whole doc | Whole doc | |
| CommonMark | ✅ Tested* | ❌ | ✅ Tested | ❌ | |
| GFM tables | ✅ | ✅ | |||
| Render time | 1 MB input | ||||
| 10 MB input | |||||
| 100 MB input | - | - | |||
| Peak RAM | 1 MB input | ||||
| 10 MB input | |||||
| 100 MB input | - | - | |||
| Binary | Language | C | Python | Rust | Go |
| Size | - |
1. See "CommonMark + GFM support, extensions, and limitations" for tested coverage and known differences.
2. streamdown and glow did not finish the 100 MB test within 100 seconds.
3. Input consisted of mixed Markdown. Performance varies by content.
4. Benchmarked on GitHub Actions (Ubuntu 24.04, AMD EPYC 7763, 4 vCPUs)
5. mdflow v0.1.2, streamdown 0.36.6, glow v3.0.0, and mdcat v2.7.1.
For Linux and macOS, installs to ~/.local/bin:
curl -fsSL https://raw.githubusercontent.com/cjccjj/mdflow/main/install.sh | shOr download a binary from Releases (Linux x86_64/arm64, macOS arm64).
Pipe Markdown into mdflow - live LLM output, live logs, files, or anything that streams:
my-ai-tool "show me a markdown demo" | mdflow
cat README.md | mdflow
curl -sL https://raw.githubusercontent.com/cjccjj/mdflow/main/assets/demo.md | mdflowTo render a file:
mdflow < README.md
mdflow README.mdTo quickly add Markdown rendering to your CLI tool, add this Bash function to
~/.bashrc:
my-ai-tool() {
command my-ai-tool "$@" | mdflow
local s=("${PIPESTATUS[@]}")
return "$((s[0] ? s[0] : s[1]))"
}Reload the configuration, and use the tool normally:
source ~/.bashrc
my-ai-tool "explain this code"For paging long documents, pipe to more or less -R.
mdflow < README.md | more-h,--help: Show usage.--typewriter-off: Typewriter pacing activates only when a live, slow stream is detected. This forces it off.--osc8-off: OSC 8 hyperlinks are on by default. This disables them for terminals such as Apple Terminal.--theme-term-256: Use the TERM_256 rendering theme, which is more reliable across terminals. If omitted, the DEFAULT rendering theme is used.--plain: Select plain output mode, disabling renderer-generated SGR and OSC 8 sequences.
mdflow starts rendering while input is still arriving. It does not wait for EOF, keep the whole document in memory, or repeatedly reprocess everything received so far. That makes it a natural fit for live LLM output and other streaming Markdown sources.
- CommonMark + GFM support - tables, strikethrough, task lists, autolinks, footnotes, and admonitions, with known differences and streaming limitations documented below.
- Extras - highlights.
- Tables - box-drawing borders, alignment, automatic layout, and wrapping that preserves styling.
- Unicode-correct - tested with CJK and emoji.
- Syntax highlighting - simplified, generic highlighting using five styles, applied to code blocks in major programming languages.
- Inline HTML - tags and entities styled for the terminal, with comments hidden.
- HTML blocks - raw HTML scanned and styled, entities decoded, comments hidden, and Markdown inside is left literal.
- Clickable links - links, autolinks, and emails are OSC 8 terminal hyperlinks.
- Color themes - a default theme that respects the terminal's local color palette, a TERM_256 theme that uses a more stable 256-color palette, and a plain mode that disables ANSI styling.
This section describes mdflow's current level of Markdown support and its known differences. It is not a claim of full conformance. CommonMark and GFM define expected HTML output in their examples. This section only addresses the parser, not mdflow's ANSI renderer or its terminal presentation.
mdflow is tested against all 652 CommonMark specification examples and the GFM features listed above. The complete example set is included in the test suite. MD4C is fully CommonMark-compliant; mdflow's parser produces output identical to MD4C for all examples except those involving a limitation documented below.
A proper live Markdown generator already avoids features that depend on future input. In static documents, the practical impact remains small.
| Feature | mdflow behavior | Practical impact |
|---|---|---|
| Tight/loose lists | The first list item may retain tight. | No visible difference in the terminal. |
| Multi-line Setext headings | Only the last line becomes a heading. | Affects only uncommon multi-line Setext headings. |
| Feature | mdflow behavior | Practical impact |
|---|---|---|
| Reference links | Reference shown immediately without resolving definition, and definitions appear at the end. | Rare in live Markdown. Not fully functional in a terminal anyway. No content is lost. |
| Footnotes | Footnote reference shown immediately without validating definition. | Rare in live Markdown. No content is lost. |
- Syntax highlighting - current highlighting is lightweight and generic, rather than language-specific.
- No pager or TUI - mdflow renders; scrolling is left to
moreorless -R. - Customization - two built-in themes and one fixed configuration object are exposed; user-defined themes and additional feature flags are not exposed.
More: streaming Markdown renderer | FAQ | LLM terminal recipes
mdflow is also a small C library with a small libc-only API:
#include "mdflow.h"
mdflow_config_t config;
mdflow_t* mf;
config.theme = MDFLOW_THEME_DEFAULT;
config.plain = 1;
config.osc8 = 1;
mf = mdflow_open(80, &config, my_output_callback, my_userdata);
mdflow_write(mf, "# Hello\n", 8);
mdflow_close(mf);cmake -S . -B build
cmake --build buildBuilding requires only a C compiler and CMake. GCC and Clang builds enable -Wall, -Wextra, and -Wshadow.
stdin -> parser (streaming) -> renderer (streaming) -> stdout
Two components, both streaming, bundled into one library - no AST, no document buffer.
Parser (MD4CS) - MD4C is a fast SAX-like Markdown parser with a flat-buffer design, though it still buffers in full and fires all callbacks at the end, because many features depend on input that has not arrived yet.
When analyzed feature by feature, some require only one line of lookahead; some require unbounded lookahead but style can be determined earlier. mdflow's parser MD4CS, builds on top of MD4C, reconstructs the features that require handling to enable true streaming. It can thus emit callbacks in the first pass and free memory immediately.
Renderer (md4cs-ansi) - maps parser callbacks to styled terminal output.
Sub-modules:
highlight.c- single-pass lightweight code highlighting, derived from microlight (MIT)html.c- HTML tag/entity scanner that styles raw HTML- tables - box-drawing layout that redraws when column widths change mid-stream
- MD4C by Martin Mitas (MIT) - the parser mdflow is built on.
- microlight by asvd (MIT) - the code highlighter is derived from it.
MIT. See LICENSE and the license comments in the source file headers.
