PHPackages                             renfordt/prune - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. renfordt/prune

ActiveLibrary

renfordt/prune
==============

Find orphaned and unused PHP classes in your project

04↑650%[2 PRs](https://github.com/renfordt/Prune/pulls)PHPCI passing

Since Mar 24Pushed 2d agoCompare

[ Source](https://github.com/renfordt/Prune)[ Packagist](https://packagist.org/packages/renfordt/prune)[ RSS](/packages/renfordt-prune/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (3)Used By (0)

Prune
=====

[](#prune)

A CLI tool that finds orphaned and unused PHP classes in your project using static AST analysis.

Prune parses your PHP files with [nikic/php-parser](https://github.com/nikic/PHP-Parser), collects all class declarations and references, then reports classes that are declared but never referenced anywhere in the scanned codebase. It also supports detecting unused [Blade](https://laravel.com/docs/blade) views in Laravel projects.

Installation
------------

[](#installation)

```
composer require --dev renfordt/prune
```

Requires PHP 8.4+.

Usage
-----

[](#usage)

Scan one or more directories:

```
php vendor/bin/prune src
php vendor/bin/prune src app lib
```

### Output formats

[](#output-formats)

By default, results are printed as a console table. You can switch to JSON or HTML:

```
php vendor/bin/prune src --format=json
php vendor/bin/prune src --format=html
```

JSON and HTML reports are written to `.prune/report.json` or `.prune/report.html` in your project directory. Use `--output` to override the path:

```
php vendor/bin/prune src --format=json --output=orphans.json
```

### Blade view analysis

[](#blade-view-analysis)

Prune can detect unused Blade views by scanning for `@include`, `@extends`, `@component`, and similar directives, as well as `view()` calls in PHP code.

Blade analysis is enabled by default. To run Blade analysis only (skipping class detection):

```
php vendor/bin/prune src --blade
```

### Exit codes

[](#exit-codes)

Prune exits with code **1** if any orphans are found, and 0 if the codebase is clean. This makes it suitable for CI pipelines.

Configuration
-------------

[](#configuration)

Create a `prune.neon` (or `prune.neon.dist`) file in your project root:

```
parameters:
    paths:
        - src
        - app
    excludePaths:
        - vendor
        - tests
    extensions:
        - php
    format: console
    blade:
        enabled: true
        viewPaths:
            - resources/views
        excludeViews:
            - errors.404
            - errors.500
```

OptionDefaultDescription`paths``[src]`Directories to scan for PHP files`excludePaths``[vendor]`Paths to exclude from scanning`extensions``[php]`File extensions to include`format``console`Output format (`console`, `json`, `html`)`blade.enabled``true`Enable Blade view orphan detection`blade.viewPaths``[resources/views]`Directories containing Blade templates`blade.excludeViews``[]`Blade view names to ignore (dot notation)You can also point to a custom config file:

```
php vendor/bin/prune src --config=custom-prune.neon
```

How it works
------------

[](#how-it-works)

1. **File discovery** -- Symfony Finder collects all PHP files in the configured paths
2. **AST parsing** -- Each file is parsed into an abstract syntax tree using nikic/php-parser
3. **Class map** -- All declared classes, interfaces, traits, and enums are recorded with their fully qualified names
4. **Reference scanning** -- All references to classes are collected: `extends`, `implements`, `new`, type hints, static access, `instanceof`, `catch`, attributes, and trait `use` statements
5. **Orphan detection** -- Any declared class that appears nowhere in the reference set is reported as an orphan
6. **Blade analysis** (optional) -- Blade templates are scanned for view references via directives and PHP `view()` calls; views with no references are reported

Limitations and risks
---------------------

[](#limitations-and-risks)

Prune performs **static analysis only**. It does not execute your code, so it cannot detect references that only exist at runtime. Be aware of the following before deleting classes based on its output:

- **Dynamic instantiation** -- Classes created via `$class = 'App\\MyClass'; new $class()`, `app()->make(...)`, or similar patterns are invisible to static analysis. This is common in service containers, factories, and plugin systems.
- **String-based references** -- Class names passed as strings (e.g. to configuration 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 that uses `ReflectionClass`, `class_exists()`, or `__call`/`__callStatic` to interact with classes dynamically will not be tracked.
- **External consumers** -- If your project is a library, its public API classes may appear unused because the consumers live outside the scanned directories.
- **Framework conventions** -- Some frameworks auto-discover classes by convention (e.g. Laravel commands, event listeners, policies, or Nova resources). These classes may have no explicit references in your codebase.
- **Blade analysis scope** -- Blade view detection only covers `@include`, `@extends`, `@component`, `@each`, `@livewire`, and `view()` calls. Custom directives or JavaScript-driven component rendering are not tracked.
- **Generated code** -- Classes generated at build time or by code generators may not exist at scan time, causing their references to be flagged.
- **Scope of analysis** -- Only files within the configured `paths` are scanned. If a class is referenced in a file outside those paths (e.g. in a test suite or a script not under `src/`), it will still be reported as orphaned.

**Recommendation:** Treat Prune's output as a starting point for investigation, not as a delete list. Review each reported class before removing it.

License
-------

[](#license)

MIT

###  Health Score

23

—

LowBetter than 28% of packages

Maintenance65

Regular maintenance activity

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity14

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/1edb79f2a1fcd61016ec9a5b65183e1f6e7852a4b1f9a5bd6f69c6160366f22c?d=identicon)[renfordt](/maintainers/renfordt)

---

Top Contributors

[![renfordt](https://avatars.githubusercontent.com/u/699163?v=4)](https://github.com/renfordt "renfordt (12 commits)")

### Embed Badge

![Health badge](/badges/renfordt-prune/health.svg)

```
[![Health](https://phpackages.com/badges/renfordt-prune/health.svg)](https://phpackages.com/packages/renfordt-prune)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
