Cleaning Up a Vibe-Coded Codebase
Andrej Karpathy coined "vibe coding" in February 2025, describing a way of building where you "fully give in to the vibes, embrace exponentials, and forget that the code even exists." By November, Collins Dictionary had named it word of the year. Somewhere between those two dates, a very large amount of production software got written that no human has ever read. This post is about what comes after, because after has already arrived: one of the breakout searches around the term this year is "vibe coding cleanup specialist" (Google Trends).
Cleanup became a job title
404 Media profiled the engineers paid to fix vibe-coded messes: freelancers and small firms whose entire pipeline is AI-generated apps that outgrew their authors' understanding. Indeed now explains the role to job seekers. Marketplaces match fixers with founders whose prototype reached paying customers before it reached review.
Even people who enjoy the workflow draw the same line. Linus Torvalds vibe-coded the audio visualizer in his AudioNoise side project over the holidays (Phoronix has the story), and told The Register he is fine with the practice "as long as it's not used for anything that matters". Plenty of it was used for things that matter. The bill lands on whoever inherits the repository.
Why inherited AI code is its own problem
Engineers have always inherited messy codebases. Two things make the vibe-coded variety different.
There is no author to ask. The person who "wrote" the code watched it stream past; the reasoning lives in a chat log that scrolled away months ago. The standard onboarding move, find the person who knows and buy them a coffee, has no target. The code is the only witness to its own design.
And the mess has an unusual texture. Session-by-session generation means each conversation solved its problems from scratch: three date-parsing helpers, two retry wrappers, a hand-rolled auth check beside a half-wired auth library. Quality varies file by file in a way human tech debt rarely does, a clean, well-shaped module next to one that silently swallows errors, because each file reflects the context one session happened to have. This is the same visibility failure we describe in why AI coding agents fail on large codebases, compounded over every session that ever touched the repo.
There is also simply more of it. An agent produces code at a pace review practices were never sized for, and the inheritance moment arrives sooner: the cleanup market grew up within a year of the term being coined, which is faster than most codebases used to need a rescue.
Both properties defeat reading as a strategy. Reading a repository end to end was already impractical. Reading one where structure may or may not exist, with nobody to confirm intent, is how cleanup engagements blow their estimates.
Survey before you touch anything
The first deliverable of a cleanup is a map nobody ever drew. A code graph computes one directly from the dependency structure: parse the repository into symbols and edges, run community detection over the result, and the modules that actually exist fall out, with the load-bearing functions ranked by how much of the graph routes through them and the places where two "modules" are secretly one tangle exposed as coupling. We generate this view for the repositories in our architecture library; on a vibe-coded repo it answers the first client question, "what did we actually buy", in an afternoon.
The map also finds the duplication. Semantic search over the indexed code surfaces the three retry implementations as neighbors even when their names share nothing, which turns "I suspect there's duplication" into a list with file paths.
The survey is also the deliverable that survives contact with stakeholders. "We found three hundred issues" starts an argument. A module map with named hubs, a ranked duplication list, and a blast radius per proposed edit reads as a plan, and it prices the engagement in units the person paying for it can check.
Size every edit by blast radius
The dangerous cleanup edit is the one that looks local. Consolidating those three retry helpers into one reads as pure hygiene, until the callers of each turn out to sit on different assumptions about timeouts. Before every consolidation, rename, or deletion, ask what breaks when you change this function: callers first, then the downstream set, then decide whether the edit is an afternoon or a project.
The same numbers rank the backlog. High fan-in plus duplicated logic marks the profitable targets, the ones where one fix removes risk from many paths. Zero callers marks the safe deletions, and vibe-coded repos carry a lot of those, because sessions abandoned approaches without removing them. Tests deserve their own line item: these projects often ship with few or none, which removes the usual refactoring safety net. Until a test base exists, blast radius is the available substitute: it tells you which paths could change behavior, so you know where to verify by hand and where the first tests you write will earn the most.
Keep the next agent from re-vibing
A cleanup that ends with clean code and an unchanged workflow has scheduled the next cleanup. The root cause was visibility: the agent writing file forty could never see the first thirty-nine, so it duplicated, diverged, and accreted, one plausible file at a time.
The fix is the same graph, pointed forward. An agent connected to it over MCP resolves "add retry logic" to the retry helper that now exists, checks callers before changing a signature, and sizes its plan before executing it. That turns a one-time rescue into a workflow change, and it is the point where the cleanup stops being a cost center: the graph that paid for the audit keeps paying every session after it.
Known limits
A graph reads structure, and intent stays out of reach: it can tell you two functions are near-duplicates, and it cannot tell you which of the two behaviors was the requirement, so cleanup still involves a human deciding what the software is supposed to do. Community detection proposes modules; the proposal needs review before it becomes the target architecture. And in repositories that wire behavior through configuration or reflection, parsed edges understate reach, so treat a low blast-radius number in those areas with suspicion.
If you have just inherited one of these repositories, start with the survey, because it is the part machines genuinely do faster: point Symvanta at the repo and the module map, the duplication list, and per-edit blast radius come back before the first billable week ends. Book a 15-minute demo