Markdown Print: One-Command PDF Rendering and Printing from the Terminal

Two Claude Code skills that convert local Markdown files to A4 PDFs and send them to a Brother laser printer, all from a single voice command.

Why Does Printing a Markdown File Require Twelve Clicks?

Printing a Markdown file should not require opening a browser, pasting into Google Docs, adjusting margins, and hitting Ctrl+P. But that's what most people do. In a household where printed lesson plans, checklists, and reference sheets are part of the daily routine, that friction adds up fast. I was doing this dance three or four times a day before I decided to automate it away.

The goal was simple: say "print this file" and have paper come out of the printer. No intermediate steps. No print dialogs. No margin fiddling.

What the Skills Do

The project includes two nearly identical skills — markdown-print and print-markdown — that handle Markdown-to-printer conversion. They exist as separate entry points for natural language flexibility (some people say "print this markdown" and others say "send this to the printer"), but they share the same pipeline.

The skill validates the file path (expanding ~ and confirming the file exists), checks whether the Markdown file already has YAML front-matter with PDF options, and if not, prepends a standard block — A4 format, 20mm margins on all sides, print background enabled. Then it runs npx md-to-pdf, which uses headless Chromium via Puppeteer to render the Markdown as a styled PDF with GitHub-style syntax highlighting for code blocks. Finally, it sends the PDF to our Brother HL-L2360D via lp with A4 media and fit-to-page options, and reports the print job ID.

Start to finish, about ten seconds for a typical document. Most of that is Chromium rendering.

Options

Natural language modifiers adjust the output without touching any config:

  • "print 2 copies" → adds -n 2 to the lp command
  • "duplex" or "double-sided" → adds -o sides=two-sided-long-edge
  • "landscape" → sets landscape: true in the front-matter and passes -o landscape to lp
  • "no margins" → reduces all margins to 5mm for near-full-bleed output
  • "just save the PDF" → skips the print step entirely, useful for reviewing before committing to paper

Things I Learned the Hard Way

Never modify the original file. Early versions of the skill added front-matter directly to the source Markdown. I discovered this was a terrible idea when a git diff showed 15 files with unexplained YAML headers. Now the skill always writes a temporary copy to /tmp/ before adding front-matter. Your source Markdown is never touched.

First run is slow. The first npx md-to-pdf invocation downloads Chromium — about 170 MB. I didn't account for this initially and spent a confused few minutes watching the skill appear to hang. Subsequent runs are fast.

Relative image paths break. If your Markdown references images with relative paths and you copy it to /tmp/, those paths won't resolve. The skill passes --basedir pointing to the original file's directory when needed. This one took a while to diagnose because the PDF would render fine except for blank rectangles where images should be.

Long documents just work. CSS @page rules handle pagination automatically — no manual page breaks needed. I was pleasantly surprised by this. A 12-page lesson plan paginates cleanly without any intervention.

Role in the Ecosystem

These skills are the final step in several pipelines. The daily-lesson-plans skill produces Markdown; notion-printable-markdown produces Markdown; both feed into markdown-print for the last mile to paper. They also work standalone for any local .md file you want printed.

The convention that made this all click: every Markdown file in our system includes A4 PDF front-matter by default. Once that standard is in place, any file is one command away from paper. The skill doesn't need to know where the file came from or what it contains — it just needs to know where the printer is.