CLI & GitHub Action · EPUB 3 · Optional PDF export · MIT License

Build EPUB ebooks and PDFs from Markdown.

mdbindery turns Markdown chapters or mdBook projects into EPUB 3 ebooks or paginated PDFs. Both formats share chapter links, citations, images, Mermaid diagrams and table conversion. EPUB runs EPUBCheck and DAISY Ace; PDF checks resources, links and extracted text. Review reports and layout before sharing.

EPUB remains the default. PDF export is available with the optional pdf extra. Set up PDF export.

bash — mdbindery check & build exit 0
# 1. Dry-run check any local folder or remote GitHub URL
$ mdbindery check https://github.com/OWNER/REPO

# 2. Build EPUB 3 and run validation gates
$ mdbindery build examples/sample-book
mdbindery: writing-a-book-in-markdown (5 files)
  k00 README.md: dropped ['Contributing']
  k01 01-why-markdown.md: 2 refs, 2 image(s)
  k02 02-structure.md: 1 chart(s), 2 image(s)
  k03 03-publishing.md: 1 refs
  k04 appendix-a-checklist.md: tables as cards
  built dist/writing-a-book-in-markdown.epub (108 KB)
  EPUBCheck: no messages
  Ace: 0 violation(s), 0 blocking
  word count: every file within 2% or 25 words of its source
BUILD OK

# 3. Export PDF after installing PDF dependencies
$ mdbindery build ./my-book --format pdf
Capabilities

Keep your Markdown book workflow

Write and review chapters on GitHub. Both formats share source preparation and local assets; output checks and layout depend on the selected format.

Chapter links

Chapter links and anchors

Relative links between chapters, links to headings in other files, .html links pointing to .md chapters, and custom <a id> anchors become internal book links. Any broken internal target fails the build when strict_links is enabled.

References

Visible reference lists

Citations written as [1] paired with [1]: url "Title" reference definitions (which are invisible on GitHub) become a visible, numbered reference list at the end of the chapter with working links. Footnotes become numbered endnotes.

Book assets

Images and covers

Images automatically become inline icons, block images, captioned <figure> blocks (from the image title), or dedicated full-page images ("full-page" title). Supply any supported image format for the cover or let mdbindery generate a 1600×2560 typographic cover from book metadata.

Diagrams and math

Mermaid diagrams and MathML

