Recovering from Vibe Coding Fatigue
Rediscovering the art of thoughtful software development in the era of vibe coding
Hi, I’m Jorge! After two years at Google, I left to design the life that I want and create my own startup. Every couple of weeks I share some of the learnings from my journey.
Whether you're excited about building with AI, considering your own career leap, or just curious about the journey, I’d love to hear your thoughts. Don’t forget to subscribe for free!
Feeling like a stranger in your own codebase?
Creating PRs faster than you can read them?
Coding with AI starting to create more problems than they solve?
If any of these symptoms sound painfully familiar, then you might be suffering from one of the newest ailments sweeping across tech: vibe coding fatigue.
First Contact
In early February, I came across Andrej Karpathy’s now-iconic tweet introducing vibe coding:
By then, I was already planning my exit from Google and experimenting with building AI-powered side projects in the meantime.
But when I tried Cursor, everything changed.
It was incredible to discuss design with the AI agent and watch it implement features across multiple files, run tests, fix its own mistakes, and report back—all without me lifting a finger.
From that moment until I left Google in June, I spent hundreds of hours building side projects (here are two: Helm, a project management tool for AI agents, and Metaflo, an AI workflow engine).
Over the course of all those hours, I felt like I was doing more engineering work than ever before, while somehow writing maybe 1% of the code myself.
It felt like a superpower.
Now, initially I was cautious, spending hours iterating on design with Cursor before implementation, maintaining high standards for code quality and maintainability. Despite flaws inevitably creeping in over time, as happens in any codebase, I was genuinely happy with the code quality.
But things started changing when I began working on my startup in July. I challenged myself to let go of my perfectionism and listen to the conventional startup wisdom: build quickly, get something minimal working, and move on.
I also experimented with the new wave of asynchronous coding agents: Factory, Devin, Codex, and others. The ability to kick off a coding task from your phone, have it run in the cloud, and check back later on a ready-to-go pull request (PR) felt like a huge unlock.
You were no longer limited by a single chatbox in your IDE. The possibilities seemed endless, constrained only by the number of tasks you could dream up for your army of AI agents.
Symptoms Emerge
The condition developed gradually. Each compromise seemed benign in isolation.
This implementation works, even if it’s not how I would write it.
I’ll come back and refactor this later.
This is good enough for now.
But in practice, the cumulative result was… a different story:
Spending more time debugging unfamiliar code
Drowning in AI-generated PRs
Unable to get into a rhythm from constantly context-switching between debugging half-finished agent tasks
Finding myself impatiently asking the AI to fix the same bug for the fifth time in a row without providing any context other than some error logs
Watching code quality gradually decay through countless tiny compromises
It was also just not as fun.
And that brings us to vibe coding fatigue: the malaise that comes from outsourcing too much cognitive engagement to AI tools, leaving you disconnected from your own code and craft.
Looking back, it seems so obvious. Of course I should thoroughly design my code. Of course I should carefully review all AI generated code and not compromise my standards.
But when you’re deep in it, your patience diminishing as your brain is gradually rewired to expect instant results, and every delay feels like failure, it sort of just… happens.
Recovery
Two weeks ago, I was working on building AI voice agents. After some research, I decided I’d be implementing this with the LiveKit Agents Python library.
I was new to LiveKit and hadn’t written Python code in a while, and feeling this vibe coding fatigue, I started implementing it by hand.
Well, except for some Cursor tab completion (I’m not a savage).
I took a break from using background coding agents. I stopped rushing through the design phase. I got back to using AI as a partner, spending hours having it do research, discussing alternatives, and getting feedback on design decisions before moving to implementation.
When reviewing generated code, I listened a bit more to the perfectionist in me. Details that bothered me were addressed. No more accepting implementations just because they worked. I wanted code that made sense architecturally and that I’d be happy to maintain.
And I’ve gotta say, it’s been refreshing.
The benefits were immediate and tangible:
Greater familiarity and comfort with the code
Less time debugging
Faster feature development after the extended design phase
Cleaner, more maintainable code
But the intangible benefits were even more significant.
I felt in control. The work was fun again.
Without realizing it, I had fallen into a pattern of shallow engagement—constantly switching between agent tasks, skimming PRs, never staying with one problem long enough to think deeply about it. It was like my coding workflow had become TikTok-ified: swipe to the next task, quick review, merge, repeat. It felt like this constant context-switching and cognitive offloading was actually rewiring my brain for impatience rather than problem-solving.
Now, I was allowing myself to deeply engage with challenging problems again. My engineering skills were getting exercised rather than atrophying.
It made me realize that in rushing the implementation, I had outsourced the problem-solving and design that I actually enjoyed about engineering.
What I’ve Learned
I’m not saying you should stop using AI coding tools, or even background coding agents.
Coding agents will continue to improve, and it’s unwise to avoid dedicating time and effort to incorporating background agents into your workflow, just as it’d be unwise for a newly promoted manager not to get comfortable delegating tasks to their junior engineers.
Also, with the cost of implementation decreasing, rapid AI implementation can be perfect for validating MVPs before pivoting or rebuilding from scratch.
But if you’re working on something you care about and have a technical background, don’t stop thinking about your code just for the sake of shipping quickly.
As much as I’m trying to be a founder, I’m also an engineer. The extra enjoyment and motivation from staying engaged with technical challenges more than makes up for any initial slowdown.
The solution isn’t abandoning AI tools, but finding the sweet spot where you stay in control.
My Workflow Now
For fellow builders curious about the specifics, here’s what’s been working for me:
Design Phase: I’ve gotten back to spending significantly more time upfront collaborating with AI on architecture and design docs.
Typically I’ll start by creating a new session on Opencode in plan mode, talking in detail about what I’d like to implement, giving plenty of context, and pointing out relevant parts of the codebase as I think through and explain my initial thoughts on implementation.
Depending on the task, I might initially avoid giving implementation details just to see what it comes up with. I find it helps to leverage AI as a way to access different perspectives and ideas I might not have considered. There’s You can add an extra layer by discussing with different models and prompting them differently. It’s also a great way to stay engaged and learn as you go. I tend to be very inquisitive during this phase, asking a lot of questions and encouraging the AI to do research to inform its decisions and justify its claims.
The upfront investment in this deeper design phase pays off exponentially: better AI output, fewer debugging sessions, cleaner code, and more enjoyable work. Depending on the complexity of the tasks I’m working on, I might have up to four sessions open at a time.
Implementation: I’ve been doing more synchronous AI coding again, especially for complex logic where I want to stay in the conversation, and background agents for boilerplate, simple fixes, UI changes, to test the AI's capabilities, or as a first pass at a task (after which I can judge what went well vs. what didn’t and update my design).
It should come as no surprise also that handing off a solid design doc to background agents produces dramatically better results than even a well-thought-out but less specific multi-paragraph prompt.
I also always ask the agents to implement tests for their code. This leads to better results, catches bugs early, makes code reviews easier, and gives me confidence in the quality of the AI-generated code.
I’m constantly experimenting with new AI tools, but here’s my current setup:
Synchronous coding:
Opencode: Has slowly supplanted Claude Code as my go-to coding CLI. I typically use Claude Opus 4.1 through my Claude Max subscription.
Context7 MCP server: For helping the AI find relevant documentation quickly.
Note: Been meaning to explore more MCP servers. Let me know in the comments if you have favorites worth checking out
Cursor: For manual edits and the still-unmatched tab completion.
Background agents:
Terragon: My current favorite for running Claude Code in the background. Works with your Claude Pro or Max subscription, simple UI, and it’s been free so far.
Cursor background agents (honorable mention): Despite having moved away from Cursor in the last month, their implementation of background agents deserves credit for the seamless handoff between remote and local environments. You can kick off tasks from anywhere, browse remote sessions in your IDE, and easily pull them to your local machine with along with the remote agent’s full chat history. I did eventually stop using it though now that I’m relying fully on a Claude Max subscription.
Coding by Hand: Like I mentioned, I tried coding by hand for the first time in a long time and it felt refreshing. I don’t necessarily think this will become a staple of my workflow, but it’s nice every once in a while when you’re starting something from scratch, introducing a new module, when the LLM is struggling, or when you just want to change it up.
Code Review: Not that I didn’t review AI-generated PRs before. I’d check for bugs, spot security issues, and test manually. But I was doing surface-level reviews. Understanding what the code did but not always why it was structured that way or whether there were better approaches. Each compromise felt small—what’s one suboptimal bit of code in the grand scheme of things?
But as any engineer can tell you, that’s how every codebase ultimately ends up in a gnarled, unmaintainable state, the tech debt piling on with each shortcut. The effect will only be multiplied when engineers have multiple AI agents working for them at any given time, with the power to pump out code at an unprecedented rate.
Now, I’m taking the time to think through the implementation. Could this be cleaner? Does this fit our architecture? Would I write it this way if I were doing it manually? The temptation to accept a working PR without considering alternatives is real, but resist it. The first time you give in starts a slippery slope that leads to death by a thousand cuts.
Side Note on Speech-to-Text (STT): Throughout all of this, I've consistently used STT tools when talking to models. Speaking out loud not only saves time but helps me flesh out my thoughts more clearly, but it also reduces the friction to providing models with lots of context.
Last month I switched from SuperWhisper, which was getting way too buggy, to Willow Voice and it has been incredibly reliable.
TL;DR
If you’re suffering from vibe coding fatigue, here’s your antidote:
Use AI as a coding partner. The best sessions feel like pair programming with an incredibly knowledgeable colleague, not like managing (and cleaning up after) brand new interns.
Always request tests with implementation. AI-generated tests serve as both documentation and quality gates, catching edge cases you might miss and making code reviews more confident and efficient.
It’s okay to slow down to stay engaged. The productivity from just making building a more pleasurable experience (not to mention the decreased tech debt) will outweigh the initial time cost of being more thoughtful upfront.
Find the right balance between autonomy and control. There’s absolutely a place for fully autonomous agents. But in many cases, you want AI that augments your thinking rather than replacing it.
As AI continues to evolve and take on more of our tasks, experimenting with these tools is essential. But beware of outsourcing the parts of your work that give you purpose and energy.
Stay in control of what matters to you, and let AI handle the rest.







Funny how you only notice coding fatigue when your productivity crashes… I think your breakdown of symptoms is real and hits home. Great read!