The Vibes Were Never the Point

ewancroft.uk uses AI. I’m not going to bury that in a footer disclosure or frame it as a confession at the end. It is built with AI assistance, some of the code was generated rather than hand-typed, and I have no intention of pretending otherwise.

That said, “AI-assisted” is doing a lot of heavy lifting as a phrase right now – covering everything from autocomplete to entirely unreviewed code generation. The difference between those two things is not small. The conversation around AI and software development has spent the past year and a half collapsing that distinction, and I think it is worth pulling it back apart.

Enter the Vibes

In February 2025, Andrej Karpathy – a co-founder of OpenAI and one of the more credible voices in AI research – posted something on X that quickly became a piece of tech-discourse furniture. “There’s a new kind of coding I call ‘vibe coding’,” he wrote, “where you fully give in to the vibes, embrace exponentials, and forget that the code even exists.”

The description was deliberately casual. You describe what you want. The model produces code. You accept it. You run it. You paste the error message back in and repeat. No reading of diffs. No careful consideration of what the model actually did. Just vibes, as the name suggests. Karpathy framed it as suited for throwaway weekend projects – a rapid ideation mode rather than a professional practice. The post was viewed 4.5 million times, spawned its own terminology, and became shorthand for a style of development that was simultaneously inspiring and concerning, depending on who you asked.

I assume many people who read that post took “vibe coding” as a general description of AI-assisted development. It isn’t, or wasn’t, and Karpathy himself clarified this when he effectively retired the term in February 2026 – exactly one year after coining it.

The Term Is Already Dead

By early 2026, Karpathy announced that “vibe coding” was passé. The LLMs had, in his estimation, got good enough that the casual, unreviewed approach was no longer a particularly useful description of what serious practitioners were doing. His proposed replacement: “agentic engineering.”

The framing is worth noting. In a post on X, he described the current practice: “programming via LLM agents is increasingly becoming a default workflow for professionals, except with more oversight and scrutiny.” He prefers “agentic engineering” because the word “agentic” captures the fact that developers are no longer writing code directly most of the time – they are orchestrating agents who do – while “engineering” emphasises that genuine craft and expertise remain in the picture. This is not, in other words, just vibes. It is direction, judgement, and taste, applied to autonomous systems that do the implementation.

This distinction matters to me personally, because my experience of using AI in development does not resemble vibe coding in Karpathy’s original sense. I am not forgetting that the code exists. I am reading it. I am understanding it well enough to catch what the model got wrong. I am directing the process toward an outcome I can describe precisely, which requires knowing what good looks like.

Whether that makes me an “agentic engineer” rather than a “vibe coder” is a branding question I’ll leave to tech journalists. The point is that the spectrum is real and the labels matter for the same reason any taxonomy matters: they help you think clearly about what you are actually doing.

The Security Problem Nobody Is Downplaying Enough

To be quite honest, this is the part that gives me pause, and I want to engage with it seriously rather than wave it away in the direction of skill-issue discourse.

The data on AI-generated code and security is not good. A 2025 study found that 38% of AI-generated code contained at least one security flaw. Veracode tested over 100 large language models on security-sensitive coding tasks and found that 45% of AI-generated samples introduced OWASP Top 10 vulnerabilities – and that figure had not meaningfully improved across multiple testing cycles from 2025 into early 2026, despite vendor claims to the contrary. CVEs formally attributed to AI-generated code jumped from six in January 2026 to 35 in March 2026, with researchers estimating the true figure is five to ten times higher because most AI tools leave no commit metadata to track attribution. AI-assisted commits expose hardcoded secrets at more than twice the rate of human-only commits – 3.2% versus 1.5%.

There is a specific failure mode worth naming: slopsquatting. Across 2.23 million AI-generated code samples from 16 models, nearly 20% contained at least one hallucinated package name that does not actually exist. Of those hallucinated names, 43% reappeared on every single run with the same prompt. Consistent hallucinations are predictable. Predictable names are registerable. Attackers identify the phantom package names that LLMs reliably generate, publish malicious code under those exact names, and wait for developers to run the install command their AI assistant just wrote. The developer pulls attacker-controlled code directly into their project, no exploit required.

This is not theoretical. This is a documented, active attack vector.

None of this is an argument against using AI in development. It is an argument for understanding that AI-generated code requires the same security review, test coverage, and architectural scrutiny as human-written code – possibly more, because the failure modes are different. The errors are, as Karpathy himself noted, less likely to be syntax and more likely to be subtle conceptual mistakes that pass a first read. That demands a higher standard of review, not a lower one.

The De-Skilling Question

The concern I find most interesting – because it’s the least settled and the most contested – is whether AI-assisted development erodes the skills of the people who use it.

