← writing Build journal · 2026-07-03

The cheapest file is a Markdown file

I kept handing files to LLM agents a PDF here, a spreadsheet there and kept paying more than needed for my desired results. Not in dollars I noticed at the time, but in tokens: the little units of text a model charges you for, both to read your stuff and to answer. And a raw file is an expensive way to say something simple.

So I built a small service that takes any file you throw at it and hands back plain Markdown. It's live on my homelab, I use it from a browser, and my agents call it before they do their real work. This is the build log for it i guess a little light on the code, a little more of why the whole thing is mostly other people's code.

Why a PDF is expensive and Markdown isn't

A model doesn't read a file the way you do. A PDF or a Word document is a container underneath the words there's a pile of structure describing fonts, positions, styling, embedded metadata, all the machinery that makes it look like a document on screen. To the model, a lot of that turns into tokens too. You're paying to ship the formatting, and the model has to wade through it to find the two sentences you actually cared about.

Markdown throws all of that away and keeps the part that carries meaning: the headings, the lists, the tables, the words. Same content, a fraction of the tokens. A hefty report that lands as thousands of tokens of PDF becomes a few hundred tokens of clean text — and the model reasons better over the clean version, because there's less noise between it and the point, the substance.

The whole idea in one line. Convert the file to Markdown before the model sees it. You spend less, and the model thinks straighter. That's it. Everything else is me running around with an idea, tools and some tape.

The best code is the code you don't write

My first instinct was to figure out how to parse a PDF. My second, better instinct was to remember that smartermroe capable people exist. People who had already spent years doing that so I didn't have to. And I found something, Microsoft maintains a library called MarkItDown whose entire job is turning files — PDF, Word, PowerPoint, Excel, HTML, audio, CSV, a dozen more — into Markdown. It's very good, and it's free.

So I didn't build a converter. I built a thin wrapper around one: a little web page you can drag files onto, and an address my agents can send files to. My aim was just to make a good tool out there even more convenient, and then address the one thing it couldn't do.

The one thing it couldn't do: read a picture

markitdown reads text that's already text. Give it a scanned document a photo of a page, a receipt and it comes back with almost nothing, because to a computer that "page" is just an image. There are no words in there yet. Pulling words out of a picture is a separate, genuinely hard problem with its own name: OCR, Optical Character Recognition.

Not my wheel to reinvent, never forget smarter people out there. This is one of the most-worked-on problems in computing. I reached for two mature open-source tools and let them do the reading:

  • Tesseract, a decades-old OCR engine, handles loose images.
  • OCRmyPDF handles scanned PDFs, it quietly reads the pages and stitches a real text layer back into the file, so markitdown can then read it like any normal document.

Made sure this only wakes up when it's needed. A normal text file sails straight through untouched; only a scan or an image gets the slower OCR treatment. You don't pay for it(with your time) unless you use it.

Where I drew the line honestly. These tools read printed text well and handwriting badly — sometimes not at all. Reading handwriting reliably needs a heavier kind of AI model and a beefier machine than my little 2011 always-on laptop. So rather yeah there is a warning in the interface, a note in the docs that says " handwriting = ¯\(ツ)/¯ ". I know what this tool can't do so lowering expectations before disappointment.

Built for me, and for my agents talking to each other

There are two kinds of visitor here. There's me, in a browser, who wants to log in, drag a file, and read the result. And there are my agents, little AI programs running across different projects — who don't have hands to log in with. They need to knock on the door with a key instead of a password.

So the service has both doors. I get a normal login. Each agent gets a secret key it sends along with its request, and one line is enough for it to get Markdown back:

curl -H "X-API-Key: my-secret-key" \
     -F "files=@report.pdf" \
     https://markdown.mydomain/api/convert

That's the part that was kinda important to me. When one of my agents needs to hand a messy file to another, it doesn't ship the whole expensive PDF — it drops it here first and passes on the lean Markdown. The service becomes a shared little utility my tools use to talk to each other more cheaply. I'm not in the loop at all; I put the vending machine there no more interaction needed while raking in benifits from it's use ;) .

What I actually built

Counting honestly, I wrote very little. The conversion is Microsoft's. The OCR is Tesseract's and OCRmyPDF's. The part that's mine is the tape: a small web app, two ways in, a bit of logic that decides when a file needs OCR, and the plumbing to run it on my own hardware behind a secure tunnel so I can reach it from anywhere.

And I think that's the actual lesson, the one I keep relearning on these projects. A useful tool isn't always a clever new invention. Very often it's a handful of excellent existing tools, pointed at one specific job, wrapped so a human or a machine can use them without thinking . Fewer tokens, borrowed wheels, a steering column I bolted on myself.

Code: github.com/Daisentaur/local-markdown ↗
← back to writing