Limitations & Risks
Prune performs static analysis only. It does not execute your code, so it cannot detect references that exist only at runtime. Treat its output as a list of candidates to investigate, never as a confirmed delete list.
Always review before deleting! Removing a class that Prune flagged — without checking — can break your application. Read this page before acting on a report.
Things Prune cannot see
Dynamic instantiation
Classes created from a variable or resolved by a container are invisible:
$class = 'App\\MyClass';
new $class();
app()->make(MyService::class); // resolved at runtime
This pattern is common in service containers, factories, and plugin systems.
String-based references
Class names passed as plain strings — to config arrays, route definitions, or event listeners — are not detected. Laravel service providers, middleware stacks, and config files frequently reference classes this way.
Reflection and magic methods
Code using ReflectionClass, __call, or __callStatic to interact with classes dynamically is not tracked. (Note: class_exists() and similar functions are tracked, but only for fully qualified string names — see What Gets Detected.)
External consumers
If your project is a library, its public API classes may look unused because the consumers live outside the scanned directories.
Framework auto-discovery
Some frameworks discover classes by convention — Laravel commands, event listeners, policies, Nova resources, and so on. These often have no explicit reference in your own code.
Generated code
Classes produced at build time or by code generators may not exist when Prune scans, which can cause references to them to be missed.
Scope of analysis
Only files inside the configured paths are scanned. If a class is referenced solely from a file outside those paths — a test suite, a script not under src/ — it will still be reported as orphaned. Use excludePaths, additional paths, or referencePaths to widen or narrow the scope deliberately.
Blade analysis scope
Blade view detection only covers @include, @extends, @component, @each, @livewire, <x-…>/<livewire:…> tags, and view()/Route::view() calls. Custom directives, dynamically named views, and JavaScript-driven component rendering are not tracked.
Recommendation
- Run Prune.
- For each reported class or view, search the codebase (and any consumers) for dynamic, string-based, or convention-driven uses.
- Add anything that is intentionally referenced indirectly to
excludePaths/excludeViews, or widenreferencePaths. - Only then remove what remains genuinely dead.
For tuning which paths and views are considered, see the Configuration File.