There is an uncomfortable data point from METR, published in 2025, that I’m going to acknowledge rather than quietly skip: experienced developers took 19% longer to complete tasks with AI assistance than without it, because of the time spent correcting and validating generated code. That is one study, conducted at a specific moment in the capabilities curve, and the models have improved considerably since. But it illustrates a real dynamic: the productivity gains at the task level do not automatically translate to gains at the system level, because the bottleneck was rarely the typing. It was the thinking.

The deeper concern is about junior developers. I should declare an interest here: I finished college this month and I cannot find work as a developer. That is not a detour from the argument – it is the argument, in miniature. A 2025 LeadDev survey found that 54% of engineering leaders expect junior developer hiring to drop long-term as a direct result of AI coding tools. Stanford’s Digital Economy Lab , working from ADP payroll data covering millions of workers, found that employment for software developers aged 22–25 had declined nearly 20% from its late-2022 peak by mid-2025 – while employment for developers over 30 grew. AI is not eliminating software engineering. It is eliminating the entry point into it.

The irony is that AI-generated technical debt requires precisely the kind of human judgement that juniors develop through years of writing code, making mistakes, and learning what causes what. By eliminating the conditions under which that judgement develops, you don’t just get a skills gap in the next generation. You get a future in which nobody has the expertise to fix the mess the current generation left behind.

I don’t think AI will replace developers. I think the more accurate prediction is that it will differentiate them more sharply. Karpathy has said that technical mastery is “even more of a multiplier than before” in an agentic workflow – a developer who deeply understands architecture can leverage a team of agents to achieve an order-of-magnitude productivity gain, while someone without that foundation will generate broken code faster. The floor is lower and the ceiling is higher. Whether that’s a good outcome depends almost entirely on who you’re rooting for.

On Being the Wrong Kind of Gen Z

Here is something I have not seen many people in my position say plainly: the Gen Z backlash against AI makes me feel bad about myself. Not wrong, exactly. Just uncomfortable in a way I haven’t fully resolved.

I write poetry. I’ve been writing it since I was old enough to have feelings I didn’t know what to do with. It is not a hobby in the casual sense – I take commissions, I publish it, it is one of the few things I do that exists entirely outside the computational frame. No architecture decisions, no dependency graphs, no pull requests. Just language trying to get at something true. I say this upfront because it means the stolen works argument is not abstract for me. It lands somewhere specific.

AI systems were built, in significant part, on creative work taken without consent. Not purchased. Not licensed. Scraped. The poetry, the prose, the art – absorbed into training sets without the knowledge of the people who made them, without payment, without credit, without the option to opt out until after the fact. That is not a policy disagreement I hold at arm’s length. That is theft, dressed in the language of data processing, and the fact that the people harmed include poets I admire and writers whose work I have read and taken from in the way that reading properly takes from you – that makes it worse, not better. I am genuinely, non-performatively angry about it.

And yet. I use AI tools for development. I find them useful. I have not found a way to reconcile those two facts that isn’t slightly dishonest in one direction or another.

The best I can do is this: necessary poison. The tools exist. They were built the way they were built. Refusing to use them in a development context does not undo that. The training happened. The theft happened. My abstention from AI-assisted code generation does not make a single displaced poet whole. What it does is make me slightly less effective at building things I actually want to build, while accomplishing nothing of consequence for the people who were actually harmed. I am not sure that trade is principled. I think it might just be self-soothing.

What I find harder to sit with is the generational dimension. The loudest Gen Z opposition to AI tends to come from people who are already employed, already established, already past the entry-level ceiling that AI has now lowered. There is a specific kind of safety in being able to declare principled opposition to a technology when your position doesn’t depend on keeping pace with it. The junior developer who graduated into a collapsed market and quietly uses AI to stay relevant gets very little sympathy from that conversation – because the conversation isn’t really about them. It’s about identity. About the specific satisfaction of having a clean position on a culture-war-adjacent technology debate.

I have a position. It is not satisfying in that way. It is: these tools were built badly, the displacement of junior developers is a structural problem that principled individual non-use will not fix, and I am a junior developer who uses them anyway and feels the particular discomfort of someone who has not found a clean answer.

I also notice, without particular smugness, that a significant proportion of the people loudest about AI being uniquely harmful use it too. Not the large-scale infrastructure decisions they’re criticising – that’s a fair distinction to draw. I mean the everyday tools. The writing assistants. The autocomplete. The image generators. The position and the practice often don’t quite match. That’s not a reason to dismiss the criticism. It is a reason to be honest that the criticism is more complicated than it looks when it’s trending.

If that makes me the wrong kind of Gen Z, I can live with that.

The Toaster Argument

That said: there are places where AI has no business, and I want to name them clearly, because this post being candid about using AI in development should not be read as a general endorsement.

