Using AI agents to clean up dead code, stale packages and feature flags
A NimblePros Halloween post walks through removing the accumulated cruft of long-lived .NET codebases: unused private members, unreferenced public types, unused or vulnerable NuGet packages and stale feature flags. The method pairs compiler analyzers and dotnet CLI checks with an AI agent that investigates edge cases, guided by a reusable skill file. It is a practical playbook for teams who never find time to clean up.
Key points
- Set EnforceCodeStyleInBuild to true and raise IDE0051, IDE0052 and IDE0060 to warning so unused private code surfaces during dotnet build.
- Run dotnet list package with --vulnerable, --deprecated and --outdated; NuGet Audit also reports vulnerable transitive packages as NU1901 to NU1904.
- Public types can be used invisibly through assembly scanning, configuration binding, serialization, conventions or InternalsVisibleTo, so check those first.
- A feature flag that has the same value in every environment is a ghost flag candidate; remove the dead code path and the flag from all configuration files.
- Require every finding to carry evidence and a confidence level, and have a human review the report before anything is deleted.
Long-lived codebases accumulate dead methods, unused packages, stale feature flags and commented-out blocks that slow reviews and complicate refactors. The author argues that this cleanup is tedious and repetitive, which makes it a good match for AI coding agents, as long as humans make the final removal decisions. The core principle is that tools find candidates, agents investigate them, and humans decide.
On the tooling side, the post enables EnforceCodeStyleInBuild and raises IDE0051, IDE0052 and IDE0060 to warnings, so unused private members show up in dotnet build. For dependencies it combines dotnet list package checks with NuGet Audit and has an agent test whether a reference is really used. A read-only ghost-hunt skill file produces a report with evidence and confidence levels before anything is removed.
Real-world use
- Cleaning up a feature flag that has been on everywhere for a year in a multi-year ASP.NET Core API, where both pricing code paths still exist.
- Simplifying a solution whose Newtonsoft.Json to System.Text.Json migration finished, but the old package reference is still in the csproj.
- A team preparing for a security audit that needs vulnerable and deprecated NuGet packages removed.
Why it matters
Dead code, zombie packages and stale flags quietly enlarge the attack surface and slow every change; a read-only agent survey with evidence lets you clean them up in reviewable pull requests.