It's a language mode with finite context and the ability to use tools. Whatever it can fit into its context, it can usually do pretty well. But it does require guidance and documentation.
Just like working with actual humans that aren't you and don't share your brain:
1) spec your big feature, maybe use an LLM in "plan" mode. Write the plan into a markdown file.
2) split the plan into smaller independent parts, in github issues or beads or whetever
3) have the LLM implement each part in isolation, add automatic tests, commit, reset context
Repeat step 3 until feature is done.
If you just use one long-ass chat and argue with the LLM about architecture decisions in between code changes, it WILL get confused and produce the worst crap you've ever seen.
What good is AI as a tool if it can get not on the same page as you
Imagine negotiating with a hammer to get it to drive nails properly
These things suck as tools
I had to rewrite several vibe coded projects from scratch due to this effect. It's useful as a prototyping tool but not a complete productionizing tool.
Specifically: what if I just started downloading repo’s and aggressively copying and pasting to my needs… I’d get a whole bunch of code kinda quick, it’d mostly work.
It feels less interactive, but shares a high level similarity in output and understanding.
As a developer that has spent far too much of my career maintaining or upgrading companies' legacy code, my biggest fear with the LLM mania is not that my skills go away, but become in so much higher demand in an uncomfortable way because the turn around time between launch and legacy code becomes much shorter and the management that understands why it is "legacy code"/"tech debt" shrinks because it is neither old or in obviously dead technologies. "Can you fix this legacy application? It was launched two days ago and nobody knows what it does. Management says they need it fixed yesterday, but there's no budget for this. Good luck."
Being effective with the code to get the same things done is. That requires a new kind of driving for a new kind of vehicle.
Me: hey make this, detailed-spec.txt
AI: okidoki (barfs 9k lines in 15 minutes) all done and tested!
Me looks at the code, that has feature-sounding names, but all features are stubs, all tests are stubs, and it does not compile.
Me: it does not compile.
AI: Yes, but the code is correct. Now that the project is done, which of these features you want me to add (some crazy list)
Me: Please get it to compile.
AI: You are absolutely right! This is an excellent idea! (proceeds to stub and delete most of what it barfed). I feel really satisfied with the progress! It was a real challenge! The code you gave me was very poorly written!
... and so on.
Meaning, is the answer in the field I'm not an expert of good, or am I simply being fooled by emoji and nice grammar?
Or you can do like some of the others suggest and eliminate pure vibecoding. Just use it as a back and forth where you understand along the way and make well-reasoned changes. That looks a lot more like real engineering, so it's not surprising the other commenters report better results.
I have not experienced the level of malice and sweet-talking work avoidance from anyone. It apologizes like an alcoholic, then proceeds doubling down.
Can you force it to produce actually useful code? Yes, by repeatedly yelling at it to please follow the instructions. In the process, it will break, delete, or implement hard to find bugs in rest of the codebase.
I'm really curious, if anyone actually has this thing working, or they simply haven't bothered to read the generated code
With anything above a toy project, you need to be really good with context window management. Usually this means using subagents and scoping prompts correctly by placing the CLAUDE.md files next to the relevant code. Your main conversation's context window usage should pretty much never be above 50%. Use the /clear command between unrelated tasks. Consider if recurring sequences of tool calls could be unified into a single skill.
Instead of sending instructions to the agent straight away, try planning with it and prompting it to ask your questions about your plan. The planning phase is a good place to give Claude more space to think with "think > think hard > ultrathink". If you are still struggling with the agent not complying, try adding emplasis with "YOU MUST" or "IMPORTANT".
I think like any tool it's has it's pros and cons and the more you use it the more you figure out how to make the best use out of it and when to give up.
It wasn't super bad at converting the code but even it struggled with some of the logic. Luckily, I had it design a test suite to compare the outputs of the old application and the new one. When it couldn't figure out why it was getting different results, it would start generating hex dumps comparisons, writing small python programs, and analyzing the results to figure out where it had gone wrong. It slowly iterated on each difference until it had resolved them. Building the code, running the test suite, comparing the results, changing the code, repeat. Some of the issues are likely bugs in the original code (that it fixed) but since I was going for byte-for-byte perfection it had to re-introduce them.
The issues you describe I have seen but not with the right technology and not in a while.
I have seen AI agents fall into the exact loop that GP discussed and needed manual intervention to fall out of.
Also blindly having the AI migrate code from "spaghetti C" to "structured C++" sounds more like a recipe for "spaghetti C" to "fettuccine C++".
Sometimes its hidden data structures and algorithms you want to formalize when doing a large scale refactor and I have found that AIs are definitely able to identify that but it's definitely not their default behaviour and they fall out of that behaviour pretty quickly if not constantly reminded to do so.
What do you mean? Are you under the impression I'm not even reading the code? The code is actually the most important part because I already have working software but what I want is working software that I can understand and work with better (and so far, the results have been good).
"This looks good", vs "Oh that is what this complex algorithm was" is a big difference.
Effectively, to review that the code is not just being rewritten into the same code but with C++ syntax and conventions means you need to understand the original C code, meaning the hard part was not the code generation (via LLM or fingers) but the understanding and I'm unsure the AI can do the high level understanding since I have never gotten it to produce said understanding without explicitly telling it.
Effectively, "x.c, y.c, z.c implements a DSL but is convoluted and not well structured, generate the same DSL in C++" works great. "Rewrite x.c, y.c, z.c into C++ buildings abstractions to make it more ergonomic" generally won't recognise the DSL and formalise it in a way that is very easy to do in C++, it will just make it "C++" but the same convoluted structure exists.
Ok. Let me be more specific then. I'm "understanding" the code since that's the point.
> I'm unsure the AI can do the high level understanding since I have never gotten it to produce said understanding without explicitly telling it.
My experience has been the opposite: it often starts by producing a usable high-level description of what the code is doing (sometimes imperfectly) and then proposes refactors that match common patterns -- especially if you give it enough context and let it iterate.
> "Rewrite x.c, y.c, z.c into C++ buildings abstractions to make it more ergonomic" generally won't recognise the DSL and formalise it in a way that is very easy to do in C++, it will just make it "C++" but the same convoluted structure exists.
That can happen if you ask for a mechanical translation or if the prompt doesn't encourage redesign. My point was literally make it well-designed idiomatic C++ and it did that. Inside of the LLM training is a whole bunch of C++ code and it seems to be leaning on that.
I did direct some goals (e.g., separating device-specific code and configuration into separate classes so adding a device means adding a class instead of sprinkling if statements everywhere). But it also made independent structural improvements: it split out data generation vs file generation into pipeline/stream-like components and did strict separation of dependencies. It's actually well designed for unit testing and mocking even though I didn't tell it I wanted that.
I'm not claiming it has human-level understanding or that it never makes mistakes -- but "it can't do high-level understanding" doesn't match what I'm seeing in practice. At minimum, it can infer the shape of the application well enough to propose and implement a much more ergonomic architecture, especially with iterative guidance.
I had to have it introduce some "bugs" for byte-for-byte matching because it had generalized some of the file generation and the original C code generated slightly different file structures for different devices. There's no reason for this difference; it's just different code trying to do the same thing. I'll probably remove these differences when the whole thing is done.
So effectively it was at least partly guided refactoring. Not blind vibe coding.
It doesn't really matter what we told it do; a task is a task. But clearly how each LLM performed that task very different for me than the OP.
You migrated code from one of the simplest programming languages to unarguably the most complex programm language in existence. I feel for you; I really do.
How did you ensure that it didn't introduce any of the myriad of footguns that C++ has that aren't present in C?
I mean, we're talking about a language here that has an entire book just for variable initialisation - choose the wrong one for your use-case and you're boned! Just on variable initialisation, how do you know it used the correct form in all of the places?
It's actually far easier to me to tell that it's not leaking memory or accessing some unallocated data in the C++ version than the C version.
A simple language just pushes complexity from the language into the code. Being able to represent things in a more high-level way is entirely the point of this exercise because the C version didn't have the tools to express it more cleanly.
I had a similar issue with GNU plot. The LLM-suggested scripts frequently had syntax errors. I say: LLMs are awesome when they work, else they are a time suck / net negative.
Was this a local model?
The niche is "the same boring CRUD web app someone made in 2003 but with Tailwind CSS".
If you have a CLI, you can even script this yourself, if you don't trust your tool to actually try to compile and run tests on its own.
It's a bit like a PR on github from someone I do not know: I'm not going to actually look at it until it passes the CI.