A toaster, with the right mechanisms, could theoretically produce marks on paper resembling words. That would not make it a poet. The output would not be poetry. Not because the marks were ugly or the words were wrong – because the toaster did not feel anything, did not need to say anything, did not reach for language as the only available form of a thing that would otherwise have no form at all. Poetry is what happens when a person has something they cannot say any other way and forces language into the shape of it. That necessity – the specific human consciousness doing the forcing, with the specific weight of whatever it is carrying – is the thing. The output is just evidence it happened.

AI-generated poetry is not poetry with a different author. It is a different thing wearing poetry’s clothes. It was not made because anyone needed to say it. It was made because a prompt asked for it and a model obliged. The emotional truth is not absent because the model is bad at faking it. It’s absent because no one felt anything when it was made.

That is not a technical limitation that future models will overcome. That is a category error.

The same argument applies to fiction, to visual art, to any form of creative expression that requires human emotion, human experience, and human intent as its actual material. I am not interested in the output-quality debate. I am not arguing that AI cannot produce things that superficially resemble creative work – clearly it can. I am arguing that the resemblance is the problem, not the solution. When everything can be instantly generated, when the cost of producing approximate creative content is effectively zero, the genuine article becomes harder to find. The readers who might have encountered a real poem wade through a sea of statistically plausible ones to reach it. The poets – the actual ones, the ones who needed to say something and found a form to say it in – are shouting into an increasingly noisy room.

That’s the harm. Not replacement. Drowning.

I write poems. I will not be using AI to write them. I write short stories. Same. This is not an ideological performance. It is just that the entire point of those things, for me, is the part that AI cannot do – the having something to say, the needing to say it, the finding the words. Remove that and you haven’t made the process more efficient. You’ve removed the process entirely and replaced it with a different activity that happens to produce similar-looking output.

Those are not the same thing. They are not even close.

What I Actually Do

My relationship with AI in development is not “fully give in to the vibes.” It is something more like: describe the problem with enough precision that the model can make a useful attempt, review what it produces, understand it well enough to spot when it’s wrong, and redirect from there. The model handles significant amounts of the implementation. I handle the architecture, the decisions about what to build, the evaluation of whether what was built is actually correct, and the debugging when it isn’t.

The poetry, the short stories, the blog posts – none of that is touched. That separation is not incidental. It is the whole point. The distinction I’m drawing in this post is not “AI is fine” versus “AI is bad.” It is “here is the specific domain where a necessary poison has a use” versus “here is the domain where it has no business and I will not pretend otherwise.”

ewancroft.uk is a SvelteKit application with a fairly involved stack – AT Protocol integration, a Ko-fi webhook pipeline, a custom design system with OKLCH tokens, a monorepo of published npm packages underneath it. Worth noting: because the site is built on the AT Protocol, everything user-facing is public by design. The protocol stores data in a cryptographically signed, publicly readable repository. There is no private layer to accidentally expose, which means the entire class of vulnerabilities involving broken access control and leaked user data is structurally off the table. The security concerns that remain are real but different: server-side credential handling, dependency chains, the slopsquatting problem. Architecture ruling out a failure mode is a more reliable guarantee than code review catching one.

This post lives on blog.ewancroft.uk, powered by Leaflet – a publishing platform built on the AT Protocol. The ewancroft.uk/blog view of it is a different reading client for the same underlying record. The data is identical; the interface changes. That is the protocol working as intended, not described abstractly.

The site exists because I wanted it to exist in a specific way, and it does what it does because I had enough of an opinion about what good looks like to direct it there. The AI accelerated the implementation. It did not provide the taste.

That last part is, I think, the honest answer to the vibe coding question. The tools are increasingly capable of generating code that compiles, runs, and does something. They are not capable of knowing what it should do, why it should do it that way rather than another way, or whether it does it securely enough to ship. Those remain human problems, and they will remain human problems for longer than the breathless headline cycle would suggest.

Where This Leaves Things

The term “vibe coding” had a useful year. It captured something real about the early generative AI development experience – the novelty of describing a thing in plain language and watching a model produce it, the intoxicating feeling of iteration at speed. It also, somewhat accidentally, gave people a name for a practice that looks like development but skips most of what makes development work: understanding, scrutiny, judgement, and ownership of the result.

Karpathy retired it not because the tools stopped working but because the serious practitioners had moved beyond what the term described. The tools are better now. The stakes are higher now. The security data is accumulating.

What I can say, without particularly hedging it: AI-assisted development is real, it is useful, it is part of how I build things, and it requires more competence to do well than the “forget the code even exists” framing implies. The fact that the tools were built on stolen work is true and I am angry about it. The fact that my generation is being displaced by them is true and I am living it. The fact that I use them anyway, in the specific domain where they are useful to me and nowhere else – that is also true, and it does not resolve neatly against the other facts. I am not trying to make it.

Some things are necessary poisons. The line is in knowing which things are not.

The code is still there, whether you’re reading it or not.