Fenced ```mermaid diagrams render to PNG images via mermaid-cli with automatic alt text extracted from the chart labels. TeX formulas convert to MathML for EPUB readers and Chromium PDF rendering.

Small screens

Wide tables as row cards

For files listed under options.cards.files, wide Markdown tables (options.cards.min_columns, default 9 columns) transform into vertical per-row card blocks with repeated header labels so they read cleanly on a phone.

GitHub formatting

GitHub formatting and HTML

GitHub alerts (> [!NOTE]), task lists, monochrome code syntax highlighting, and supported raw README HTML (<br>, <sup>, <img>, <p align>, <details>) pass through shared cleanup for EPUB and PDF; unsupported tags are removed and reported.

mdBook

Read existing mdBook settings

For mdBook projects, book.toml supplies book metadata, SUMMARY.md sets the reading order, {{#include}} directives expand with cycle and size limits, and hidden Rust lines are stripped.

PDF export

Paginated PDF

Choose A4 or Letter pages, margins and page numbers with options.pdf. Export uses installed Chromium and shared book styles with print overrides. Inspect pagination and glyphs; PDF/A, PDF/UA and print-production readiness are not claimed.

Deterministic

Reproducible EPUB builds

Building the same Git commit twice with the same tools, fonts, and a saved metadata.identifier produces byte-identical .epub files. EPUB metadata includes a publication identifier and schema.org accessibility information.

Installation

Install on Linux, macOS, Windows, or CI

The installers need no preinstalled Python, Java, or Node.js and no administrator rights. Linux and macOS need Bash, curl, tar, and standard checksum utilities; Windows needs PowerShell. Tools are installed in your user directory. Once installed, local builds work offline. See tool versions and verification.

Linux & macOS

Installs mdbindery to ~/.local/bin and managed tools to ~/.local/share/mdbindery (macOS: ~/Library/Application Support/mdbindery):

curl -fsSL https://raw.githubusercontent.com/sagol/mdbindery/main/install/install.sh | bash

Pin a specific release tag or pass --no-node to skip Node.js tools (~370 MB instead of ~1.5 GB):

curl -fsSL https://raw.githubusercontent.com/sagol/mdbindery/v0.2.0/install/install.sh | bash -s -- --ref v0.2.0

Windows PowerShell

Installs to %USERPROFILE%\.local\bin (added to user PATH) and tools to %LOCALAPPDATA%\mdbindery:

irm https://raw.githubusercontent.com/sagol/mdbindery/main/install/install.ps1 | iex

PyPI (uv / pipx)

Install the Python package from PyPI with uv or pipx, then install the companion tools:

uv tool install mdbindery
mdbindery install-tools
mdbindery doctor

Homebrew (macOS & Linux)

Install from the Homebrew tap on macOS or Linux, then run install-tools:

brew install sagol/tap/mdbindery
mdbindery install-tools
mdbindery doctor

GitHub Actions

Use the official composite GitHub Action with tool caching across workflow runs:

- uses: sagol/mdbindery@v0.2.0
- run: mdbindery build path/to/book

Optional PDF export

Install version 0.2.0 or newer with the PDF extra in your Python environment:

python -m pip install 'mdbindery[pdf]>=0.2.0'
mdbindery install-tools
mdbindery build ./my-book --format pdf

PDF needs Node.js, Puppeteer and pypdf. An install with --no-node cannot export PDF. doctor checks the EPUB toolchain; it does not verify pypdf. See the PDF guide.

Downloaded uv, pandoc, EPUBCheck, and Node.js binaries are checked against pinned SHA-256 checksums. Java uses a suitable installed runtime or the latest Temurin 21 build, verified with the checksum returned by its API. Mermaid-cli and Ace have pinned top-level npm versions; their dependencies resolve during installation.

Build checks

Validation for each output format

Both formats check links, images, charts and includes. EPUB adds EPUBCheck, Ace and per-chapter word counts; PDF adds resource, internal-link and extracted-text checks. Reports use dist/reports/build.json for EPUB or dist/reports/pdf/build.json for PDF. The includes entry appears only on failure. A failed gate returns status 1.

links · Both Gate

Fails on unresolved internal chapter anchors or links to missing files when options.strict_links is true (default); warns when false.

images · Both Gate

Fails when an image is missing, remote (http://, https://), empty, or (for untrusted repositories checked by URL) outside the repository checkout.

charts · Both Gate

Fails when a ```mermaid block fails to render. Warns (using chart placeholders) if mermaid-cli is missing while options.mermaid is png.

includes · Both Gate

