Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Patrol Laravel Package

nunomaduro/patrol

Patrol is a Laravel package by Nuno Maduro for monitoring your application's health and performance. It provides an elegant dashboard to track slow requests, queries, and exceptions, helping you spot issues before they affect users.

View on GitHub
Deep Wiki
Context7

Getting Started

Patrol is a dev-only Composer binary, not a Laravel package. There is no service provider, no facade, no config publish step, and no runtime footprint. You install it, run it from your project root, and read the report it prints about your composer.json / composer.lock.

Install, per project, pinned:

composer require --dev nunomaduro/patrol

Do not install it globally. Patrol inspects the project it is executed from; a global binary makes it trivially easy to audit the wrong root and get a misleadingly clean report.

First run:

vendor/bin/patrol --help    # confirm the binary boots on your PHP version and see the real flag surface
vendor/bin/patrol           # the default report

Where to look first, in order of usefulness:

  1. vendor/bin/patrol --help — this is the authoritative documentation. The README is thin.
  2. vendor/nunomaduro/patrol/src/ — the source is a handful of Laravel Zero console commands. Reading it for fifteen minutes is genuinely faster than hunting for docs, and it's the only reliable way to learn the exact exit codes and what each check actually inspects.
  3. Your own composer.json → require-dev — confirm the constraint is pinned (^1.0 on a single-maintainer package is a liability).
  4. Any patrol.php / config file the version you installed supports, if --help mentions one.

Verify what it actually reports before you build process around it. The available write-ups disagree: one describes dependency hygiene via unused package detection (static inspection of your codebase against composer.json), the others describe outdated packages plus security advisories. That ambiguity is itself the first thing to resolve — run it once on a repo where you already know the answer (you know one package is outdated, or one is obviously unused) and see whether it says so. Whatever --help and the source say is the truth; the marketing copy is not.

Canonical first use case: wire it into CI as a reporting step on day one, not a gating step. Run it right after composer install, archive the output as an artifact, and leave it non-blocking until you've confirmed both the signal-to-noise ratio on your real dependency graph and the exit-code contract.

# .github/workflows/deps.yml
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/patrol || true
  # capture stdout to a file and upload-artifact it

Implementation Patterns

Wrap it in a Composer script so nobody invokes it ad hoc. Ad-hoc invocation means inconsistent flags and reports nobody reads.

{
  "scripts": {
    "patrol": "patrol"
  }
}

Then composer patrol is the single entry point locally and in CI. Add a Makefile target only if the rest of your team already lives in make.

Local workflow — the pre-upgrade pass. The highest-value moment to run Patrol is before estimating a Laravel or PHP runtime upgrade, not during it. Unused or stale packages pin transitive constraints and generate upgrade work for code nobody calls. Run it, export the list into the upgrade ticket, and shrink the graph first so the estimate reflects the real job.

Scheduled nightly CI, published, non-blocking. The correct home is a tech-debt / platform-health track:

on:
  schedule: [{ cron: '0 3 * * *' }]
jobs:
  patrol:
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.3' }
      - run: composer install --no-interaction --prefer-dist --no-progress
      - run: vendor/bin/patrol 2>&1 | tee patrol-report.txt
      - uses: actions/upload-artifact@v4
        with: { name: patrol-report, path: patrol-report.txt }

Note the deliberate absence of || true and of gating: pipe through tee so the step's own exit status is decided by tee, not by Patrol, while you're still learning its behaviour. Once you understand the exit codes, choose explicitly — either || true (advisory forever) or remove the pipe (real gate).

Run it in parallel with the native tools for a defined window. Two sprints is enough. Diff Patrol's findings against:

composer outdated --direct
composer audit
composer why-not laravel/framework ^11.0

If Patrol surfaces nothing that composer audit and composer outdated miss, retire it — the native commands are maintained by the Composer team and are the authoritative source. If its report materially improves review ergonomics (a readable, consolidated list per cycle), keep it strictly as a presentation layer on top of native tooling, never as a replacement.

