← Back to Blog
pullmdclaude-codepwadockerMarch 29, 2026 · 5 min read

PullMD Part 2: From Spec to Running Container – Simply Explained

SPEC → TESTS FIRST → CONTAINER · RUNNINGAI-generated image
Editorial diagram: a glowing SPEC portal on the left, a 'TESTS FIRST' banner above four stacked test cards (NORMALIZE, FETCH, FALLBACK, INTEGRATION), then a CONTAINER panel on the right with a green RUNNING indicator; a small status panel bottom-left tracks TDD · REVIEW · GREEN.Editorial diagram: a glowing SPEC portal on the left, a 'TESTS FIRST' banner above four stacked test cards (NORMALIZE, FETCH, FALLBACK, INTEGRATION), then a CONTAINER panel on the right with a green RUNNING indicator; a small status panel bottom-left tracks TDD · REVIEW · GREEN.

In Part 1 I’d written down what PullMD should do. Architecture figured out, interfaces settled, comment format decided. A complete specification, basically a blueprint.

On the evening of March 2 I handed all of that to Claude Code. Claude Code is a piece of software you can talk to, and it writes program code in return. My expectation: it starts building the actual program. The part that calls Reddit, pulls out the text and turns it into clean Markdown. Markdown is a simple text format with structure but without the clutter.

What happened instead: it wrote four tests first. No server, no Reddit logic. Just tests.

What a test is

A test is a small verification rule. It defines in advance what the correct output should be for a given input.

Think of it like building a house. First you write down how tall the doors need to be and where the windows should go. Then you build. And at the end you check against the list.

Normally you build first and test afterwards. Here it was the other way round: the verification rules existed before a single line of the actual program did.

What the four tests checked

The tests covered exactly what would later make up PullMD’s architecture:

  • Are the Reddit addresses that go in cleaned up properly?
  • Can the tool fetch Reddit data? (Checked with sample data, without actually calling Reddit.)
  • Does the backup plan work if Reddit blocks the fast route?
  • Does the whole thing also work with a real Reddit call?

So the tests didn’t just describe “a tool that fetches Reddit.” They described a tool with several fallback stages that cleans up addresses first and keeps fast checks clearly separated from slow ones. The architecture was essentially settled before the actual coding began.

Why that wasn’t a coincidence

The logs from that night show what Claude Code actually did. It wasn’t one single big run. The work was split into a chain of several steps:

  1. The specification was broken into numbered tasks: “Task 1: set up the basics,” “Task 2: address cleanup,” “Task 3: resolve redirects” and so on.
  2. For each task a fresh helper was started. It only got its own task description, not the full picture.
  3. Every helper had a clear instruction: first write a test that fails. Then build just enough to make the test pass.
  4. After each task, another helper checked whether the result actually matched the specification.

The logs show fairly precisely what each helper was briefed with:

You are implementing Task 2: URL Normalization Module … with TDD

(TDD means “test-driven development”, the approach where you always write the test before the code.)

So this wasn’t a flash of insight from the assistant. The workflow itself enforced “tests first” in every single step.

The container

That same night the service moved into a container. In the software world, a container is a sealed package. The program runs inside it together with everything it needs. You can put a package like that on any server, and it runs right away without having to set up anything there first.

The container for PullMD was small and straightforward. It only had to do three things: fetch Reddit data, convert text, output the result.

On top of that came a configuration that tells the server: “Make the service reachable at a specific address and take care of the security certificate.” That’s the same setup I use for my other self-hosted services. Start the container, and it runs.

The phone version

The PWA (Progressive Web App, a website that behaves like a real app on the phone) was also part of that same night. And that’s exactly the part I’d originally built the whole thing for.

You install it, it gets its own icon on the home screen. The key thing here was the share menu. Once the PWA is installed, it shows up in the Android share menu, right where WhatsApp, Signal and the other apps normally sit.

A small entry in the PWA’s settings tells the phone: “When someone shares a link with me, accept it and start processing.” That’s all it takes.

In practice: open the Reddit app, pull up a post, tap “Share.” PullMD appears as a target. Tap it, wait a moment. Clean text on the screen. Copy button. Done.

The aha moment on the phone

I remember pretty well when it worked completely for the first time. I had a longer thread open in the Reddit app, on a topic I wanted to talk to Claude about. So I tapped “Share,” picked PullMD. And then the clean text was simply there.

No cookie banner, no sidebar. Just the post and the comments, indented by reply depth.

My first thought wasn’t “cool, it works.” It was more like: that’s a lot faster than I expected.

The old routine: copy the address, switch tabs, paste, wait. The new one: one tap in the share menu, and the text is there. That sounds like a few saved steps. In practice it’s exactly the difference between a tool you actually use and one where you think every time: ah, for that I’d have to go and …

Why the tests paid off

Over the following weeks the project kept growing. Every time something bigger changed, the tests caught it first. They showed which previously working cases a change would have quietly broken, before it ever reached the server.

Precisely because the verification rules weren’t stuck onto the finished program after the fact, they mapped the original architecture decisions fairly closely. They’d been created at the same time as the architecture.

What came next

After that the service just ran along quietly. Mostly on the phone, and for now only for me.

What was written down nowhere the whole time: what you can actually call on the thing.

→ PullMD Part 3: The API, and How Reddit Became Any URL


Part 2 of 15 in the PullMD series.

← PullMD Part 1: Ctrl+A and the Junk Context | PullMD Part 3: The API, and How Reddit Became Any URL →

Comments

Commenting takes an email confirmation or a GitHub login. Comments run on my own server, not on an ad provider's — details in the privacy policy.