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

Laravel Inotify Laravel Package

octopyid/laravel-inotify

View on GitHub
Deep Wiki
Context7

Getting Started

Requirements: Linux with inotify-tools installed (sudo apt install inotify-tools / apk add inotify-tools). Verify with inotifywait --help. This package is a thin wrapper around the inotifywait binary, so if the binary isn't on the PATH of the PHP process, nothing works. macOS and Windows are not supported (no FSEvents / ReadDirectoryChangesW backend).

Install:

composer require octopyid/laravel-inotify
php artisan vendor:publish --provider="OctopyID\Inotify\InotifyServiceProvider"

Because the package is archived (last release 2022-06-28), pin it in composer.json and commit composer.lock immediately. Do not run composer update on a Laravel 10/11 app without checking composer.json constraints in vendor/octopyid/laravel-inotify — the Illuminate constraints are almost certainly capped at ^8.0|^9.0.

Where to look first, in order:

  1. vendor/octopyid/laravel-inotify/src/ — the whole package is a handful of files. Read the command class and the watcher class before trusting the README.
  2. config/inotify.php (after publishing) — the paths/events/ignore shape.
  3. php artisan list | grep inotify — finds the shipped console command (typically inotify:watch).
  4. The README.md on GitHub — it's the only documentation, and method names in it are authoritative over anything else.

First use case (five minutes): point the watcher at storage/logs and echo new lines, or at app/ and print the event name + path. That confirms three things at once: the binary is reachable, the config is loaded, and the event format parses. Get that green before wiring handlers.

# sanity check outside Laravel first — this is what the package shells out to
inotifywait -m -r -e create,modify,delete,move --format '%e %w%f' app/

If that prints events and the artisan command doesn't, the bug is in your config or the PHP process environment, not in inotify.

Implementation Patterns

1. Config-driven watchers for repeatable, committed behavior. Keep the paths and event lists in config/inotify.php so the watcher is reproducible on every developer machine. Reserve inline facade usage for one-off scripts in tinker.

2. Treat the watcher as a dispatcher, not a worker. The watcher is a single long-running PHP process. Doing real work inside the callback (running a full test suite, an HTTP call, an image resize) blocks every subsequent event. The pattern that scales:

// callback should be cheap and idempotent
Inotify::watch(base_path('storage/app/inbox'))
    ->onCreate(fn (string $path) => ImportFileJob::dispatch($path)->onQueue('imports'));

3. Cache-busting recipes. These are the day-to-day wins and each is two lines:

  • Blade changed → Artisan::call('view:clear') (avoids the "my edit didn't show up" 15-minute rabbit hole).
  • config/*.php changed → Artisan::call('config:clear').
  • routes/*.php changed → Artisan::call('route:clear').
  • .env changed → Artisan::call('config:clear') plus a note to restart Octane/queue workers, because env changes don't reach already-booted processes.

4. Poor-man's dev loop. Watch app/, tests/, routes/ and shell out to vendor/bin/phpunit --filter or vendor/bin/pint --dirty. Debounce by tracking the last-fired timestamp per path and skipping anything inside 300–500 ms. This is the single most useful thing the package does, and it's also the thing spatie/phpunit-watcher and Vite's own watcher already do better.

5. Event-driven integration for inbound files. A drop folder (storage/app/inbox, an SFTP landing zone, a mounted S3 fuse path) with a create handler that dispatches a queued job is a legitimate production pattern — but run it under Supervisor/systemd with autorestart, not in a terminal.

6. Process supervision:

[program:inotify]
command=php /var/www/app/artisan inotify:watch
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/var/log/app/inotify.log

7. Testing handlers. Don't test the watcher by waiting for real filesystem events. Extract the callback body into an invokable class or a job, and unit-test that directly with a fake path. The inotify layer itself has one behavior worth asserting: that a given event name maps to the right handler.

Gotchas and Tips

  • Archived = frozen. No Laravel 10/11 support guarantees, no security patches, no PHP 8.3 fixes. Before adopting, run composer why-not octopyid/laravel-inotify against your target framework version. If it fails, fork it into app/Support/Inotify — it's small enough that vendoring is cheaper than fighting constraints.
  • Linux only. Docker on macOS with a bind mount will not propagate host filesystem events into the container. Editors writing over a mount (and some IDE "safe write" modes that rename a temp file over the target) can swallow events entirely. Enable "use safe write" off, or fall back to polling.
  • ENOSPC / "no space left on device" is the classic inotify failure and it means watch descriptors, not disk. Raise fs.inotify.max_user_watches (and max_user_instances) via sysctl; also add vendor, node_modules, storage/framework, .git to the ignore list — a recursive watch on node_modules alone can eat tens of thousands of watches.
  • Events are noisy and non-atomic. A single editor save can produce CREATE + MODIFY (×N, one per write chunk) + MOVED_TO. Deduplicate by path with a short cooldown before dispatching. Do not assume one event per save.
  • No hot reload of your own code. The watcher process holds your handlers in memory. Edit a handler and you must restart the watcher — this trips people coming from Vite/HMR expectations.
  • Symlinks aren't followed by default; inotifywait needs -L/explicit targets. If you watch a symlinked deploy path (current -> releases/xyz), you may be watching nothing after a deploy.
  • Relative vs absolute paths. Normalize to absolute paths (base_path(...)) before comparing or storing; the %w%f output is whatever you passed to inotifywait.
  • Nothing is logged for you. Errors from the subprocess land on the parent's stdout/stderr and vanish under Supervisor unless you redirect. Wrap handler bodies in try/catch and Log::error — an uncaught exception may kill the watcher loop silently.
  • Memory and stale state. Long-running PHP accumulates memory and holds stale container bindings (same class of problem as queue:work). Restart the process nightly or after N events.
  • Extension points are thin: the console command and the service provider binding. If you need filtering, debouncing, or a different event vocabulary, you're better off replacing the package with ~15 lines of Symfony\Component\Process\Process around inotifywait and keeping the same config shape. That also removes the abandoned dependency without changing your handlers.
  • When to skip it entirely: hot module reload → Vite; log tailing → laravel/pail or tail -f; test watching → spatie/phpunit-watcher or phpunit --watch; CI file triggers → your CI provider's path filters. Inotify is the right tool only for "run arbitrary PHP when a file on this Linux box changes," and even then, verify you actually need the wrapper.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource