innmind/file-watch
Watch files and directories for changes from PHP. innmind/file-watch surfaces filesystem events when files are created, modified, or deleted, making it useful for hot reloading, build watchers, and automation that must react to file changes.
Dev-experience / DX investment. If your roadmap includes a "watch mode" — re-running tests, static analysis, or asset builds on save — this package is one way to build it in PHP rather than shelling out to Node or entr. This is a feature decision, not a platform decision: the buyer is your own engineers or the developers who consume a package you ship.
Production file-drop ingestion (the higher-value case). Any product that ingests files arriving from outside the app — partner CSV/SFTP drops, bank statements, EDI feeds, lab results, uploaded media landing in an object-store-synced mount — needs to notice "a new file appeared" and act. Today that's usually cron polling with last_modified bookkeeping, which produces duplicate processing, missed files during downtime, and support tickets about latency. A PHP-native watcher is a direct lever on your ingest SLA and on the "why hasn't my file shown up yet?" ticket volume.
Build vs. buy, three ways. For any file-change trigger you now have three options, and the PM owns the tradeoff:
watchexec, inotifywait, systemd path units) — battle-tested, but adds a system dependency your customers or your managed-hosting platform may not allow.This package only makes sense in the narrow third column. Framing your recommendation as "which of these three, and why" is the actual product decision.
Long-running worker ergonomics. If you run Octane, FrankenPHP, or RoadRunner, hot-reloading config, feature flags, or translation files without a worker restart is a small but real reliability win. Niche, but it's a legitimate roadmap item this package can inform.
Roadmap signal on the opportunity score. Opportunity 44.55 with 1 star and 0 dependents says: little competition and little demand. That's a market-of-one. Do not build a product strategy on it; do consider a spike if a concrete internal need already exists.
Consider it when:
watchexec, no inotify binary — because you ship to customer-controlled or managed hosting where you cannot install system packages.innmind/immutable, innmind/io) and the functional abstractions are a fit rather than a tax.Look elsewhere when:
npm run watch, Pest's --watch, and php artisan serve already solve this. Buying here is strictly worse.ext-inotify. Verify the polling fallback's interval against your latency target before you commit; a 5-second poll dressed up as a watcher will disappoint.Maybe/Either/immutable collections with no Eloquent or container integration is a real onboarding cost — likely more than the ~50 lines of stat() polling you'd write yourself.composer audit, read the source, and pin the version.Decision gate I'd set: timebox a one-to-two-day spike behind our own FileWatcher interface, with a polling adapter as the default implementation and this package as a second adapter. If the spike doesn't beat the polling adapter on latency or code volume, drop it — we keep the interface and lose nothing. Also constrain watched paths and validate file ownership: "execute code when a file changes" is an execution vector if the watched directory is writable by anything other than us.
For executives (one paragraph): We have a recurring need to react when a file lands — partner data drops, uploaded documents, content exports — and today we handle it with cron polling, which is slow and occasionally reprocesses or misses files. There's a small MIT-licensed PHP library that does this in-process. It's cheap to trial (about two engineer-days) but it's a one-person project with no adoption, so I'm not recommending it for anything revenue-critical. My recommendation: fund the two-day spike, wrap it behind an interface we own so it's swappable, and use it only for internal tooling or a dev-time watch mode. For the production ingest path, the cheaper and safer answer is a queue with idempotent file claiming, possibly plus a systemd path unit or watchexec sidecar — no new library dependency at all.
For engineering leads: This is a thin watcher abstraction, not a Laravel package — no service provider, no config, no supervisor story. We'd write the integration, the process supervision, and the failure handling ourselves. What we get in exchange is a PHP-native callback on file change with no external binary, which is genuinely useful if we ever ship to locked-down hosting. The cost is a dependency on Innmind's IO and immutable abstractions, which nobody on the team currently uses. Mitigation: define App\Support\FileWatcher with poll(), inotify(), and optionally innmind() adapters; default to poll(), feature-test both, and treat the third-party adapter as an experiment. Also note the risk profile — 1 star, 0 dependents, single maintainer, and a release date that needs verifying on Packagist before we pin it.
The trade in one line: if the spike works we get sub-second file-triggered workflows without leaving PHP; if it doesn't we lose two engineer-days and keep a polling implementation we would have written anyway — which is why the interface boundary, not the library, is the actual deliverable.
How can I help you explore Laravel packages today?