md-to-pdf

Caution

Raw Markdown exports look raw. Most PDF exporters produce plain text with no styling, no code highlighting, and broken tables. Sharing a PDF that looks like a terminal dump is worse than sharing nothing.

Tip

Two engines, one command. reportlab requires zero system dependencies — install and go. weasyprint adds full CSS, syntax highlighting, and pixel-perfect tables when quality matters. LLM preprocessing lets you strip or rewrite sections before conversion.

Quick reference

FieldValue
Command/brewdoc:md-to-pdf
Arguments<file.md> [--engine name] ["prompt"] | styles | test | help
Modelsonnet
ToolsRead, Write, Edit, Bash, Glob, Grep, AskUserQuestion

When to use

  • Share a deliverable — convert a SPEC.md or PLAN.md to PDF before a review meeting
  • Archive a report — turn a daily/weekly markdown report into a permanent PDF snapshot
  • Preprocess before export — strip internal sections, rewrite headings, restructure — then convert
  • Verify engine setup — run test mode to confirm your engine renders correctly end-to-end
  • Customize appearance — use styles mode once to set page size, color scheme, and code theme

Examples

# Basic conversion — output lands next to the source file
/brewdoc:md-to-pdf README.md

# Force a specific engine for this run
/brewdoc:md-to-pdf report.md --engine weasyprint

# LLM preprocessing before conversion
/brewdoc:md-to-pdf spec.md "remove the Internal Notes section, rewrite all headings as imperatives"

# Verify engine installation
/brewdoc:md-to-pdf test

# Configure page size, colors, code theme once
/brewdoc:md-to-pdf styles

Engines

Featurereportlabweasyprint
Installationpip onlypip + brew (system deps)
QualityGoodExcellent
SpeedFastModerate
ImagesBasicFull
CSS stylingNoYes
Code highlightingNoYes (Pygments)
Best forQuick text docsTables, code, complex layout

Engine is saved to .claude/md-to-pdf.config.json after first selection. Override any run with --engine.

Flow

  1. Parse arguments

    Detects mode from arguments — HELP, STYLES, TEST, CONVERT, or CONVERT+PROMPT. Extracts —engine flag if present.

  2. Dependency check

    Runs check_deps.sh check ENGINE. If packages are missing, offers three options: install the current engine, switch to the other engine, or cancel. Installation is automatic on user consent.

  3. Engine selection

    Reads saved config from project (.claude/md-to-pdf.config.json) or global (~/.claude/md-to-pdf.config.json). First run with no config triggers an interactive comparison prompt. Selection is written to project config.

  4. LLM preprocessing (CONVERT+PROMPT only)

    Reads the source file, applies the quoted instruction — delete sections, rewrite headings, restructure — writes result to a temp file. The temp file feeds the converter; original stays untouched.

  5. Convert

    Runs md_to_pdf.py INPUT OUTPUT —engine ENGINE. On failure, reads error output, attempts one auto-fix, and retries. If still failing, reports the full error and stops.

  6. Report results

    Prints a summary table: source path, output path, page count, file size, engine used, and preprocessing summary (or none).

Customization & internals

Styles mode

Run /brewdoc:md-to-pdf styles for four interactive questions:

ParameterOptionsDefault
Page sizeA4, Letter, LegalA4
Color schemeDefault blue (#1a3a5c), Dark (#2d3748), Custom hexDefault blue
Code theme (weasyprint)github, monokai, friendly, solarized-dark, solarized-lightgithub
FooterPage {page} of {total}, {page}/{total}, DisabledPage {page} of {total}

Config is saved to .claude/md-to-pdf.config.json. Example:

{
  "engine": "weasyprint",
  "pygments_theme": "monokai"
}

Config lookup order

  1. --engine flag on the command line (always wins)
  2. Project config: .claude/md-to-pdf.config.json
  3. Global config: &#126;/.claude/md-to-pdf.config.json
  4. Default: reportlab

Test mode

/brewdoc:md-to-pdf test converts the bundled test-all-elements.md to /tmp/md-to-pdf-test-ENGINE.pdf. The test file exercises all supported Markdown elements — headings, tables, code blocks, images, lists — so you can visually verify engine output before converting real files.

CONVERT+PROMPT temp file lifecycle

The temp file is named {original_dir}/.tmp_{original_name}.md. It is deleted immediately after conversion regardless of success or failure. The original source file is never modified.

🚀

Publish skill

Push generated PDFs (and other artifacts) to remote destinations via the publish skill.

🔗

GitHub source

Source code, scripts, and bundled test file.

📄

Brewdoc overview

All brewdoc skills — auto-sync, memory, my-claude, md-to-pdf, and more.

Updating plugins

Use /brewtools:plugin-update to check and update the brewcode plugin suite in one command. See the FAQ for details.