openapi-changes sucks
My secret shame revealed

openapi-changes is a big pile of tangled shit, and I would avoid it for now. It works, but it’s janky-ass software.“

What a quote!

It’s not verbal bashing from a customer or a competitor - it’s my own.


openapi-changes sucks

Hearing someone bash your baby, insult your labor of love, or crush your creativity is never easy. And quite frankly, if we’re honest, it hurts.

“Your work is bad, and you are not worthy.”

It still triggers my impostor syndrome.

However, no one is saying this, it’s my own inner monologue.


No, but mate… it is bad.

Yeah, I know, the code really is bad.

I am self-aware enough to know when my work stinks. openapi-changes has a lot of promise, but misses the mark on too many points to be truly useful.

It does work, but the harder you look, the more holes appear.

The code is a tangled mess. I once had an engineer look at it, then slowly back away while making polite excuses. I don’t blame him. I didn’t have a design in mind when I started sketching the code. It just flowed like poetry as I wrote it.

The poem was horrible and confusing. Reading it back was painful.


But the internet liked it!

It had over a million downloads. It shows that the tool is valued and useful.

After stabilizing it and adding some early community feedback, I kind of just… ignored it and left it alone, that was a bad idea.

Bugs, Vulns, and Features - Oh My

Focused deeply on building out the core of the OpenAPI Doctor in 2025, I let openapi-changes rot. Software rots fast when you stop tending to it.

We call it ‘bit rot’ in the industry.


A glorified tech demo

The tool was really just a way to stress-test the core engine (libopenapi). It was never intended to end up in the form it was in. For one, the HTML report was built using an incompatible stack compared to the rest of the pb33f toolchain.

But that scratchy code laid the foundation for the rest of pb33f.

Building out the graph’s visual experience (and a companion tree) taught me everything there was to know about how it all worked. Once completed and shipped, it was time to start on the long-term vision.


A total rebuild of everything, everywhere, all at once

The OpenAPI Doctor implements the exact same explorer idea openapi-changes does, except for a few major differences.

  • It’s designed to be flexible against multiple model types.
  • We don’t use React anymore; we use web components at pb33f.
  • Except for ELK.js, it’s custom-built from the ground up.

ELK stands for Eclipse Layout Kernel. I kid you not, it’s a Java layout engine for Eclipse that was compiled to JS using GWT (Google Web Toolkit).

It took me over a damn year to get this thing right. It’s really hard to build a graphing engine and model that works across multiple interfaces and handles graphs composed of thousands of files.

An engine that would work with a document, or a change set, or both, or a subset of a model, something that could render in a TUI, markdown, or a web UI using SVG and HTML.

It may have looked like things were quiet with openapi-changes, but in reality, they were anything but. I was working on the following:

All at the same time, all of them connect together. The doctor library powers it all.


50GB of YAML

Can you imagine?

Shortly after deploying the OpenAPI Doctor, with the change detection features in preview in the fall of 2025, storage use started to skyrocket.

Hundreds of MB were being stored for power users, and that storage was growing daily.

The graphing was half-working, with data duplication everywhere, and the rendering engine was showing everything in the graph at once.

Not great, but not entirely terrible either.

As data use skyrocketed, some profiling was called for, and two issues jumped out immediately:

  • The graph was printing itself recursively with each node, and this compounded at scale (yikes)
  • 5x duplication when saving all files.

It forced me to spend days refining, tuning, fixing, testing, and hacking on this system, stabilizing it, reducing its footprint, and speeding up its rendering, ensuring it was accurate and, most importantly…

Useful as a tool for exploring the data.

It had to be right, otherwise there was no point in doing any of this work.


A stack of building blocks

In March 2026, pb33f very quietly released features and upgrades to the OpenAPI Doctor (that are all unannounced at the moment).

I’ll leave that content to another article.

But what is important is that it includes all of the machinery for the birth of new tools, as well as the rebirth of old ones.

Most importantly, the tuned and fixed graph/model/explorer combined with all the new change-rendering built for the OpenAPI Doctor, was now available for use. Ready to be reboxed into all sorts of useful tooling.