Triage loop — findings are hypotheses, not verdicts. The only pattern that survives contact with a real codebase:

  1. Report lands as a CI artifact; a named engineer owns reading it each cycle.
  2. Each candidate becomes a ticket with a link to the artifact line.
  3. Removal happens in an isolated PR, capped at a few packages per week, with the full test suite green.
  4. Record the outcome (removed / kept, and why) so next quarter's report doesn't re-litigate the same package.

Without step 1's named owner and step 4's ledger, the report is noise and the job gets muted within a month.

Use it as one input among several, not as the dependency-risk source of truth. Adjacent tools, each doing a different job:

Concern Tool
Outdated direct deps composer outdated --direct
Known advisories composer audit
Unused packages Patrol / composer-unused
Licenses, SBOM CycloneDX/Syft, license policy tooling
Why is this installed composer why, composer depends

PHP version matrix. Pin one Patrol version and check composer.json's PHP constraint against your runtime matrix. Do not let the dependency bot bump Patrol independently of your matrix — the failure mode is the job dying on a runtime upgrade rather than the tool reporting anything useful.

Gotchas and Tips

Static analysis breaks on dynamic resolution — this is the big one. If your codebase resolves classes by string, every "unused" verdict is a guess and some of those guesses are wrong:

  • app()->bind('foo', 'App\Services\Foo') and service-provider string bindings
  • Config-driven class names (config('services.driver') → App\Drivers\Stripe)
  • Laravel package auto-discovery (the package is used, just never imported by name)
  • Morph maps, event/listener string registrations, queue $connection/$queue class strings

Treat each result as a hypothesis requiring a human reviewer. Never automate removal. The removal PR must be test-covered, because the tests are the only thing that will catch the case where the class was reachable via a string you didn't grep for.

Confirm the exit codes before gating anything. Run it against a deliberately broken repo (force an outdated constraint, or a known-vulnerable pinned version) and check echo $?. Tools that print a nice table but exit 0 on findings are normal and fine — but you must know, or your gate is decorative. Conversely, a tool that exits non-zero on network failure will block unrelated merges; handle that case explicitly.

Advisory data comes from an external endpoint. That means (a) your CI needs egress to Packagist and the advisory source, and (b) an endpoint outage produces either a false pass (silent green — the worst outcome for a security-adjacent check) or a hard failure. Decide which you prefer, and say so in the runbook. Stale advisory data producing a false negative manufactures false assurance; if you present this to a security audience, present it as a convenience view over composer audit, not as coverage.

Pin the version and budget for owning it. 280 stars, zero dependents, single maintainer, an overall score of 2.33. Expect to own upgrades and eventually a replacement. Keep the fallback documented in the same runbook: composer-unused + composer audit. The mitigating factor is that dropping Patrol requires zero changes to application code — it touches nothing at runtime.

It's a Laravel Zero app, so it brings its own dev dependency tree. You are adding transitive require-dev packages (including Symfony Console components) to your lock file with a tool whose purpose is dependency hygiene. That's ironic but harmless — as long as it stays in require-dev and your production install uses composer install --no-dev. Verify that, and verify nothing in your autoload classmap picks it up.

Monorepos and path repositories will produce murky results. Package-to-usage mapping degrades badly when lock files are partial or packages are symlinked locally. If you're in that situation, scope the run to a single, self-contained package directory rather than the monorepo root, or skip the tool.

Always run from the project root. The report is about the composer.json in the current working tree. A cd into the wrong directory in a CI step or a make target silently audits the wrong thing — and usually reports "all clean," which is exactly the wrong signal.

Prefer text output plus human review over scraping. If --help shows no --format=json, don't build brittle grep/awk parsing on top of a formatted table — it will break on the next patch release and you'll be debugging your parser instead of your dependencies. Archive the raw text, link it from the ticket, and let a human read it. If a JSON flag exists, use it and store the payload.

Treat the tool's own staleness as the first finding. composer outdated nunomaduro/patrol — if the pinned version is far behind and upstream has gone quiet, that's your argument for retiring it, and you should make that call before anyone starts depending on the report.

Frame it internally as reversible. Dev-only, no config, no runtime coupling, one-line install and one-line removal. That's the honest pitch, and it's also the reason not to make it load-bearing for dependency or security governance — keep composer audit as the blocking control and let Patrol be the readable summary you actually look at.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager