Every category page for vibe coding tools ranks the same axis: how fast a prompt becomes a running app. Nothing on any of them says what the code is worth a month later, and that second number decides what the first one bought. This site is an unusually clean subject for the question — every line of it was produced by prompting an agent, none was typed into an editor in the ordinary way, and the history is complete. npm run check:durability reads all 46 commits and reports, line by line, what survived. 96% of it is still standing. That is the opposite of the expected result, and the interesting part is where the other 4% went. If you are choosing the agent rather than the prototyper, the assistants pillar is the decision above this one.
Key takeaways
- 57,537 lines were ever written into this repository; 55,065 are alive today — 96% survival across 290 text files and 31 days.
- The first prompt-to-app commit produced 65 files and 6,440 lines. 85% of those lines are still standing, and 63 of the 65 files still exist.
- 66% of files have never had a single line replaced. Median commits per file is 1.
- Rewriting is concentrated, not distributed: 1 file holds 50% of all replaced lines, 10 files hold 70%, 20 files hold 80%.
- The obvious hypothesis is wrong. Code touching the network, filesystem, env or request scope survives at 95% — identical to code touching none of them.
The short answer
Generated code does not decay; it gets replaced in a small, predictable set of places, and those places are the ones you were always going to own. Use vibe coding tools for the leaves — presentational components, one-off pages, the parts of an app nobody returns to. Expect to write the spine yourself: routing, middleware, configuration, and anything whose shape is decided by a requirement that has not stopped moving.
The number that should change your buying decision is not survival, which is high everywhere. It is revisit rate, which is 24% for files under 200 lines and 55% for files over it.
npm run check:durability # → 46 commits, 2026-07-22 to 2026-08-23, 290 text files # → 57,537 lines written, 55,065 alive — 96% # → 191 of 290 files (66%) have never had a line replaced # → top 10 files hold 70% of every replaced line
What was measured
Three numbers per file, all from git and none from memory.
- Lines ever written —
git log --follow --numstatper path, summed across every commit. This is every line the agent emitted into that file, including the ones it later replaced. - Lines alive —
git blame --line-porcelainagainstHEAD, attributing each surviving line to the commit that wrote it. - First-draft survival — of the lines alive, the share still carrying the SHA of the commit that created the file.
Files are grouped into three areas: code (app/, components/, lib/, db/, middleware and configs), instruments (scripts/ — the measurement harnesses this site publishes), and prose (content/ plus the three governing Markdown documents). Binaries, public/, assets/ and the lockfile are excluded; they carry no authored lines and would swamp the totals.
| Area | Files | Written | Alive | Survives |
|---|---|---|---|---|
| code | 84 | 8,066 | 7,638 | 95% |
| instruments | 128 | 23,850 | 23,616 | 99% |
| prose | 72 | 25,379 | 23,606 | 93% |
| all | 290 | 57,537 | 55,065 | 96% |
96% survives, and that is not the good news it sounds like
The headline is inflated by write-once files, and saying so is the honest reading. 186 of 290 files — 64% — were never revisited at all. For those, first-draft survival is 100% by construction, because there was never a second draft. Most of them are published articles, which are written, reviewed and left alone.
Restrict to the 104 files that were touched more than once and the picture changes:
| Area, revisited files only | Live lines | Still from the creating commit |
|---|---|---|
| prose | 19,655 | 78% |
| code | 3,954 | 71% |
| instruments | 2,369 | 55% |
The instruments are the worst survivors and they are the most carefully written code here. That is not a contradiction. Each one is a measurement script whose first version was wrong in a way that only appeared when its output was read — the debugging harness scored two TypeScript faults as clean because Node refused to spawn tsc.cmd; the testable-surface classifier called a database route pure. Those corrections are exactly what a 55% first-draft survival rate looks like from the inside, and they are the healthiest churn in the repository.
The first prompt-to-app pass, 31 days later
The cleanest analogue to what a vibe coding tool hands you is this repository's first commit: one session, one prompt sequence, a complete Next.js site with routing, layout, content loading and styling.
| First commit | Value |
|---|---|
| Text files created | 65 |
| Lines added | 6,440 |
| Files still tracked, 31 days later | 63 |
| Its lines still standing | 5,485 (85%) |
85% of the first pass is still running the site. Two of its 65 files are gone. Whatever else is true about generated-first code, "you will throw it away and start again" is not what happened here, and it is the claim most often made against these tools.
The 15% that went is worth naming, because it is not random. app/[category]/page.tsx lost 63 lines when pagination was extracted into lib/pagination.ts. app/layout.tsx lost 24 when the navbar was restructured to hide itself on admin routes. app/sitemap.ts lost 11 when the canonical origin gained its www prefix. Every one is a structural decision that could not have been made in the first session because the thing it depends on did not exist yet.
Rewriting is concentrated, not distributed
This is the finding that transfers to any repository:
| Files | Share of all 2,472 replaced lines |
|---|---|
| top 1 | 50% |
| top 3 | 58% |
| top 10 | 70% |
| top 20 | 80% |
One file — roadmap.md, revised across 31 of the 46 commits — accounts for half of every line ever replaced in this project. Strip it out and the code's churn is a rounding error.
191 of 290 files have not had a single line replaced. The distribution is not a bell curve with a long tail; it is a near-empty field with a small number of very hot files in it. That is the same shape the review-scope measurement found in the import graph, where 9 of 76 modules held 25.6 kB reaching 613.5 kB, and it suggests a general rule about generated codebases: the cost is never spread across what was generated, it sits in a handful of files you can name in advance.
| File | Written | Alive | Survives | Commits |
|---|---|---|---|---|
app/tags/[tag]/page.tsx | 125 | 66 | 53% | 2 |
.env.example | 65 | 37 | 57% | 9 |
middleware.ts | 136 | 80 | 59% | 3 |
app/[category]/page.tsx | 227 | 164 | 72% | 3 |
app/layout.tsx | 121 | 97 | 80% | 3 |
Routing, middleware, layout, configuration. Not a component in the list.
What predicts a rewrite, and what does not
The hypothesis going in was that code touching the outside world would churn hardest — that files reaching the network, the filesystem, process.env or a request scope would be rewritten more than self-contained ones. It is intuitive, it fits the "generated code is fine until it meets reality" story, and it is wrong.
Crossing this measurement against the side-condition classifier gives:
| Split | Files | Survives | Ever revisited |
|---|---|---|---|
| touches the outside world | 44 | 95% | 50% |
| touches none of it | 33 | 95% | 36% |
Identical survival. The only band that separates at all is fs, where 9 of 10 files were revisited — and that is one number over ten files, which is a hint and not a result.
Size is the signal that survives contact with the data. Files with 200 or more lines ever written were revisited at 55%; files under it at 24%. Even that predicts being touched again, not being deleted, and the plainest reading is the least exciting one: big files are where the work is, so big files get more work.
Four files that were deleted entirely
Four paths were generated, committed, and then removed with a survival rate of zero:
lib/geo.ts removed 2026-07-23 components/category/FilterTabs.tsx removed 2026-07-24 components/category/Pagination.tsx removed 2026-07-24 lib/posts.ts removed 2026-07-24
All four went within 48 hours of the first commit, and all four are the same kind of mistake: a feature invented by the generator rather than asked for. lib/geo.ts was geolocation nothing needed. FilterTabs was a filtering UI for categories that have no filters. lib/posts.ts was a second content loader alongside lib/mdx.ts.
That is the real failure mode of prompt-to-app generation, and it is not decay — it is scope. A tool asked to produce a working site produces a plausible one, and plausible includes things you did not ask for. The cost is paid immediately, in the first two days, by a human reading what arrived.
What this says about vibe coding tools
bolt.new, Lovable, v0 and Replit AI are not tested here and this article will not pretend otherwise — none is installed on this machine and no account exists for any of them. What they share with the process that built this site is the artifact: code written from a prompt rather than typed, at a volume no one reviews line by line.
On that shared artifact, the measurements above support three things:
- The durability objection is weak. 96% overall, 85% of the first pass, 66% of files never touched. If a tool's output resembles this history at all, "it all gets rewritten" is not the reason to avoid it.
- The scope objection is strong and it lands immediately. Four invented files in 48 hours, all deleted. The review cost of prompt-to-app output is front-loaded, and it is a reading task, not a debugging one.
- The parts they do worst are the parts they show best. Routing, layout, middleware and configuration are what a prompt-to-app demo renders in ninety seconds, and they are the five files at the bottom of the survival table. A generated component survives; a generated route boundary gets rewritten as soon as a second requirement arrives.
Which is a narrower and more useful recommendation than the category usually gets: use them to get a shape on screen, and plan to own the four or five files that decide how requests actually flow.
How to measure your own
- Run blame and numstat over your own history before you argue about this. The whole measurement is two git commands per file and the arithmetic is subtraction. Any repository with a real history can answer this question about itself in an afternoon.
- Report the revisit rate, not just survival. Survival was 93–99% in every slice here and separated nothing. Revisit rate separated everything that separated at all.
- Exclude the lockfile and binaries explicitly.
package-lock.jsonalone would have added roughly 3,900 lines to the first commit and moved every ratio. - Check your rename handling.
git log --followtracks one path through a rename and rename detection is heuristic, so a file that moved can lose its history and report more lines alive than were ever written. That is the guard this script exits non-zero on. - Do it before the codebase is a year old. 31 days is a short window and it is honest to say so; it is also long enough for 2,472 lines to have been replaced, which was enough to find where they were.
Common mistakes we made
- We led with the wrong number. The first version of this measurement reported 96% survival as the headline and had nothing to say, because 96% is what you get when 64% of files are write-once articles. The finding only appeared after splitting revisited files out.
- We tested a hypothesis that failed and kept it. The boundary-code prediction was wrong — 95% against 95% — and reporting it is more useful than the confirmations, because it is the intuition most people bring to this question.
- We counted the lockfile at first. The first commit read as 10,379 lines until
package-lock.jsonand the PDF were excluded, which overstated the first pass by 61% and would have made its 85% survival look like 53%. - We assumed churn meant a mistake. The instruments have the worst first-draft survival in the repository and they are the code most worth trusting, because every rewrite was a correction found by reading the output. Low survival is a signal about attention, not about quality.
What we are not claiming
No vendor is measured. One agent, one operator, one repository, 31 days. bolt.new, Lovable, v0 and Replit AI produce code under different constraints and their individual output quality is not in evidence here.
Git's line accounting is crude. A moved block is a deletion plus an addition; a one-character fix is a whole line rewritten. Both understate survival, so 96% is a floor rather than a ceiling.
Prose and code are mixed in the totals. They are reported separately for that reason — the 93% prose figure is dominated by one document revised 31 times and says nothing about software.
Survival is not correctness. Every number here counts lines that are still present. None of them says those lines are right, and this repository has published corrections to prove the two are different.
Conclusion
Judge vibe coding tools on the review cost of what arrives, not on whether it lasts — the durability panic is not supported by 46 commits of prompt-generated code, and the scope problem showed up inside 48 hours. Generate the leaves and read the output the same day, especially the files you did not ask for. Then keep the routing, middleware and configuration in your own hands, because on this evidence those are the five files you will rewrite regardless of who wrote them first. If you are weighing the tools rather than the output, the ledger for that decision splits the artifacts by who they were actually for.
Frequently asked questions
Does vibe coded software have to be rewritten?
How much of AI generated code survives?
Is vibe coding good for production apps?
What predicts which generated code gets rewritten?
Are bolt.new, Lovable, v0 and Replit AI tested here?
Muhammad Kashif
Founder and editor of Devventa, covering AI coding assistants, Next.js and the modern AI development stack.




