mdx
A fast, single-binary markdown toolchain built in Rust. Render in the terminal with syntax highlighting, preview in the browser with live reload, search, fetch web pages, format, lint, diff, export to HTML/PDF/EPUB, and publish — all from one command.
Install #
bashcurl -fsSL https://raw.githubusercontent.com/Harsh-2002/mdx/main/install.sh | sh
powershellirm https://raw.githubusercontent.com/Harsh-2002/mdx/main/install.ps1 | iex
bashcargo install --git https://github.com/Harsh-2002/mdx --features serve
Installs the binary and sets up shell completions automatically. Works on macOS, Linux (glibc and musl), and Windows. Supports x86_64 and ARM64.
Pre-built binaries
Each release includes pre-built binaries for every supported platform. Download the one that matches your system:
| Binary | Platform | Architecture |
|---|---|---|
mdx-x86_64-apple-darwin.tar.gz | macOS | x86_64 (Intel) |
mdx-aarch64-apple-darwin.tar.gz | macOS | ARM64 (Apple Silicon) |
mdx-x86_64-unknown-linux-gnu.tar.gz | Linux (glibc) | x86_64 |
mdx-x86_64-unknown-linux-musl.tar.gz | Linux (musl) | x86_64 |
mdx-aarch64-unknown-linux-gnu.tar.gz | Linux (glibc) | ARM64 |
mdx-aarch64-unknown-linux-musl.tar.gz | Linux (musl) | ARM64 |
mdx-armv7-unknown-linux-gnueabihf.tar.gz | Linux (glibc) | ARMv7 (32-bit) |
mdx-x86_64-pc-windows-msvc.tar.gz | Windows | x86_64 |
mdx-aarch64-pc-windows-msvc.tar.gz | Windows | ARM64 |
Extract and move the binary to a directory in your PATH:
bashtar xzf mdx-<target>.tar.gz
sudo mv mdx /usr/local/bin/
Quick Start #
bashmdx README.md # render in terminal
mdx README.md --pager # pipe through less
mdx serve file.md # live preview in browser
mdx serve ./notes/ # serve a directory of notes
mdx search "query" ./docs/ # full-text search across files
mdx fetch https://example.com # fetch web page as markdown
mdx export --to epub file.md # export to EPUB e-book
mdx update # self-update to latest version
cat README.md | mdx # read from stdin
mdx https://example.com/doc.md # render from URL
Features #
- Syntax highlighting — language-aware code blocks via syntect
- Tables — full GFM table rendering with alignment and cell wrapping
- Docs extensions — description lists,
==highlight==,^superscript^,[[wikilinks]]and inline footnotes, on top of GFM — each rendering in every output target - Mermaid diagrams — rendered as interactive SVG in browser preview (
mdx serve) via mermaid.js - Math — inline
$...$and display$$...$$; KaTeX in browser preview, Unicode in the terminal (\frac{a}{b}renders asa/b) - Images — inline image rendering in supported terminals (iTerm2, kitty)
- URL fetching —
mdx <url>andmdx fetch <url>share one pipeline: markdown URLs render as markdown, web pages have their article extracted - Web page extraction —
mdx fetchextracts article content as clean markdown, with MFA content negotiation - Markdown for Agents —
mdx serveresponds with raw markdown when AI agents sendAccept: text/markdown - Live reload —
mdx serveopens a browser preview that updates on save - Built-in editor — edit markdown in the browser, saves back to disk
- Search & replace — find and replace text in the editor with regex support
- Image upload — drag and drop or paste images into the editor
- Print / PDF — native PDF export, plus browser print with clean CSS
- Reproducible PDFs — the same document always exports to the same bytes, with subset fonts keeping files small and
SOURCE_DATE_EPOCHhonoured - Structured fetch —
mdx fetch --jsonreports status, extraction method, token count and warnings alongside the markdown;--max-tokenstrims to a context window - EPUB export —
mdx export --to epubfor Apple Books, Kobo, Calibre, and other e-readers - Full-text search —
mdx searchwith BM25 ranking, tag filtering, and parallel file parsing - Dark/light theme — toggle with button or t, persisted across sessions
- Slide presentation —
mdx presentturns---separators into terminal slides - ToC generation —
mdx tocextracts headings with depth control - Self-update —
mdx updateupdates to the latest release - Shell completions —
mdx completions installfor bash, zsh, fish, PowerShell - Alerts — GitHub-style note, tip, warning, and caution blocks
- Full GFM — footnotes, task lists, strikethrough, autolinks
CLI Tools #
mdx fetch — Web page to markdown
Fetches a web page, extracts the main article content using Mozilla Readability, and outputs clean markdown. Supports the Markdown for Agents protocol — MFA-enabled sites return pre-converted markdown directly. Great for LLM pipelines.
--json emits a structured object instead: the requested and final URLs, HTTP status, how the content was extracted (server-markdown, readability or raw), token estimate, warnings, and the markdown itself — so a pipeline can tell a clean extraction from a fallback without parsing stderr. --max-tokens truncates to roughly a token budget, cutting at a block boundary and never inside a code fence.
bashmdx fetch https://example.com # extract article as markdown
mdx fetch --raw https://example.com # full HTML to markdown (sanitizes scripts)
mdx fetch --metadata https://example.com # include YAML front matter
mdx fetch --tokens https://example.com # show estimated token count
mdx fetch -o article.md https://example.com # save to file
mdx fetch --json https://example.com | jq -r .content # structured output
mdx fetch --json --max-tokens 4000 URL # fit a context window
mdx fetch https://example.com | llm # pipe to LLM
mdx toc — Table of contents
Extracts headings from a markdown file and prints a table of contents with configurable depth.
bashmdx toc README.md # print table of contents
mdx toc --depth 2 README.md # limit to h1 and h2
mdx stats — Document statistics
Word count, reading time, headings, links, images, and code blocks at a glance.
$ mdx stats README.md
Words: 1,247
Lines: 89
Headings: 12
Links: 8
Code blocks: 3
Reading time: ~5 min
mdx fmt — Markdown formatter
Normalizes markdown formatting. Use --check in CI to enforce consistent style.
bashmdx fmt README.md # print formatted to stdout
mdx fmt --in-place README.md # overwrite the file
mdx fmt --check README.md # exit 1 if not formatted (CI)
mdx lint — Markdown linter
Checks for broken links, duplicate headings, missing image alt text, and trailing whitespace.
$ mdx lint README.md
README.md:12 broken link: ./missing.md
README.md:34 image missing alt text
README.md:45 duplicate heading: "Setup"
3 issues found
mdx diff — Markdown diff
Colored side-by-side or unified diff of two markdown files.
bashmdx diff old.md new.md # side-by-side
mdx diff -u old.md new.md # unified
mdx diff - new.md # read first file from stdin
mdx search — Full-text search
BM25-ranked search across markdown files. Headings are weighted higher than body text, body higher than code. Files are parsed in parallel. Automatically skips .git, node_modules, target, and other non-content directories.
bashmdx search "rust async" . # search current directory
mdx search "query" docs/ # search recursively
mdx search --tag rust "ownership" # filter by front matter tag
mdx search -n 5 "error" . # top 5 results
mdx search -l "query" . # list matching file paths only
mdx export — Format conversion
Export markdown to a single-file HTML page, PDF, EPUB, JSON AST, or plain text. EPUB embeds local images, splits chapters on headings, and maps front matter to metadata. HTML is one file, but math and mermaid load KaTeX and mermaid.js from a CDN, so those two need a network connection to display. PDF renders mermaid with a local mmdc; without it the diagram is written in as a labelled source block and the export still succeeds — --allow-remote-render uploads the source to kroki.io instead, so it is off by default.
PDF output embeds only the glyphs a document actually uses, so files are small — this site’s own README exports to about 200 KB rather than 3 MB. Output is also byte-reproducible: exporting the same document twice produces the same file, and SOURCE_DATE_EPOCH sets the embedded timestamp.
bashmdx export --to html README.md # single-file HTML page
mdx export --to pdf README.md # PDF (native, no browser needed)
mdx export --to epub README.md # EPUB e-book
mdx export --to json README.md # AST as JSON (for tooling)
mdx export --to txt README.md # plain text (strip formatting)
mdx publish — Static site generator
Generate a static site from a directory of markdown files. Supports YAML front matter for titles, dates, tags, and draft status.
bashmdx publish ./blog --out ./dist
mdx update — Self-update
Updates mdx to the latest release from GitHub. Downloads the correct binary for your platform automatically.
bashmdx update
mdx completions — Shell completions
Generate or install tab completions for your shell. Supports bash, zsh, fish, and PowerShell.
bashmdx completions install # auto-detect shell and install
mdx completions bash # print bash completions
mdx completions zsh # print zsh completions
mdx completions fish # print fish completions
mdx completions powershell # print PowerShell completions
mdx present — Slide presentation
Present markdown as slides in the terminal. Splits content on --- separators.
bashmdx present slides.md
mdx watch — Watch mode
Re-renders markdown in the terminal whenever the file changes.
bashmdx watch file.md
Serve Mode #
mdx serve turns your markdown into a live browser preview with three modes:
Single file — mdx serve file.md opens a live preview. Edit in your editor, the browser updates instantly on save.
Directory — mdx serve ./notes/ shows all .md files as a card grid. Click any card to view it, or click "+" to create a new note.
Multiple files — mdx serve a.md b.md c.md
mdx serve file.md --host 0.0.0.0 # expose on your LAN
mdx serve file.md --unsafe-html # render raw HTML in the document serves the listed files with sidebar navigation and search.
All modes include a built-in editor, image upload (drag and drop or paste), print/PDF export, dark/light theme, and a table of contents sidebar. AI agents sending Accept: text/markdown get raw markdown with X-Markdown-Tokens and Vary: Accept headers instead of HTML (Markdown for Agents protocol).
Local images are served from the document's directory, so  renders — including files the drag-and-drop uploader writes.
Security defaults
The server is unauthenticated: anyone who can reach the port can read your files, overwrite them, create new ones and upload into assets/. So it is locked down by default.
- Binds
127.0.0.1— reachable only from this machine.--host 0.0.0.0exposes it to your network. - Answers only on an address —
127.0.0.1,::1,localhostor a LAN IP, never a domain name. Binding loopback alone does not stop a web page pointing a domain at127.0.0.1and reaching the server through your browser; requiring an address in theHostheader does. Writes carrying a cross-originOriginare refused. - Raw HTML is dropped — a
<script>in a downloaded or agent-written document cannot run.--unsafe-htmlrenders it the way GitHub does:<div>and<details>pass,<script>and<iframe>stay neutralised.
mdx export is different: it writes a file you open yourself, so it converts your document faithfully, tags and all.
| Key | Action |
|---|---|
| e | Toggle editor |
| t | Toggle dark/light theme |
| [ | Toggle sidebar |
| ] | Switch sidebar tab |
| Ctrl+F | Search in editor |
| Ctrl+H | Search and replace |
How It Works #
mdx parses markdown into an AST using comrak (CommonMark + GFM), then walks the tree to produce either styled terminal output with ANSI escape codes, or HTML served via a local server with SSE-based live reload.
markdown file
|
v
comrak --> AST
|
|--> terminal renderer --> ANSI output
|
|--> HTML renderer --> axum server --> browser (live reload via SSE)
|
'--> CLI tools (stats, toc, fmt, lint, diff, search, export, fetch, publish)Credits #
mdx is built on top of these open-source libraries:
| Library | Purpose |
|---|---|
| comrak | Markdown parsing (CommonMark + GFM) |
| syntect | Syntax highlighting for code blocks |
| clap | CLI argument parsing and completions |
| axum | HTTP server (serve mode) |
| tokio | Async runtime |
| notify | File system watcher (live reload) |
| ratatui | TUI framework (watch and present modes) |
| crossterm | Terminal manipulation |
| similar | Text diffing |
| rayon | Parallel file parsing (search) |
| walkdir | Recursive directory traversal |
| textwrap | Text wrapping |
| image | Image decoding (PNG, JPEG, GIF, WebP) |
| genpdfi | PDF layout |
| printpdf | PDF writing |
| subsetter | Font subsetting for PDF |
| epub-builder | EPUB e-book generation |
| ureq | HTTP client (URL fetching) |
| dom_smoothie | Web article extraction (Readability) |
| htmd | HTML to markdown conversion |