I started using ChatGPT for development before coding agents were a thing.

There was no agent moving through the repository, running tests, editing five files, and coming back with a finished diff. There was a chat window beside my editor. I copied in a problem, read the response, moved a useful part into the code, ran it, and brought the result back when it failed.

It was manual and a little awkward. It was also immediately useful.

What I did not do was hand over the decision-making. I still thought through the larger scope, asked what-if questions, looked for edge cases, tested the result, and decided whether the approach belonged in the system at all. AI was an assistant to my experience, not a substitute for it.

The tedious parts became dramatically faster. The responsibility stayed exactly where it had been.

That distinction is getting lost now. “Vibe coding” has become a convenient insult for almost any software built with AI, including work where an experienced developer understands the system, directs the tool, reviews the result, and owns what ships.

There is a real failure mode underneath the phrase. It just is not the whole category.

The bad version is genuinely bad

If someone describes an application to a model, accepts whatever appears, and keeps prompting around errors until the demo works, I understand the concern.

Working on the happy path is not the same as being correct. The generated code may have weak authorization, unsafe data handling, accidental complexity, dependencies nobody evaluated, or tests that confirm only the behaviour the model happened to implement. If the person shipping it cannot explain the architecture or trace a failure, the speed is not impressive. It is exposure.

AI makes that kind of software easier to produce and easier to make look finished.

That matters. A bad decision used to take longer to turn into a convincing interface. Now it can arrive with clean naming, plausible tests, and enough polish to survive a shallow review. AI did not invent false confidence, but it can manufacture the evidence for it very quickly.

So yes, you can make bad software with AI.

You could always make bad software.

We had copied forum answers, cargo-culted architecture, framework scaffolding, giant dependency trees, code generators, and developers following tutorials they did not understand long before a model could edit a repository. None of those tools guaranteed quality either. They gave people leverage, and leverage works in both directions.

AI is more leverage.

The sensible response is stronger engineering discipline, not pretending the tool itself tells us whether the work is good.

I did not stop engineering when the tool improved

The tools have changed quickly since that chat-and-copy-paste workflow. They can now hold more context, navigate a codebase, make coordinated changes, run commands, inspect failures, and revise their own first attempt.

That has changed how much work I can delegate. It has not changed what I need to know.

I still need to understand where state lives. I need to know what happens when a request is repeated, a dependency is unavailable, two users act at the same time, or a migration meets production data instead of a clean development database. I need to recognize when a solution is technically valid but wrong for the team that will maintain it.

Those questions do not disappear because the generated diff is tidy.

My useful test is simple: can I explain the change without referring to the prompt?

Can I describe why this boundary exists, what the alternatives cost, how the failure path behaves, and what evidence would make me comfortable releasing it? Could I modify the implementation myself when the requirements change? Do I know which part I distrust most?

If I cannot answer those questions, I am not ready to ship the code. It does not matter how quickly it was produced or how confidently the tool described it.

This is why experience can make AI-assisted development so effective. Years of production work give you a catalogue of consequences. You notice the missing permission check, the operation that cannot safely retry, the convenient abstraction that will be painful to debug, or the edge case that matters because a real user will eventually find it.

AI compresses the mechanical distance between a decision and its implementation. Experience helps determine whether it was a good decision.

The tool can still make experienced people careless

I do not want to turn this into an argument that AI is safe in senior hands and dangerous in everyone else’s.

Experience is not immunity. A capable developer can accept a large diff too quickly because it looks coherent. Generated tests can create confidence without testing the right behaviour. An agent can move fast enough that reviewing its work becomes the new bottleneck, and the temptation is to skim the parts that look repetitive.

There is also a real learning problem for newer developers. Struggling through an implementation teaches you how the pieces connect. If AI removes every difficult step before you understand it, you may finish the feature without building the mental model needed to debug it later.

The answer is not to avoid the tool until some imaginary point when you know everything. It is to keep the work inside the boundary of what you can verify and explain.

That boundary moves as your knowledge grows. It should not move merely because the model became more confident.

“No AI” is a poor hiring signal

This is where some of the current reaction becomes counterproductive.

A job posting that treats any AI use as evidence of weak engineering is measuring the wrong thing. It cannot tell the difference between someone who outsourced their thinking and someone who used a powerful tool under disciplined control. It may even reward candidates who hide their process rather than candidates who can explain it honestly.

I would rather evaluate the judgment directly.

Give a candidate an AI-generated change and ask them to review it. Ask what they would verify before merging, which assumptions make them uncomfortable, what happens under retries or partial failure, and which tests would actually increase confidence. Ask them to explain a piece of AI-assisted work they shipped, including what the tool got wrong and what they changed.

The useful signal is not whether every character was typed by the candidate.

It is whether they can distinguish plausible code from appropriate code. Whether they know what to delegate, what to inspect, and what they are still responsible for after the merge. Whether they can own the result when production behaves differently from the prompt.

Those were important engineering skills before AI. They are more important now because implementation can move so much faster than understanding.

We need a better distinction

I have no interest in defending blind generation. If you cannot explain the code, test the important paths, or recognize the limits of the approach, calling it engineering does not make it engineering.

But calling all AI-assisted development “vibe coding” is equally lazy. It collapses two opposite behaviours into one label: surrendering judgment to a tool and using a tool to apply judgment faster.

I use AI because I know what the slow, tedious parts of software development feel like without it. I also know that typing those parts myself never guaranteed a safe or maintainable result. The quality came from understanding the problem, making the tradeoffs, checking the edges, and staying accountable after release.

AI lets me do more of the mechanical work in less time. That is real leverage, and I am going to keep using it.

I am also going to keep reviewing, testing, questioning, and owning what ships.

The tools have moved a long way from the chat window I started with. Responsibility has not moved an inch.