So many subsystems

One key item missing was a custom file revision system that allowed libopenapi to look up references across commits. This is something that was already developed for the OpenAPI Doctor to allow revisions to be tracked across repos or databases.

It’s key because without it, any parsing library has no idea what to do when it encounters a $ref (JSON Pointer Reference) to an external file that no longer exists in the file system.

A change made to a spec a year ago points to files that were moved or deleted a long time ago, without the parser knowing how to look up a reference from a specific Git commit in time when looking for that JSON pointer - you can’t build a time machine that spans across a file system that changes over time.

From the outside, it must have looked like openapi-changes had been abandoned, but on the inside, it had been consuming huge cycles of my brain for over a year.


Strangler Fig

Without announcing any of the new features, it was time to fix the rotting corpse I had left out in the sun.

There was no saving the codebase; most of it had already been rewritten upstream anyway.

It had to be a complete rewrite downstream as well.

It had to be backward-compatible with the old CLI, built on top of the existing capabilities, whilst also completely replacing them. This is kind of hard to do ‘in-place’, but there is an architectural technique I use that makes it easier.

The Strangler Fig pattern is something I use in these situations. Essentially, as the new system grows alongside the old while they both still operate, the new system gradually obscures the old, allowing it to be dismantled. The system stays operational while two codebases coexist.

Just before release, openapi-changes was running two feature sets in parallel. All the new code was prefixed with new-, which allowed me to perform detailed side-by-side comparisons of the features.


Harder, Better, Faster, Stronger

It is materially better in every direction that matters. More results, better organized, correct multi-file support and more control.

The HTML Report is a personal work of art. One self-contained file, all you can eat!

All the interfaces are covered! HTML, Markdown, JSON, and Terminal UI.

A whole new terminal UI experience that aligns with vacuum

The Console TUI

The console terminal UI is beautiful and now aligned with the new vacuum console, making it far easier to navigate huge change sets in the terminal.

Zoom into a change and see it rendered in full context of the specification

The visual style and the architecture have been aligned with vacuum and the two can now work together.

Zip about large change sets over many revisions and see how the spec has changed

The Terminal Summary

The summary is richer now, with a much more detailed view of the change tree and overall totals.

Render the change tree with meaningful output, instead of abstract change counts

A quick way to see what has changed

Now it’s an easy to consume overview of the changes and where they are

The Markdown Report

The markdown-report has gone from basic output to something properly useful. It now produces a real changelog for a changeset, not just a dump of information.

Rendered in my IDE, because why not?

Pièce de résistance

The best part is the all-new html-report.

It folds in the timeline, explorer, diffing and markdown reporting into a single experience, whether comparing a simple left/right pair or tracking changes over time.

A beautiful, purpose built diffing interface, specifically for OpenAPI

Expand and explore visually, click nodes, click the tree, see the change rendered and a focused diff in the right hand panel.

Explore changes visually, using the explorer and rendering components from the OpenAPI Doctor

A new timeline experience that mirrors OpenAPI Doctor

The doctor timeline has been tuned for moving across commits in a git history

Diff with focus, switch to a full file view, explore the change set visually, inspect individual objects with targeted diffs and rendered changes, and view the changelog as HTML with optional list-based views.

Focused diffing for targeted specific changes in the contract

The markdown report is also available as a change report, rendered into HTML and styled.

The markdown-report is rendered into HTML inside the HTML report. A report inception

I think it looks great, and it ships with three pb33f themes built in across the product line: Dark Mode (pb33f), Roger Mode (light / monochrome), and Tektronix (retro green phosphor).

Roger mode is a color blind friendly monochrome black and white e-ink style theme

Tektronix mode makes me want to shout ‘I’m in.’

Tektronix is a fun retro 1970’s green phosphor theme. I think it looks awesome

v0.2 of openapi-changes is now available. Upgrade using whatever method you originally used to install it, and the new experience is ready to go.

If you have never used it, what a great time to give it a try!


All new license

I’ve moved openapi-changes to Apache 2. It’s no longer GPL!

Try it out for yourself.

Don’t take my word for it.