thesis / hot-reload
Thesis Hot Reload
Fund package maintenance!
0.4.0
2026-04-01 01:58 UTC
Requires
- php: ^8.4
- ext-pcntl: *
- amphp/amp: ^3.0
- revolt/event-loop: ^1.0
- symfony/console: ^7.0 || ^8.0
- thesis/exceptionally: ^0.3.0
Requires (Dev)
- amphp/http-server: ^3.4
- amphp/log: ^2.0
- phpunit/phpunit: ^12.4
- symfony/var-dumper: ^7.4
README
Watches files for changes and automatically restarts a command.
Useful for development servers, workers, or any long-running PHP tasks.
Supports debouncing to avoid redundant restarts when multiple files change at once.
Installation
composer require thesis/hot-reload --dev
Requires PHP 8.4+.
Usage
vendor/bin/hot-reload [options] [--] <cmd>
Options
| Option | Description | Default |
|---|---|---|
--path |
Paths to watch (repeatable) | src |
--ext |
File extensions to watch (repeatable; if none, all are watched) | none |
--exclude |
Patterns to exclude (repeatable, e.g. *.generated.php) |
none |
--debounce |
Delay in seconds before restarting after a change | 0.1 |
--term-timeout |
Seconds to wait for the process to exit after SIGTERM before sending SIGKILL |
3 |
--forward-signal |
Signals to forward to the process (repeatable, e.g. SIGUSR1 or 10) |
none |
Exit code
vendor/bin/hot-reload returns the exit code of the watched command if it terminated on its own, or 0 when stopped
via SIGINT or SIGTERM.
Examples
# Watch src/, restart on any file change vendor/bin/hot-reload -- php server.php # Watch multiple paths, only .php files vendor/bin/hot-reload --path=src --path=config --ext=php -- php server.php # Exclude generated files vendor/bin/hot-reload --path=src --ext=php --exclude='*.generated.php' -- php server.php # Increase debounce delay (useful when many files change at once) vendor/bin/hot-reload --debounce=0.5 -- php server.php
PHP API
You can use hotReload() directly in PHP instead of the bin script:
use Amp\Cancellation; use Amp\Http\Server\SocketHttpServer; use function Amp\ByteStream\getStdout; use function Amp\trapSignal; use function Thesis\hotReload; hotReload( files: __DIR__, task: static function (Cancellation $termination): void { $server = SocketHttpServer::createForDirectAccess(/** ... */); $termination->subscribe($server->stop(...)); $server->expose(/** ... */); $server->start(/** ... */); trapSignal([SIGINT, SIGTERM], cancellation: $termination); $server->stop(); }, onReload: static function (): void { getStdout()->write("\nFiles changed, reloading server...\n\n"); }, );
$termination is cancelled when files change or when hotReload() itself is cancelled — subscribe to it to stop the
task gracefully.
TransparentProcess
Use TransparentProcess::start() to run an external command with full TTY transparency:
- stdin/stdout/stderr are inherited
- specified signals are forwarded
- the process is terminated gracefully via
SIGTERM SIGKILLis dispatched after a timeout.
See bin/hot-reload for a real-world usage example.
Roadmap
- inotify-based change detector for Linux (event-driven, no polling)
License
MIT