The expectations are clear at my workplace that all software developers shall use LLMs aggressively.
LLMs have allowed me to work in a new area in which I’m not specifically experienced, and bring my general knowledge to bear in ways that have allowed me to substantially improve that software beyond what those natively expert in the domain of the tools and frameworks in use have done. I’ve been able to lead successful efforts to make the software far more robust — even though I’m not an expert in the language or frameworks.
I’ve been able to brow-beat the machine into producing code of high enough quality that it’s within reason that a human could maintain it. It is possible with experience to tell it to do better in specific ways.
The default code quality deteriorates rapidly without actively correcting the machine’s actions. It’s really bad at following the DRY principle. Unless you strongly direct it otherwise, it writes many subtly different copies of the same thing in hundreds of places through the code, making the user experience subtly inconsistent. (This is generally true of multiple LLMs.)
On the good side, almost everyone hates writing tests even if they love tests existing, and the robot can usually be easily convinced to write tests — though often testing the same thing in ten different brittle ways. I have to challenge it, “what does this test add?” and it says “oh, you are right, it is useless” (though usually not acknowledging that it’s worse that useless because it slows down the test suite and speed is critical). It’s also good at adjusting brittle tests; you just have to make sure that what it’s changing then to makes sense.
Sometimes, it will remove code and then write a permanent test to ensure that the code was removed, and leave it in there to run indefinitely. Lots of stupid excess like this sometimes makes me feel like the CI providers must be paying them kickbacks!
(I know they aren’t, it’s just a joke…)
For work that requires large quantities of structural but mechanical change, LLMs are hard to beat. A few people were able to do some of this semantic transformation with tools like Coccinelle, but LLMs make this generally not that hard. I just had the robot army build almost 8000 lines of hardening that would have taken me probably 20x as long to do by hand. It was in a code base moving fast enough that actually I would never have finished because I’d have hit a conflict by the time I was finished fixing the previous conflict and trying to merge…
I now rarely hand-code at work. But I never vibe-code as I define it. If the robot does something that requires knowledge I don’t have to effectively review, I go to a domain expert, tell them what I have reviewed myself and what I don’t understand, so that I’m being honest about what I can stand behind and what I can’t, and what I’m asking for. I don’t just say that I “wrote” it and ask them to review it as such. To me, that would be anti-social…
It really matters which model I’m using. With Claude, if I accidentally use a dumb model like sonnet, it can go off the rails and waste my time unless the change is purely mechanical. Opus or fable do better right now. (The details of which models can do what seem to change about monthly, though…) I’ll often tell opus to use sonnet subagents to do work not requiring judgment, and opus for subagents that do require judgment. Being really aggressive about using subagents tends to conserve token space in the parent agent. When an agent runs low on tokens, it gets dumb before it runs out. It’s like a filesystem getting really slow before it completely runs out of space…
We have multiple AI agents reviewing our code at work. They often disagree, and even one agent will ask for a change and then the other agent will complain about the change and insist on it being reverted. This is an amazingly accurate re-implementation of one of the annoying traits of human reviewers. 
Personally, I have been doing an experiment asking Gemini to build me a specific piece of ham radio software. It did… ok initially. But I’m not that impressed with it often. I have to keep an eagle eye on its output. It regularly creates regressions, changes behavior when I ask for a pure refactor, drops tests for no reason; it’s like working with a bright but half-witted intern with shifting and bad opinions. Ultimately I just have to take over and drive more. It was still a net win for time vs hand-coding, but less so. At least “add tests for current behavior, refactoring and adding interfaces to make more code testable” is usually within its happy place, as long as I review carefully that it hasn’t just gotten opinionated. When it starts giving me lectures on software architecture that are wildly misplaced (this is, after all, literally my job) I have to slap it down really hard to make it stop. And sometimes it just can’t see how to do a simple task and I just take the wheel and tell it to stand down.