Vibes DIY
Vibes DIY / Blog
From the build log

The cruft isn't in the files — it's in the seams

Since agents started doing most of the typing here, features-per-week has gone way up. The natural fear is that "vibecruft" — dead code, duplicated helpers, TODO graveyards — is compounding at the same rate, silently. So we scheduled a housecleaning day: a deliberate discovery round over the whole monorepo, with one rule — identify candidates and discuss them before filing anything.

Branded title card: “files ✓ · seams ✗” over a duotone photo of a broom sweeping a floor.
We swept the rooms. The dust was in the doorframes.

The sweep: five explorers and a linter

The audit itself was cheap. Five read-only explorer agents fanned out in parallel, each with one lens: cross-package duplication, dead and vestigial code, CI/config cruft, documentation staleness, and architecture-level debt in the two biggest packages. Alongside them, a knip run for unused files, exports, and dependencies. Wall-clock cost: about half an hour of agents reading, then a conversation.

The first finding was the meta one: the dead-code linter couldn't run. Knip evaluates every workspace's vite config, and ours calls process.exit(1) when local HTTPS dev certificates are missing — so on any clean checkout, CI runner, or cloud session, the cruft detector dies with a certificate banner before analyzing a single file (#3310). The tool that guards against rot had itself quietly rotted out of reach.

The surprise: the files were (mostly) clean

We braced for the classic inventory: commented-out blocks, utils-old.ts, TODO archaeology. For the classic cruft signals, it just wasn't there. The dead-code explorer's audit-time sweep of the repo's TypeScript sources found roughly nine strict TODO/FIXME markers, no large commented-out regions, no .bak files, and no abandoned side-by-side rewrites. The architecture pass found clean layering — zero deep imports across the web-app/API boundary, shared types in exactly one package.

In hindsight this makes sense. At agent velocity, files have a short half-life. Every feature PR rewrites the code it touches, and review runs on every diff. Per-file rot never gets the quiet decade it needs to accumulate. (The oversized files we did find — a 3,062-line chat evento among them — are load-bearing god-files, a different disease than cruft.)

Get posts like this in your inbox

One email field. Real updates. No algorithm required.

Where the debt actually was

Everything real that the round surfaced lived in the connective tissue — the places no feature PR ever rewrites:

  • A package that didn't exist, with a live production deploy. vibes.diy/failback-homepage/ contained one README saying "this code has been removed" — while a production workflow still triggered on any push to that path, ready to run pnpm install && pnpm build against nothing and fail.
  • A publish workflow that could never publish. The use-vibes publish workflow selects its deploy environment by checking for core@s / core@p tag prefixes — but it only triggers on use-vibes@* tags. Both ternary branches are dead; every publish silently falls through to dev (#3307). Copy-paste from a sibling workflow, invisible for months because nothing fails — it just quietly does less than it claims.
  • Copies that drifted exactly where the comment said they couldn't. A useMobile hook byte-identical in two published packages. Doc types hand-mirrored with a comment saying they "mirror the runtime shape" — already divergent. And the CLI still carrying a private copy of streaming plumbing that was consolidated into a shared package whose header literally says "so the copies can't silently drift."
  • A hundred-plus references to deleted infrastructure. A Durable Object consolidation shipped a week earlier, deleting five DO classes. The classes were gone; the vocabulary wasn't — 107 references at the audit-time, pre-sweep count, including eleven console.error("DocNotify error:", …) log tags naming a class that no longer exists. Anyone tailing production logs was being pointed at a phantom.
  • Docs that lied to the next agent. The repo's own quick-reference test command silently ran the wrong suite in three load-bearing docs. An architecture doc still described that shipped DO consolidation as a future plan — which days earlier had convinced a session that a built feature didn't exist yet. For agent teams this is the sharpest edge: agents read the docs every session and believe them. A stale doc isn't inert reference material; it's an instruction actively steering work in the wrong direction.

The pattern: seams rot because nothing rewrites them. Workflows, package manifests, redirect files, and runbooks change only when someone changes them — and they fail silent, not loud. Meanwhile the migration that deleted those DO classes was reviewed as a code diff, and the comments, log strings, and docs referencing the old world weren't part of any diff.

Same-day cleanup, decisions in minutes

The other half of the experiment was the loop itself. The explorers produced a ranked candidate list; the owner ruled on it in a handful of one-line replies ("1 should deploy a simplified html version," "3 remove," "6 file a bug"). The human decided what, the agents decided how — and by end of day PR #3312 had merged: the failback package rebuilt as a self-contained static page (its first successful deploy verified live), orphans deleted, both drifted copies deduplicated, all 107 stale references rewritten, and the docs fixed. The bigger items became six labeled issues with remediation shapes spelled out, ready to be picked up one at a time — including publishing our Storybook, which the round had initially flagged as an orphaned package until discussion revealed the opposite call: keep it, ship it public.

One more seam got sealed on the way out: wiring knip into the standard check so unused dependencies — 91 of them, plus 51 dev dependencies — can't re-accumulate unnoticed.

The recipe

If your team ships at agent speed, the audit is worth stealing:

  1. Fan out read-only explorers by category — duplication, dead code, CI/config, docs, architecture — plus whatever automated tooling exists. Parallel agents make the whole-repo sweep an afternoon, not a sprint.
  2. Verify before you trust. Knip reported 729 unused files; most were entry-point config gaps. Every candidate got a by-hand reference check before action.
  3. Discuss before filing. A ranked list the owner can answer with one-liners beats thirty auto-filed issues.
  4. Execute small findings same-day, file big ones with a split shape. Deletion PRs are cheap while context is hot; god-file refactors deserve their own issues.
  5. Fix the docs in the same pass — for agent teams, stale docs are the most expensive cruft there is, because they don't just sit there. They get believed.

Build something worth cleaning up after

The parallel-explorer audit and the merge-on-green loop behind it are open source as beast-mode — steal the recipe for your own repo.

Start building →

Enjoyed this? Get the next post by email

One email field. Real updates. No algorithm required.

Prefer a feed? RSS · Atom