← Back to Blog

Day 118: v0.5.8, and a README That Earns the Star

Some release days are a single big feature with a bow on it. Today wasn’t that. v0.5.8 was a convergence (code, docs, and marketing all landing in the same window), and the thing I keep coming back to, hours after the tag went out, isn’t any of the code. It’s the README. Because the README is the storefront, and I’d spent a hundred and seventeen days not really looking at mine.

I’ll get to that. But the code first, because there was a lot of it, and some of it was the good kind of boring: the kind where you fix something that was quietly wrong and nobody ever has to know it was.

The code: lossless tokens, a broken PDF tool, and a security sweep

The headline change is PR #504: lossless per-turn token accounting from the trajectory. The old accounting was lossy: it summed things up in a way that could drift from what actually happened in a turn. The rebuild reads the trajectory and counts what’s really there, per turn, without rounding the truth away. Token counts are one of those numbers a self-hosted operator has to be able to trust completely, because they feed cost, budgets, and compaction decisions downstream. A number that’s “about right” is worse than no number, because you stop checking it.

PR #500 is the one that closes a real bug a user could actually hit. OpenClaw’s built-in PDF tool is broken, and OpenClaw is a third-party runtime I don’t control; I only own the openclaw-node SDK that talks to it. So rather than wait on an upstream fix, I rerouted PDF attachments through our own pinchy_read path, which already knew how to read them. Attach a PDF, the agent reads it. That’s the whole user-facing story, and it should have been true all along. The part that stings is that the capability was sitting right there in pinchy_read the whole time: the fix was choosing our working path over the broken inherited one, not building anything new.

Two more guardrails. PR #496 disables the native pre-compaction memory flush, runtime behaviour I’d rather have off than fighting me at the edge of a turn. And PR #497 gates a known-bad model family out of the agent model picker and the write path. The two-place fix matters: keeping a bad model out of the picker is cosmetic if a stored config can still smuggle it in through the back door. A blocklist that only blocks the front door isn’t a blocklist, it’s a suggestion.

And then the unglamorous half-day: a security-dependency sweep. PR #505 cleared ten OSV advisories at once (js-yaml, vite, @babel/core, protobufjs, tar), with #494 taking esbuild and #506 taking dompurify. None of these are exciting. All of them are the rent you pay to ship a self-hosted product that an enterprise security team will eventually run a scanner against. A clean advisory report is a feature, even though no user will ever see it.

The README was underselling, and partly lying

Here’s the part I didn’t expect to be the emotional center of a release day.

The README is the first thing a GitHub visitor reads. Before the docs, before the website, before a single line of code, they land on the repo, and the README decides whether they keep reading or close the tab. Mine had two problems, and they pulled in opposite directions.

The first: it was underselling. A hundred and seventeen days of work (the per-agent tool allow-list that starts at zero tools, the tamper-evident audit trail, Telegram, Odoo, the local-model story), and the README read like a sleepy internal note. It described features without ever saying why they mattered. It buried the thing that makes Pinchy worth running.

The second problem was worse, and it’s the one that kept me honest: parts of it were describing things the product doesn’t do. Not maliciously: README rot is just entropy. You write a line early, the product moves, the line stays. But a README that claims a capability the code doesn’t have isn’t aspirational, it’s wrong. It’s the exact failure mode this blog keeps circling back to: “I built it” and “it works in production” are different claims, and a README is where I’d quietly conflated them for an audience of strangers.

PR #498 was the rewrite: badges, a hero, a comparison table, a quick-start, a star-history chart. The temptation in a marketing overhaul is to reach for the buzzword shelf: to make it sing by making it lie a little louder. I tried very hard not to. Every line in the new README is something the code actually does today: web and Telegram channels, not Slack; the allow-list that defaults to nothing; the audit trail you can verify; the flat Pro price, not a per-seat tariff. The comparison table doesn’t flatter us where we don’t deserve it, the same posture as the comparison pages from Day 117. Writing copy that’s genuinely compelling and can’t be falsified is harder than writing either one alone. It’s the same discipline as the code: the constraint isn’t “make it impressive,” it’s “make it true, then make it impressive within that.”

One source of truth, on the website too

The docs-and-marketing side of the day had its own small cleanup. PR #499 and #502 added a glossary: an AI-agent concept hub with ten definition pages aimed at the data-void queries people actually type but that nobody has written a straight answer for. Citable, plain, no funnel hidden in the prose.

PR #503 fixed something I should have caught sooner: release notes were duplicated. They lived on GitHub Releases and got hand-copied onto the website’s Releases page, which means they drifted, which means one of the two was always slightly wrong. Now the website pulls release notes live from GitHub Releases. One source of truth. The same instinct as the lossless token accounting, honestly: stop maintaining a second copy of a number that can disagree with the first.

Day 118

The code and the README looked like two different jobs this morning. By evening they’d collapsed into the same one. The broken PDF tool was a place where the product quietly didn’t do what a user would assume. The README was a place where the description quietly didn’t match what the product does. Both are the same crack, just on opposite sides of the glass: one in the thing, one in the story about the thing.

I’ve gotten reasonably disciplined about not lying in code; the tests don’t let me. The uncomfortable lesson of v0.5.8 is that the README has no tests. Nobody fails CI for a sentence that used to be true. The storefront drifts on its own, and the only thing that catches it is going back to read it as a skeptic would, which is exactly the visitor I’m asking to spend a star. If you want the longer version of how I think about running an agent runtime you don’t control, that’s the OpenClaw security guide. It’s written to the same rule the README finally is: nothing in it that the code won’t back up.

← Day 117: Comparison Pages That Don't Flatter Us Day 119: Auditing My Own Marketing for Lies →

Pinchy is open source and ready to deploy. Clone the repo, run docker compose up, and your first agent is live in minutes.