Release candidatePure Zsh · HTML to Markdown · v1.0.0-rc.1

zhtml2md

Turn HTML into Markdown an agent can read.

zhtml2md converts UTF-8 HTML into compact, deterministic Markdown, entirely inside Zsh. Use it on its own or after an HTML cleaner when preparing web content for AI-agent workflows.

View on GitHub

Preserve what the document says

Readable structure

Convert headings, paragraphs, nested lists, blockquotes, links, and code into Markdown while preserving their text and hierarchy.

Tables with fallbacks

Render simple tables as GFM pipes. Complex tables use row and cell lists that retain spans and child blocks.

Text handled deliberately

Decode supported HTML character references, preserve code whitespace, and escape prose punctuation so source text stays text.

Pure Zsh, ready to source

Use the library or CLI with Zsh 5.8 or newer. Conversion needs no external commands, parsers, codecs, or loaded modules.

Source it or run the CLI

Keep the checkout intact so the library can locate its supporting files. Read a file or stdin, and write Markdown to stdout.

source /path/to/zhtml2md/zhtml2md.zsh

zhtml2md -- page.html > page.md
print -r -- '<h1>Hello</h1><p>Read <strong>this</strong>.</p>' | zhtml2md

# Or use the standalone CLI:
/path/to/zhtml2md/bin/zhtml2md -- page.html > page.md

Conversion buffers the document until validation, parsing, and rendering succeed. Diagnostics go to stderr. The optional --strict flag rejects documented recoverable syntax defects instead of repairing them.

From cleaned HTML to agent context

zoup can remove scripts and visual layers before conversion. zhtml2md then renders the retained semantic HTML as Markdown. Both are part of the page-reading pipeline in zfetch.

The converter also works independently for its documented HTML subset. It preserves retained content, including navigation, rather than selecting an article or executing JavaScript.

Release candidate, explicit bounds

Version 1.0.0-rc.1 is a locally verified v1 candidate, tested on Linux with actual Zsh 5.8 and 5.9.2 binaries. Input is limited to 4 MiB, nesting to 256 frames, and rendered output to 16 MiB. Its documented HTML parsing and recovery rules define the supported subset.