Claude Is Not a Compiler

✨ Check out this must-read post from Hacker News 📖

📂 **Category**:

💡 **What You’ll Learn**:

In early 2025, I wrote Is Claude a Compiler? At the time, my answer was: I don’t know.

I’m now pretty sure the answer is “no, that’s a category error, it’s better than a compiler.” But this requires a bit of unpacking.

Computer programs are notoriously intricate and finicky. A program operates at an extreme level of precision. There is no “wave hands” CPU instruction. High-level goals, meanwhile, are deeply underspecified.

In a highly stylized view of the world, software gets built in layers, each one adding specification and hiding “unnecessary” detail. Vision becomes strategy, product plans become coding plans, code becomes binaries. Each step is handled by a different role: executive, VP, PM, architect, engineer, compiler. 

Critically, every step involves making lots of decisions. That’s what it means to increase the level of specification. (This is why one of my two key metrics for hiring engineers is judgment. The other is comity.)

The bottom layer, from source code to binary, is what a compiler does. Compilers make lots of decisions! Inlining, register allocation, whether to emit warnings or reject a program outright. And these decisions matter: They drive performance, system stability, predictability, and failure modes. A compiler engineer’s job is to arrange for the compiler to make consistently good decisions.

A good, trusted compiler frees a software engineer from having to make these decisions. Most engineers have little idea how compilers work; they don’t need to in order to be effective. 

In 2025, we operated in a world where we used LLMs to generate smallish chunks of code. In this mental model, a coding agent might slot in as a new layer between a software engineer and a traditional compiler. It “compiles” natural language to code, making decisions so the engineer doesn’t have to. Its value is proportional to its reliability and the scale of the decisions it can make.

The thing is, this highly stylized view of the world is false. Abstractions leak and layers rub. And even if they didn’t, we’d poke holes in them anyway.

Working across layers is extremely valuable; mechanical sympathy matters.

Part of how the Empire State Building was constructed in under a year and under budget (!!) was by systematically working across layers. For example, when deciding about the exterior chrome-nickel steel cladding:

Neither architects, builders nor subcontractors felt competent to deal with this complicated technical problem of construction without full consultation. Accordingly, after full preliminary discussion, an all-inclusive meeting was called which was attended by representatives of the owner, the architects and builders, the subcontractors rolling the material, the metal workers who were to fabricate and those who were to erect it, and the inspectors who were to test all sheets at the several stages of preparation.

This sounds really obvious when you say it out loud.

And yet we systematically fail at this in practice. I can only imagine the delight of the metal workers who had an opportunity to guide the design toward something that wasn’t slow and miserable to work on.

Part of the reason we fail is ignorance of what is even worth asking about. There’s a reason that the best executives have deep knowledge of their industry. I also suspect that some of it is dismissiveness (“What could a line metalworker have to tell me?”). But a big chunk is also communication and organizational overhead. Layers exist for a reason—information hiding enables organizational scaling.

Claude is better than a compiler because it can work vertically across the stack. LLMs now talk strategy, product, architecture, code, and machine code. It can’t (yet?) do most individual tasks as well as an experienced, dedicated human, but it can do all of them, without having to schedule meetings or ask permission.

Here’s a concrete example.

exe.dev VMs have nice domain names: vm-name.exe.xyz. When we start a new VM, we add a CNAME entry or three. Easy, right?

But our VMs start fast, so fast that even if we created the DNS entries before creating the VM, our users still had to sit around waiting for DNS to propagate, which occasionally took minutes, not seconds.

We did the obvious thing: We wrote our own DNS server, so that DNS always immediately matched the source of truth. And life was good.

But latency matters, so we added regions. And just like that, DNS became the long pole again, because all DNS was served out of Oregon. Also, deployments caused tiny DNS outages. To fix this, all we needed now was a geographically distributed but fully consistent DNS server.

We did what a sensible engineer does when faced with a hard problem: cheat. We vibe-engineered a distributed DNS server tuned to our specific needs.

The goals were clear: Reduce latency for users far from Oregon and increase uptime resiliency. But the rest was not. We had to figure out everything from the exact behavior we wanted (particularly under various failure conditions), to how it fit into our overall company plans, to the architecture that could best achieve those goals, straight through down to the fine implementation details.

We hashed out the highest level strategic and architectural decisions in person. We’d make a fairly general-purpose DNS server and layer on our particular behavioral tweaks, use a hub-and-spoke model, use an append-only replication strategy, and have persistence at the edges.

