Skip to main content
Finds unused types, members, and files. roe builds a map of what references what across your solution, starting from known entry points, and reports anything that’s unreachable.

Options

Use --root for symbols that are only reached in ways roe can’t see, such as string-based reflection:
Use --library for a project that’s consumed outside the workspace — for example, a Unity project referencing the built DLL — so its public API is never flagged even though no executable in the workspace uses it:
Both can also be set persistently in a config file. A config’s entryPoints glob list roots whole files rather than single symbols — every declaration in a matching file counts as used, along with everything it references — see Entry-point files. And a config’s deadCode.ignore glob list drops every dead-code finding in matching files without affecting the other commands — see Suppressing findings.

What counts as an entry point

Entry points are never flagged, and reachability is traced from them: static Main and top-level statements, ASP.NET controllers, test methods, declarations carrying attributes, reflection-scan contracts, the public API of packable and library-mode projects, and generated files. The full list is on Entry points and roots.

What’s never flagged individually

To keep false positives rare, roe is tuned so that when in doubt, code is marked used — a missed finding is cheap, a wrong one is a bug. That means constructors, operators, indexers, and finalizers (invoked structurally); override members and explicit interface implementations (invoked via dispatch); members satisfying an in-source interface; visible members of types implementing external I-prefixed interfaces; and extension methods are never reported on their own. Public auto-properties and enum members are treated as serializer fodder and skipped by default — opt in with --aggressive.