In 2024, YAGNI was a static analysis tool, not an agent. It generated reports. You ran it against your repository, received files and functions with zero callers, and decided what to do.
We built and tested that version with a few early collaborators, then saw that it missed the real problem. The list was easy. Everyone knew they had dead code. Nobody wanted to review 400 candidates individually, decide on each deletion, run each test, and write the PRs. That work was unwanted. A list only shifted the task from "find it" to "act on it" without lowering the total effort.
That was when we chose to build an agent.
What Linters Can and Cannot Do
Linters excel at their intended tasks: catching unused local variables, flagging unused imports, and finding obviously dead branches inside a function body. They run in milliseconds, fit into CI, and provide immediate, clean feedback during development.
A linter cannot decide whether to remove something across a repository. It works in a local scope or, at most, one file. It does not create a whole-repository call graph, compare it with runtime traces, measure coupling to assess removal blast radius, confirm that the full test suite passes after deletion, or open a pull request. Each task needs another tool or manual human effort.
Most dead code removal effort lies between "this looks unused" and "I trust this finding enough to commit the deletion." That interval needs context: the complete reachability picture, coupling structure, production execution history, and test results. Building that context for every candidate in a 400-candidate list is the bottleneck.
What an Agent Does Differently
The YAGNI agent handles each removal candidate as a task, rather than merely surfacing a signal. For a high-confidence candidate, with zero callers in the static call graph, zero production traces in the past 90 days, and coupling complexity below the threshold, it completes the removal: deleting dead functions and files that become empty, removing unnecessary imports, running the test suite, and opening a pull request with the analysis attached.
The engineer reviewing the PR need not perform the analysis. It appears in the PR description: why the agent judged the code dead, the test run result, and the coupling assessment. The engineer reviews the decision instead of rebuilding the reasoning from scratch.
For medium-confidence candidates, the agent creates a proposal marked: "this has zero static callers but the runtime trace window is short, so we are less certain." With the full context included, the engineer reviews it, makes the decision, and YAGNI carries out the chosen direction.
The Trust Problem
An agent proposing code deletions must address trust from the beginning. Even rare wrong deletions can undermine an engineer's ability to review quickly. With a non-trivial false positive rate, every PR becomes adversarial: the engineer must prove that this deletion is safe instead of trusting its accompanying analysis.
That is why YAGNI's initial design favored precision over recall. We would rather find 80% of dead code with high confidence than find 95% with a 5% false positive rate. Among 400 candidates, a 5% false positive rate produces 20 proposed wrong deletions. At that volume, engineers stop trusting the PRs and review them as if they had written them from scratch. The tool then creates work instead of reducing it.
The high-confidence tier, where automated PRs fit, aims to keep the false positive rate well below 1%. The medium-confidence tier goes to human review because we cannot provide that guarantee there.
The Scope We Did Not Build For
YAGNI is not meant to replace every form of code cleanup. We are not making a general refactoring tool or a code quality scorer. We are focused on identifying and removing dead code at a scale where manual review is the bottleneck.
With a 5,000-line codebase, you probably do not need YAGNI. You can read the whole thing in a few days. With a 500,000-line codebase that has accumulated dead code for years, manual review capacity fails before finding candidates does. That is the problem we built for.
What We Learned Building Version One
The report version taught us a lesson we still apply: confidence levels need to differ. At first, we treated every zero-caller finding as equivalent. Testing revealed a non-trivial false positive rate caused by dynamic dispatch, callback patterns, and serialization bindings that static analysis missed. Adding confidence tiers and requiring runtime signal agreement for the high-confidence tier brought the false positive rate to acceptable levels. The model came directly from the report version's failure modes.
It also showed us that PR format mattered more than expected. Engineers mainly interact with YAGNI through pull requests. PR description quality, analysis structure, and communication of uncertainty all affect review time. We spent significant time on the PR format as well as the underlying analysis, because a correct-but-hard-to-review PR does not solve the throughput problem.
The agent is still early. We handle some dead code categories imprecisely, and there are patterns we have not encountered yet. Still, choosing autonomous removal over richer reporting was right. Reports do not reduce the work; reviewed pull requests do.
Try YAGNI on your codebase. Free plan, no credit card required.
Get Early Access