Reports failed mdBook {{#include}} expansions (missing file, cycle, or size limit). The includes gate appears in build.json only with result: "fail". It is omitted when no include directive fails; no pass entry is emitted.

epubcheck · EPUB Gate

Runs W3C EPUBCheck v5.4.0 (unless options.epubcheck: false). Fails on any FATAL or ERROR message or if EPUBCheck cannot run.

ace · EPUB Gate

Runs DAISY Ace 1.4.6 (skipped with --no-ace or options.ace: false; warns if Ace is not installed). Fails on unwaived critical or serious violations.

wordcount · EPUB Gate

Fails if any chapter's EPUB word count differs from its prepared Markdown source by more than 2% (wordcount_tolerance) and 25 words (wordcount_min_words).

pdf · PDFGate

Checks loaded resources and internal links, then compares extracted PDF text with generated HTML using the configured word-count tolerances. A readable PDF with failed text checks remains available for inspection. Renderer errors preserve an older PDF. Scripts are disabled and unstaged resource requests are blocked. PDF never automatically disables the browser sandbox.

Command Purpose Exit Codes
mdbindery doctor Inspect installed versions of pandoc, epubcheck, java, node, mermaid, ace, and python. 0 required tools OK · 1 pandoc or EPUBCheck missing
mdbindery check [target] Dry-run static + pandoc check on a local folder or GitHub/Git URL. Supports -c FILE, --ref REF, --build, --no-render, --json FILE, --report FILE, -q. 0 no errors · 1 errors found · 2 target unreadable · 3 internal error
mdbindery init [path] [--force] Infer reading order, metadata, cover, and mdBook settings and write a starter mdbindery.yaml. 0 written · 1 exists or empty · 2 folder not found or bad config
mdbindery build [path] Build EPUB by default or select --format pdf. PDF writes dist/<slug>.pdf and reports under dist/reports/pdf/. Supports --format epub|pdf, -c CONFIG, -o OUT, --no-ace (EPUB only), --keep-work, -q. 0 BUILD OK · 1 gate failed · 2 config/build error · 3 internal error
mdbindery preview <epub> <out> [page ...] Capture phone-size (default 412×915 CSS px at 2x scale) PNG screenshots of EPUB pages in headless Chrome with scripts off and external requests blocked. Supports --width, --height, --full. 0 screenshots written · 2 bad input or missing tools · 3 internal error
mdbindery install-tools Install companion tools using the version and verification policy. Supports --no-node, --java, --force. 0 required tools OK · 1 pandoc/EPUBCheck missing · 2 install failed
Agent integration

Agent skills and JSON reports

mdbindery ships with self-contained SKILL.md instructions and structured JSON reports so AI coding agents (Claude Code, OpenAI Codex, Cursor, Google Antigravity, Gemini CLI, Windsurf, Aider) can inspect, repair, build, and preview Markdown book repositories.

Skill 1: mdbindery Run and validate

Instructions for installation, tool checks, configuration, builds, and previews. Run mdbindery check . --json check.json for a local book, or replace . with a repository URL. Review reports and screenshots before publishing.

Read the CLI skill

Skill 2: mdbindery-prepare-repo Check and fix

Instructions to resolve MB001–MB904 findings in a Markdown repository or mdBook: reading order, headings, anchors, [1] citations, alt text, wide tables, and raw HTML. Preserve the author’s meaning and GitHub rendering when making changes.

Read the repository preparation skill

Prompt for a coding agent

Read https://sagol.github.io/mdbindery/llms-full.txt and the two official skills:
- https://raw.githubusercontent.com/sagol/mdbindery/main/skills/mdbindery/SKILL.md
- https://raw.githubusercontent.com/sagol/mdbindery/main/skills/mdbindery-prepare-repo/SKILL.md

Then run `mdbindery check . --json /tmp/mdb-check.json --report /tmp/mdb-check.md -q`, propose a plan to resolve all MB errors and warnings without altering author prose meaning, and loop until `mdbindery build` finishes with `BUILD OK` and no gate skipped or at `warn`.
/llms.txt Concise llmstxt.org index with CLI syntax, install commands, and doc links.
/llms-full.txt Single-file reference: CLI flags, YAML schema, EPUB/PDF gates and 59 MB codes.
/agents.json Project JSON capability manifest (pointer also at /.well-known/agent.json).
mdbindery check . --json FILE Structured diagnostic output with ok, counts, by_code, facts, and findings.
Diagnostics

All 59 check codes (MB001–MB904)

Findings from mdbindery check include a diagnostic code, severity, location where available, and suggested fix. Filter by severity or search by code or keyword.

Showing 59 of 59 check codes
Code Severity Reported When Fix
MB001 warning pandoc (≥3.8) is not installed; internal link and HTML analysis skipped. Run mdbindery install-tools and verify with mdbindery doctor.
MB100 error Reading order is empty (no Markdown chapter files found). Add .md chapters to the book folder or list them under files: in mdbindery.yaml.
MB101 info No mdbindery.yaml configuration file found; using inferred settings. Run mdbindery init to generate mdbindery.yaml.
MB102 error / warn Configuration file has invalid YAML, wrong types, paths outside repo, or unknown keys. Fix syntax, types, or key names in mdbindery.yaml.
MB103 error A file listed under files: in mdbindery.yaml does not exist. Fix the relative file path or remove the missing entry from files:.
MB104 info A Markdown file in the repository is not included in the reading order. Add the file to files: if it belongs in the book, or leave it excluded.
MB105 error / info Error: file is not valid UTF-8. Info: file has a UTF-8 BOM or CRLF line endings. Re-save the file as UTF-8 without BOM and LF line endings.
MB106 warning Chapter file has no level-1 # heading. Add a # Chapter Title heading at the top or set title: on the files: entry.
MB107 warn / info Warning: one file has multiple # headings. Info: several files share the same first heading. Demote extra # headings inside a chapter to ##.
MB108 warning A heading skips a hierarchy level (e.g. # directly to ###). Use sequential heading levels (#, ##, ###) to avoid skipped-heading accessibility findings.
MB109 warning Chapter file is empty (or empty after drop_sections / drop_lines). Remove the file from files: or add chapter content.
MB110 warning Content appears above the chapter's first level-1 # heading. Move content below the # heading or strip repository badges via options.drop_lines.
MB111 warning Chapter starts with YAML front matter (which pandoc drops). Move book metadata into mdbindery.yaml or set title: on the file entry.
MB120 info Book title was inferred automatically. Set metadata.title explicitly in mdbindery.yaml.
MB121 warning No author specified in metadata. Set metadata.authors: ["First Last"] in mdbindery.yaml.
MB122 info Book language was inferred as en-US. Set metadata.lang (BCP-47 tag) in mdbindery.yaml.
MB123 warning No rights statement or license file found. Set metadata.rights or add a LICENSE file to the repository.
MB124 info metadata.identifier is empty; a permanent urn:uuid will be generated on first build. Keep identifier: in mdbindery.yaml so the generated ID is saved, or set your own permanent ID.
MB125 info Reading order was inferred from SUMMARY.md, README.md links, or file names. Review the reading order and lock it under files: in mdbindery.yaml.
MB126 warning A table-of-contents file (SUMMARY.md, toc.md) is listed in files:. Remove it from files:; mdbindery generates the EPUB navigation TOC automatically.
MB130 info Book uses an mdBook layout (book.toml + SUMMARY.md). Informational note; metadata and reading order are read from book.toml and SUMMARY.md.
MB131 error An mdBook {{#include}} directive could not be expanded (missing file, cycle, or limit). Fix the included file path, line range, or circular include chain.
MB200 error Link points to a missing #anchor in the target chapter. Point the link at an existing GitHub heading slug or add <a id="..."></a>.
MB201 warning Link anchor matched only approximately (when punctuation is ignored). Update the link fragment to match the exact GitHub heading slug.
MB202 warn / info Link points to an existing repository file that is outside the book's reading order. Set source_url in mdbindery.yaml so the link points online, or add the file to files:.
MB203 warning Relative link points to a website path that does not exist in the repository. Use a full https:// URL or set source_url.
MB204 error Link points to a local file that does not exist. Fix the relative path (relative to the current Markdown file) or remove the broken link.
MB205 info A .html or folder link was resolved to a matching .md chapter. Optional: change the link target to .md so it also works directly on GitHub.
MB300 warning Numeric reference definition [n]: url is never cited in the file. Cite [n] in the text or remove the unused definition.
MB301 error Reference label [n] is defined more than once with different URLs in the same file. Give each reference a unique number within the chapter.
MB302 warning Citation [n] in text has no matching [n]: url definition in that file. Add [n]: https://... "Title" at the bottom of the chapter.
MB303 info File uses [n] citations but has no References heading; mdbindery appends one. Optional: add ## References where you want the reference list placed.
MB304 error Footnote reference [^id] has no matching [^id]: text definition. Add the footnote definition or escape the bracket as \[.
MB305 warning Footnote definition [^id]: is never referenced in the chapter. Reference [^id] in the text or remove the unused footnote definition.
MB306 info Citation definition [n]: url has no title; the raw URL will be shown. Add a descriptive title in quotes: [n]: https://... "Source Title".
MB400 error Image has an empty path or its file does not exist on disk. Fix the image path (relative to the Markdown file, or / for repository root).
MB401 error / info Error: remote HTTP(S) image URL. Info: GitHub URL pointing to a file in the same repo. Download remote images into images/ inside the repository and use relative paths.
MB402 warning Image has no alt text (![](path) or <img> without alt). Add descriptive alt text: ![what the image shows](path).
MB403 error / warn Unsupported or non-standard image format (e.g. TIFF, BMP, ICO, AVIF). Convert the image to PNG, JPEG, SVG, GIF, or WebP.
MB404 warning Image exceeds 3200 px on its long side or file size exceeds 5 MB. Scale to at most 3200 px on the long side and compress photos (e.g. magick big.jpg -resize '3200x3200>' -quality 85 big.jpg).
MB405 warn / info Warning: SVG contains scripts or foreignObject. Info: animated GIF/PNG/WebP image. Remove scripts/foreignObject from SVG; replace animated images with a static frame if needed.
MB406 error / warn Error (URL check): image path leaves repository checkout. Warning (local check): image lies outside book source folder. Copy the image into images/ inside the book folder.
MB407 warning Symlink in a URL-checked repository pointed outside the checkout and was removed. Replace the external symlink with a real file inside the repository.
MB410 info No cover image found; mdbindery will generate a typographic cover automatically. Optional: add images/cover.jpg (1600×2560 px) or set cover.image.
MB411 warning Cover short side is below 1400 px, height:width ratio is outside 1.4 to 1.7 (ideal 1.6:1), or color mode is CMYK. Use an RGB JPEG or PNG around 1600×2560 px (at least 1400 px on the short side).
MB412 error / warn Error: cover image missing or unreadable. Warning: cover format converted to JPEG. Fix cover.image path or supply a valid JPEG/PNG file.
MB500 error / warn Chapter contains raw HTML tags that EPUB 3 cannot keep (<script>, <iframe>, <form>, <video>, etc.). Replace unsupported HTML elements with Markdown text, tables, or static images.
MB501 info Raw HTML was simplified or stripped during conversion. Verify the chapter in the built EPUB; replace raw HTML with Markdown if needed.
MB600 warning Pipe table has options.wide_table_warn (default 9) or more columns and its file is not listed in options.cards.files. List the file under options.cards.files (renders tables with ≥options.cards.min_columns columns as row cards) or split the table.
MB700 warning Book contains Mermaid charts, options.mermaid is png, and mermaid-cli is not installed. Run mdbindery install-tools (without --no-node).
MB701 error A ```mermaid chart failed to render due to a syntax error. Fix the Mermaid diagram syntax at the reported file and line.
MB710 info Book contains TeX math expressions (converted to MathML). Informational note; verify formulas in an EPUB 3 reader.
MB711 warning Text between dollar signs $...$ was read as a math formula or failed TeX parsing. Escape literal currency dollar signs as \$ or wrap code in backticks.
MB720 info Code block has lines longer than 90 characters. Optional: wrap long lines so code blocks read comfortably on narrow screens.
MB900 error / warn Trial build (--build): EPUBCheck reported an error or warning. Fix the underlying Markdown/HTML construct flagged by EPUBCheck.
MB901 error / warn Trial build (--build): DAISY Ace reported an accessibility violation (or Ace is missing). Fix heading order, alt text, or table structure; or install Ace with mdbindery install-tools.
MB902 error Trial build (--build): per-file word count differed by more than 2% and 25 words. Inspect dropped raw HTML or unclosed blocks that caused text loss in the reported file.
MB903 error Pandoc analysis or trial build stopped with an error or timed out. Check the error message or raise timeouts with MDBINDERY_TIMEOUT_SCALE.
MB904 error A trial-build validation gate failed. Resolve all reported gate errors and rerun mdbindery check --build.
Configuration

Configure your book with mdbindery.yaml

Every key in mdbindery.yaml is optional. Run mdbindery init to generate a starter configuration from your repository, or keep your book repository untouched by placing mdbindery.yaml in a separate folder with source_dir.

Sample book configuration with PDF defaults YAML
slug: writing-a-book-in-markdown
output_dir: dist
source_url: https://github.com/sagol/mdbindery/blob/main/examples/sample-book/

metadata:
  title: Writing a Book in Markdown
  subtitle: A small sample book for mdbindery
  authors: [Sample Author]
  lang: en-US
  identifier: urn:uuid:5f0f1c2e-8a4b-4d6e-9c1a-3b7e2d9f0a11
  date: 2026-09-26
  rights: Text and images licensed under CC BY 4.0
  description: A short book that demonstrates every feature of mdbindery.
  subjects: [Markdown, EPUB, Publishing]

cover:
  image: images/cover.jpg

files:
  - file: README.md
    role: front
    title: About this book
    drop_sections: [Contributing]
  - 01-why-markdown.md
  - 02-structure.md
  - 03-publishing.md
  - file: appendix-a-checklist.md
    role: appendix

options:
  citations: refdefs
  toc_depth: 2
  pdf:
    page_size: A4
    margin_mm: 20
    page_numbers: true
  cards:
    files: [appendix-a-checklist.md]
    min_columns: 9
    title_columns: 2

Build the sample book

From a checkout of the mdbindery repository, build the included sample book:

mdbindery doctor
cd examples/sample-book
mdbindery check . --build
mdbindery build
# After installing PDF dependencies
mdbindery build --format pdf
mdbindery preview dist/writing-a-book-in-markdown.epub shots

PDF writes dist/<slug>.pdf and dist/reports/pdf/{build.json,build.log}. EPUB and its reports remain available. The cover image is shared; PDF reports add Chromium/Puppeteer versions. PDF bytes are not guaranteed reproducible. preview accepts EPUB only.

Build files and provenance

Completed EPUB builds write dist/<slug>.epub, dist/<slug>-cover.jpg, dist/reports/build.json, and dist/reports/build.log, plus dist/reports/epubcheck.json and dist/reports/ace/report.json (and report.html) when those validators produce reports. A build that stops early may leave only failure diagnostics. build.json records provenance (mdbindery, python, pandoc major.minor, epubcheck, and ace versions, source Git commit, and effective options), per-stage timings, and gate states (pass, warn, fail, skipped).

Help

Frequently asked questions

Can I export PDF as well as EPUB?

Yes, with version 0.2.0 or newer, the pdf extra and Node/Puppeteer tools. Use mdbindery build --format pdf. EPUB remains the default. PDF reports live in reports/pdf/; EPUBCheck and Ace apply only to EPUB.

What makes mdbindery different from running pandoc directly?

mdbindery uses pandoc for conversion and adds a book workflow around it. It resolves chapter links and anchors, turns numeric reference definitions into visible reference lists, renders Mermaid diagrams, and converts wide tables into row cards for configured files. It also runs configured validation gates and records their results.

Does mdbindery support existing mdBook repositories?

Yes. When a folder contains book.toml and SUMMARY.md, mdbindery automatically reads the title, authors, description, and language from book.toml, takes the chapter reading order from SUMMARY.md, expands {{#include}} directives (with cycle and size limits), and strips hidden lines in Rust code blocks.

How can coding agents use mdbindery?

Point Claude Code, Codex, Cursor, or Antigravity at llms-full.txt and the two official skills in skills/mdbindery/SKILL.md and skills/mdbindery-prepare-repo/SKILL.md. The agent can run mdbindery check . --json check.json, fix reported findings by file and line number, and verify the final ebook with mdbindery build and mdbindery preview dist/<slug>.epub shots.

What do I need to install mdbindery?

The installers need no preinstalled Python, Java, or Node.js and no administrator rights. Linux and macOS need Bash, curl, tar, and standard checksum utilities; Windows needs PowerShell. Tools stay in your user directory. Local builds work offline once installation is complete.