Vibe Coding

After way too long away from this blog, I’m back, and now with a co-author (🐱).

So where have I been? Barcelona. I’ve spent the last four years at Apple, where I’m a lead machine learning engineer working on foundation models, on-device inference, and the search systems behind Spotlight and Siri. The team was full of ridiculously sharp and genuinely kind people. The work itself ran the full stack, from optimizing transformer models that actually fit on a phone, to batch inference infrastructure, to the LLM stack from pre-training through post-training.

One of the highlights was getting to present some of that work to Tim Cook and the AI/ML leadership at the Steve Jobs Theater. The project was about making Siri more performant for real-world use cases, which is a much harder problem than it sounds when the constraints are mobile hardware and a battery you can’t drain.

The reason I haven’t posted anything here in years is that Apple is very, very secretive. When your work has a chance of shipping to millions of devices, you get used to talking about it less, not more.

Right now I’m on sabbatical and heading to something I’ve wanted to do for a long time: the Recurse Center in NYC for the S2’25 batch. If you haven’t heard of it, RC is a self-directed programming retreat where you spend 6 to 12 weeks working on whatever excites you, surrounded by other programmers doing the same. No OKRs, no sprint planning, no roadmap, just learning and building.

I’m planning to spend my time on high-performance AI reasoning algorithms, get more serious about functional programming, and finally work on a few projects that have been sitting in my notes for years. The most exciting part of the whole thing is just being around other people who care about programming for its own sake again.

Vibe coding

So, vibe coding. If you haven’t heard of it yet, you will. Andrej Karpathy coined the term for the way of programming where you let an AI generate all your code while you “fully give in to the vibes, embrace exponentials, and forget that the code even exists.”

Vibe coding meme GIF

Tools like Cursor running Claude Sonnet have gotten good enough that you can describe what you want in natural language, hit “Accept All” on whatever the model proposes, and somehow end up with software that actually runs. When something breaks, you copy-paste the error back into the model and hope it fixes itself.

Debugging struggle

I’ll be honest about my own use of these tools. I use them every day. GitHub Copilot’s autocomplete is a real productivity boost, and I’ll happily ask Claude to write a regex for me, generate boilerplate, or help me trace through a confusing stack trace. The thing I won’t do is let it drive the whole project.

Why vibe coding bothers me

The first reason is that you stop understanding your own code. When I write something, even with AI help, I’m still thinking about architecture, performance, edge cases, and how the parts hold together. Vibe coding skips all of that. You ship a black box. That might be fine for a weekend project. It is genuinely scary for anything that has to keep running for more than a week.

Code confusion

The second reason is that debugging falls apart. AI-generated code will eventually break in production, the same way every piece of software does. If you don’t understand what it does, your debugging strategy collapses to “ask the AI and hope,” which is closer to gambling than engineering.

This is fine fire

The third reason is that you don’t actually learn anything. Programming is mostly the work of building accurate mental models of systems, and that’s a skill that develops through use. If you outsource the model-building to an AI, the skill never develops. You become dependent on a tool that may not be there in the future, may not understand your specific problem when it matters, and definitely doesn’t help you grow as an engineer.

There are some impressive demos out there. Pieter Levels has been building games entirely through prompting, for example. When you look closely at those projects, though, you tend to find obvious security issues or behaviors that only hold up in narrow scenarios.

Security vulnerability detected

Most real software work is the messy stuff: navigating an existing codebase, working within constraints you didn’t choose, collaborating with a team, making tradeoffs that involve people. Those are human problems, and they need context and judgment that an autoregressive model isn’t going to give you.

AI coding tools can be great when you use them deliberately. The productivity gains from autocomplete, boilerplate generation, and debugging support are real, and I’d be silly to ignore them. There’s a meaningful difference between augmenting your work and replacing it, and most of the value is on the augmentation side.

Robot assistant helping human

I think Maximilian Schwarzmueller has the right framing: use AI as a copilot, not the pilot. Let it handle the tedious mechanics while you focus on system design, architecture, and what users actually need.

Understanding still beats vibing

Maybe this is an old-fashioned position to hold in 2025, but good software still comes from understanding what you’re building and why. Vibe coding might get you to a working program faster. I’m much less sure that it produces better software, and I’m pretty sure it doesn’t produce better programmers.

Thinking programmer

The tools will keep getting better and the line between assistance and replacement will keep shifting. For now, though, I’d rather understand my code than vibe with it.