All that was left was to actually build it.

I had LLMs research standard designs for distributed DNS systems, teach me about the guts and quirks of DNS, point out historic security failings, explore alternative implementation strategies (AXFR/IXFR? no thanks), research open source offerings, game out failure modes, and plan testing strategies.

Once I had an initial sketch of a design that seemed promising, I prompted multiple concurrent agent loops into building the entire thing, including tests and adversarial code review. They raised a bunch of questions—at every level of detail, from major structural approaches down to line-level code concerns. As I answered them (or reverted answers that generated regret), I slowly converted what I had learned into very terse written guidance, codifying decisions that proved to be important.

Then I asked new agents to compare the completed implementations and look for interesting deviations. It was shocking how many important decisions the agents never asked about but simply made—and made differently.

Here’s an example. Replication uses the fairly obvious approach: Catch up by asking for everything since the last known entry, and then long poll for new entries. There’s one ugly twist: database rollbacks. Rare, but they do happen, and they break the “append-only” contract.

The agents noticed this, and they solved it in wildly different ways. The design I ultimately settled on was to give every row a “timeline” field, as in “which timeline are you living in?” These are randomly generated, and every sync request for “entries since row N” includes the edge server’s timeline value for row N. If there’s a timeline mismatch, we know that history has been altered and fall back to a full clean re-sync.

There were also obvious style differences between the systems built by different agents. Claude and Codex both agreed that Claude created a more elegant system but that Codex was more thorough.

I worked through the list of major identified divergences, experimented, and then added more written guidance.

Then I repeated that entire differential spec analysis process, twice. I know my aphorisms.

Plan to throw one away; you will, anyhow.

— Fred Brooks

If you plan to throw one away, you will throw away two.

— Craig Zerouni

By the time I was ready to build a keeper, I had accumulated a scar-tissue document that was empirically sufficient to guide an agent through most of the important decisions, at every layer, ranging from high level goals through architecture down to the occasional low level detail, such as the exact shape of the data type for load-bearing concurrent caches.

The final system included unit tests, end-to-end tests, a shadow-mode for de-risking prod rollout, and a terse written-by-and-for-agents doc suite.

This cumulatively took about a week of my attention. I read a vanishingly small amount of the actual code.

At the end of that, I presented the solution to the team. I planned to launch the server and then go on vacation. As my colleagues peppered me with questions—”How does X work? What happens in condition Y?”—I found I could answer all of them confidently. (And I did go on that vacation. Number of DNS incidents a month later: 0.)

Claude wasn’t just a compiler here. I never handed off a task and let an agent make a bunch of decisions in order to reduce it to practice. That’s vibe-coding.

Rather, Claude was a vertically integrated resource, a multi-compiler. Its ability to work across the stack accelerated and augmented my ability to make a bunch of decisions at different levels, including about which decisions were important. (Most individual lines of code don’t make that cut.) That’s vibe-engineering.

I’d say that, in all the ways that matter, I understand the code. Sure, if I had to hand-edit it now, there’d be a serious learning curve. But I won’t have to. And more importantly, I can reason about the system, share perspectives with my colleagues, and guide agents on future work. And there’s an enduring artifact that encapsulates the central, intentional aspects of the design that were important enough to record, across all layers, and should thus survive bug fixes and code churn.

One of the questions of this era is: What do software engineers need to understand about the systems they work on?

Well-chosen layers provide understanding. Fundamental laws of physics appear all-encompassing, but they’re inferior to classical mechanics for explaining why it’s better to be in a bus than a car in an accident.

Some software layers are dying, because they provide convenience, but not extra insight. (Sorry, Tailwind. I loved you.) But software layers that enable us to express important decisions in a comprehensible way? Those will stay.

We are shifting more of our attention up the stack, but without fully relinquishing the lower layers. Agents are not a free pass to hand off all understanding of the deeper layers of a system. Most of the Go standard library is written in Go, but a few key routines are written in assembly. You can’t rely on the compiler there.

Software engineers are being stretched. It’s exhilarating and exhausting. What’s becoming clear, though, is that in the near future, vibe-engineering is just…engineering.

💬 **What’s your take?**
Share your thoughts in the comments below!

#️⃣ **#Claude #Compiler**

🕒 **Posted on**: 1784647279

🌟 **Want more?** Click here for more info! 🌟

By

Leave a Reply

Your email address will not be published. Required fields are marked *