field notes · 18 august 2026
You do not need Python to turn Markdown into a PDF
What a command-line document converter is supposed to be
Most “free document converter” pages are the same product with a new coat of paint. You upload a file. A server you do not control writes a PDF. Maybe you get three conversions a day. Maybe the marketing copy says “private.” The file still left your machine.
docgen-cli is the other shape. It is a local document converter you run next to git. Markdown, JSON, CSV, or a pipe goes in. PDF, Word (DOCX), Excel (XLSX), or HTML comes out. One static binary. The convert step is a few milliseconds. This website does not see the file, because this website cannot convert anything. It is a poster. The compiler lives on your PATH.
If you already know the punchline, skip to the commands. Markdown to PDF, Markdown to Word, JSON or CSV to Excel. Everyone else: here is why this exists, what it costs, and why it is written in Rust instead of wrapping Chrome.
The tax is not the PDF. The tax is the script.
Ask Claude Code, Codex, Cursor, or Grok for a report. They do not reach for a compiler. They write a “small” Python script. Then they pip install reportlab, or WeasyPrint, or python-docx, or pandas plus openpyxl. Then a wheel fails. Then they retry. Then they debug A4. You paid for all of that so a table could have the wrong page size.
That loop is typical, not a guarantee — see the disclaimer — but you have watched it. A few thousand tokens, thirty seconds to a few minutes, and a file that still is not on disk. The convert itself was never the expensive part. The model writing a PDF library was.
docgen inverts that. The model writes Markdown (or hands you JSON). The binary writes the file. Token cost is whatever it takes to call the tool: tens of tokens, not a 3,000-token therapy session with cffi. Runtime cost of the binary is electricity. $0 to run. No per-file fee. No “upgrade for batch.”
If you are counting dollars: keep the $20 of fast requests for thinking. Do not spend them installing a typesetting stack the agent will throw away next session.
Markdown to PDF. Markdown to Word. JSON to Excel.
Three jobs show up over and over. They are first-class, not afterthoughts.
Markdown to PDF from the command line — skip WeasyPrint, reportlab, and headless Chrome:
docgen convert report.md -o report.pdf --theme modern-executive
Headings, lists, tables, quotes, fenced code. Pick a theme instead of debugging print CSS. The full walkthrough is the Markdown to PDF CLI guide.
Markdown to Word in the terminal — a real .docx, no Microsoft Word required to generate it:
docgen convert spec.md -o spec.docx --theme tech-spec
Open the result in Word, Google Docs, or LibreOffice like any other document. Details: Markdown to DOCX.
JSON to Excel and CSV to XLSX without standing up pandas:
docgen convert sales.json -o sales.xlsx
Pipes work. CI works. An API dump becomes a sheet the PM can open. See JSON / CSV to Excel from the CLI.
Themes, if you care: modern-executive, tech-spec, minimal-paper, corporate-slate, dark-glass. Inputs also include TSV, --text, and stdin. git log -n 25 --oneline | docgen convert - -o changelog.docx is a valid sentence.
Privacy is not a banner. It is the architecture.
This is not an online PDF converter. There is no upload form. There is no conversion API on docgen.lol. The terminals on the homepage are scripted. If you paste a customer spec into a browser “free PDF” site, you have a different threat model than you think you do.
docgen runs on the machine that already has the file. Output stays on disk unless you pipe it somewhere. The project does not phone home. MCP inherits the filesystem the host agent already has — same trust boundary you already accepted when you installed Claude Code or Cursor. We do not want your Markdown. The privacy page is short because there is not much to confess. Fonts on this marketing site load from Google. That is the only third party on the poster, and it never sees a document.
If legal asks “where did the file go,” the honest answer is: it did not go anywhere.
Why Rust, not another Python wrapper
Python is a fine language. It is a terrible runtime to ask an agent to assemble under time pressure. reportlab, WeasyPrint, and python-docx are libraries. They need a matching interpreter, a working pip, system libraries, sometimes Cairo, sometimes a browser. The agent will get that wrong. You will watch it get that wrong.
Rust gives you a single static binary. No virtualenv. No “works on my laptop.” You copy one file onto macOS, Linux, or Windows and you have a local PDF generator. Peak memory during render is in the neighborhood of 12 MB. Convert latency is 1–4 ms on ordinary documents. Those numbers are the convert step, not the time the model spends writing Markdown. Do not quote them as a contract.
Rust is also why this can be an MCP server without dragging Node or Python into the agent’s sandbox. docgen mcp is the same binary. docgen init-ai writes the config so Claude Code, Codex, Cursor, Grok, and OpenCode stop inventing a stack. Structured errors come back as data. The model can recover in one shot instead of opening a second novel about UnicodeEncodeError.
Could someone wrap wkhtmltopdf and call it a day? Yes. Then you shipped Chrome. That is the opposite of a compiler.
Pandoc, WeasyPrint, reportlab, and the upload sites
Pandoc is a Swiss Army knife. If you already have a Pandoc pipeline you love, keep it. PDF from Pandoc often means a TeX live install or a browser engine. Fine for humans who meant to install that. Not fine as the thing an agent improvises at 11pm.
WeasyPrint is HTML to PDF in Python plus system libraries. reportlab is a drawing API. python-docx and openpyxl are the Word and Excel versions of the same story. They are not villains. They are the wrong default for “write this file and stop.”
Browser converters are a different product. Convenient for a flyer. Wrong for a spec that cannot leave the building. A command line PDF converter that never takes an upload is not a feature checkbox. It is the point.
docgen does not try to replace Pandoc’s entire universe of formats. It tries to be the missing built-in for the three files people actually ask agents for. More in the FAQ.
If the caller is a model, the interface is a tool
Humans can type docgen convert. Agents need a contract. That is why this is an MCP document converter, not just a CLI with a README. After install:
docgen init-ai
or start docgen mcp yourself. Tell the agent: write Markdown, call the tool, do not invent Python unless the tool returns an unsupported-feature error. Same rule for Excel dumps. Same rule for DOCX. The repository is how the next session finds it. Stars are not vanity here. They are how tools show up in the prompt.
Install once. Forget it exists.
macOS, Linux, Windows. Invoked as docgen, doc, or docgen-cli:
curl -fsSL https://raw.githubusercontent.com/0xkaizoku/docgen-cli/main/install.sh | sh
Then docgen init-ai if you use an agent. Then go back to work. License is protective free-use: run it, including commercial generation. Do not rebrand it as a competing clone. Terms and the repo LICENSE are the long version.
When you should not use this
If you need tracked-changes Word, form-filling, or a designer. If you already have a blessed Pandoc plus TeX pipeline in CI and nobody is asking an LLM to reinvent it. If the job is data analysis, not “turn this array into a file” — use pandas. docgen is a compiler with themes. It is not a publishing house.
If you want the short version of everything above: the agent is not a PDF library. Put a compiler on the PATH. Keep the file on disk. Keep the quota.
Home · FAQ · star the repo