monkeyscloud / monkeyslegion-dev-server
Hot-reload development server for MonkeysLegion applications.
Installs: 191
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/monkeyscloud/monkeyslegion-dev-server
Requires
- php: ^8.4
- ext-posix: *
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.5|^10.0
Suggests
- entr: File watcher for automatic hot-reload on file changes
This package is auto-updated.
Last update: 2025-11-20 02:43:22 UTC
README
A lightweight, hot-reload development server for MonkeysLegion applications. Built on PHP's native web server with automatic file watching and zero configuration.
Features
- 🚀 Zero Configuration - Works out of the box with MonkeysLegion projects
- 🔥 Hot Reload - Automatic restart on file changes (two methods available)
- 🎯 entr - External file watcher (recommended, most efficient)
- 🔄 FileWatcher - Built-in pure PHP watcher (zero external dependencies)
- ⚡ Fast - Uses PHP's built-in server with opcache disabled for instant updates
- 🎯 Simple CLI - Easy commands:
start,stop,restart,status - 🛡️ Process Management - Robust PID tracking with fallback mechanisms
- 📁 Smart Routing - Serves static files and routes dynamic requests to your app
- 🔧 Flexible - Customizable host, port, and document root
- 💪 No External Dependencies - Works with pure PHP,
entris optional
Requirements
- PHP 8.0 or higher
- POSIX extension (included in most PHP installations)
entrfor efficient hot-reload (optional, automatic fallback to pure PHP watcher)
Installing entr
# Ubuntu/Debian sudo apt-get install entr # macOS brew install entr # Fedora/RHEL sudo dnf install entr
Installation
Via Composer (Recommended)
composer require --dev monkeyscloud/monkeyslegion-dev-server
Manual Installation
- Clone or download this package to your project's
vendordirectory - Ensure the autoloader is configured correctly
- Copy the
bin/dev-serverscript to your project'sbin/directory
Quick Start
# Start the server (default: http://127.0.0.1:8000) ./vendor/bin/dev-server # Or if copied to your bin/ directory ./bin/dev-server
That's it! Your MonkeysLegion app is now running with hot-reload enabled.
Usage
Basic Commands
# Start server on default host:port (127.0.0.1:8000) ./bin/dev-server ./bin/dev-server start # Start on custom host and port ./bin/dev-server 0.0.0.0 3000 # Stop the server ./bin/dev-server stop # Restart the server ./bin/dev-server restart # Restart on custom host:port ./bin/dev-server restart 0.0.0.0 3000 # Check server status ./bin/dev-server status # Show help ./bin/dev-server help
Environment Variables
You can set default host and port via environment variables:
# In your .env or shell profile export ML_DEV_HOST=0.0.0.0 export ML_DEV_PORT=3000 # Now just run: ./bin/dev-server
Programmatic Usage
<?php use MonkeysLegion\DevServer\DevServer; // Start server $server = new DevServer(); $server->serve('127.0.0.1', 8000); // Stop server DevServer::stop(); // Restart server DevServer::restart('127.0.0.1', 8000); // Check status DevServer::status();
How It Works
Hot Reload
The dev server offers two file watching methods, automatically selecting the best available option:
1. entr (Recommended)
When entr is installed, the dev server uses it for efficient file watching. This is the fastest and most resource-friendly method.
Advantages:
- ✅ Most efficient (low CPU usage)
- ✅ Instant change detection
- ✅ Battle-tested and reliable
Installation:
# Ubuntu/Debian sudo apt-get install entr # macOS brew install entr # Fedora/RHEL sudo dnf install entr
2. FileWatcher (Built-in Fallback)
When entr is not available, the dev server automatically falls back to a pure PHP file watcher. No external dependencies required!
Advantages:
- ✅ Zero external dependencies
- ✅ Works on any system with PHP
- ✅ Automatic fallback (no configuration needed)
- ✅ Watches for new files, modifications, and deletions
How it works:
- Polls watched directories every second
- Tracks file modification times and sizes
- Ignores
vendor/,node_modules/,.git/, etc. - Filters by extension (
.php,.css,.js,.html,.json)
Performance note: The pure PHP watcher is slightly less efficient than entr as it uses polling. For production-like performance testing, install entr.
Choosing Your Method
The dev server automatically selects the best available method:
# With entr installed: ./bin/dev-server # Output: 🔁 Hot-reload enabled via entr (recommended) # Without entr: ./bin/dev-server # Output: 🔁 Hot-reload enabled via FileWatcher
You can also force the use of FileWatcher programmatically:
$server = new DevServer(); $server->serve('127.0.0.1', 8000, null, true); // Force FileWatcher
opcache Configuration
Both methods disable PHP's opcache for CLI mode so changes are reflected immediately without manual restart:
opcache.enable_cli=0 # Disable opcache for CLI opcache.enable=0 # Disable opcache entirely opcache.validate_timestamps=1 # Check for file changes opcache.revalidate_freq=0 # Check on every request realpath_cache_ttl=0 # Don't cache resolved paths
Directory Structure
your-project/
├── app/ # Watched for changes
├── config/ # Watched for changes
├── public/ # Watched for changes (static files served directly)
│ └── index.php # Front controller
├── resources/
│ └── views/ # Watched for changes
├── var/
│ └── run/
│ └── dev-server.pid # Process ID file
├── bin/
│ └── dev-server # CLI script
└── vendor/
└── monkeyscloud/
└── monkeyslegion-dev-server/
Routing
The dev server uses a smart router that:
- Serves static files directly from
public/if they exist - Routes all other requests through
public/index.php - Handles pretty URLs and rewrite rules automatically
Configuration
Custom Document Root
By default, the server uses public/ as the document root. You can customize this:
$server = new DevServer(); $server->serve('127.0.0.1', 8000, '/path/to/docroot'); // Or relative to project root $server->serve('127.0.0.1', 8000, 'web');
Custom Router Script
The server looks for a router script in this order:
{project}/bin/dev-router.php(your custom router){project}/vendor/monkeyscloud/monkeyslegion-dev-server/bin/dev-router.php(default)
Create your own router in bin/dev-router.php if you need custom routing logic:
#!/usr/bin/env php <?php declare(strict_types=1); $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $projectRoot = dirname(__DIR__); // Custom routing logic here if (str_starts_with($uri, '/api/')) { require $projectRoot . '/public/api.php'; return; } // Serve static files $file = $projectRoot . '/public' . $uri; if ($uri !== '/' && is_file($file)) { return false; // Let PHP's server handle it } // Default to front controller require $projectRoot . '/public/index.php';
Watched Directories
To customize which directories are watched for changes, edit the dev-server script:
// Find this section: $paths = "find app public resources config -type f 2>/dev/null"; // Customize to watch different directories: $paths = "find app src templates public -type f 2>/dev/null";
Advanced Usage
Running on a Network
To make your dev server accessible from other devices on your network:
# Listen on all interfaces ./bin/dev-server 0.0.0.0 8000 # Now accessible at http://your-ip:8000
Multiple Instances
You can run multiple dev servers on different ports:
# Terminal 1 ./bin/dev-server 127.0.0.1 8000 # Terminal 2 ./bin/dev-server 127.0.0.1 8001 # Terminal 3 ./bin/dev-server 127.0.0.1 8002
Note: Each instance needs its own PID file, so you may need to modify the getPidFile() method to include the port number.
Production Warning
⚠️ Never use this dev server in production!
This server is designed for development only. For production, use:
- Apache with mod_php or php-fpm
- Nginx with php-fpm
- Caddy
- Or any other production-grade web server
Troubleshooting
Server Won't Stop
If ./bin/dev-server stop doesn't work:
# Find the process ps aux | grep "php.*-S" # Kill by PID kill -9 <PID> # Or kill by port lsof -ti:8000 | xargs kill -9 # Or use pkill pkill -f 'php.*-S.*:8000' # Clean up stale PID file rm var/run/dev-server.pid
Port Already in Use
# Find what's using the port lsof -i :8000 # Kill it lsof -ti:8000 | xargs kill -9 # Then start your server ./bin/dev-server
Hot Reload Not Working
With entr:
-
Check if entr is installed:
which entr # If empty, install it or dev server will use FileWatcher -
Verify opcache is disabled:
php -d opcache.enable_cli=0 -r "var_dump(ini_get('opcache.enable_cli'));" # Should output: string(1) "0"
-
Check watched directories exist:
ls -la app/ public/ resources/ config/
With FileWatcher (pure PHP):
-
Check which method is being used:
./bin/dev-server # Look for: "Hot-reload enabled via entr" or "Hot-reload enabled via FileWatcher" -
Check file permissions:
# FileWatcher needs read access to watched directories ls -la app/ public/ resources/ config/ -
Manually restart if needed:
./bin/dev-server restart
General troubleshooting:
- Manual restart:
./bin/dev-server restart
Changes Not Appearing
If your code changes aren't showing up:
- Hard refresh your browser -
Ctrl+Shift+R(orCmd+Shift+Ron Mac) - Check browser cache - Open DevTools → Network → Disable cache
- Restart the server -
./bin/dev-server restart - Check PHP error logs - Look for syntax errors
Permission Denied
# Make sure the script is executable chmod +x bin/dev-server chmod +x vendor/bin/dev-server # Create var/run directory if it doesn't exist mkdir -p var/run chmod 775 var/run
Technical Details
PHP Configuration
The server runs with these PHP settings:
opcache.enable_cli=0 # Disable opcache for CLI opcache.enable=0 # Disable opcache entirely opcache.validate_timestamps=1 # Check for file changes opcache.revalidate_freq=0 # Check on every request realpath_cache_ttl=0 # Don't cache resolved paths
Process Management
- PID File:
{project}/var/run/dev-server.pid - Process Group: The server kills the entire process group to ensure child processes are terminated
- Signals Used:
SIGTERM(graceful shutdown),SIGKILL(forced shutdown as fallback) - Fallback Methods: If PID-based shutdown fails, the server attempts to kill by port using
lsofandpkill
File Watching
When entr is available, the server watches these file patterns:
app/**/*.php- Application coderesources/views/**/*.ml.php- Template filespublic/**/*.*- Static assets (CSS, JS, images)config/*.php- Configuration files
Changes to any of these files trigger an automatic server restart.
API Reference
DevServer Class
serve(string $host, int $port, ?string $docRoot): void
Start the development server.
Parameters:
$host- Host to bind to (default:127.0.0.1)$port- Port to listen on (default:8000)$docRoot- Document root path or directory name (default:public)
Example:
$server = new DevServer(); $server->serve('0.0.0.0', 3000, 'web');
stop(): void
Stop the running development server.
Example:
DevServer::stop();
restart(string $host, int $port): void
Restart the development server.
Parameters:
$host- Host to bind to (default:127.0.0.1)$port- Port to listen on (default:8000)
Example:
DevServer::restart('127.0.0.1', 8000);
status(): void
Check the status of the development server.
Example:
DevServer::status();
Comparison with Other Tools
| Feature | MonkeysLegion DevServer | Symfony Local Server | Laravel Valet | php -S |
|---|---|---|---|---|
| Hot Reload | ✅ Yes (with entr) | ✅ Yes | ✅ Yes | ❌ No |
| Zero Config | ✅ Yes | ⚠️ Partial | ⚠️ Requires setup | ✅ Yes |
| Process Management | ✅ Yes (start/stop/restart) | ✅ Yes | ✅ Yes | ❌ Manual |
| Multiple Projects | ⚠️ Different ports | ✅ Yes | ✅ Yes | ❌ No |
| HTTPS Support | ❌ No | ✅ Yes | ✅ Yes | ❌ No |
| Framework Agnostic | ✅ Yes | ⚠️ Symfony-focused | ⚠️ Laravel-focused | ✅ Yes |
| Installation | Composer | Binary | Binary | Built-in |
Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
git clone https://github.com/monkeyscloud/monkeyslegion-dev-server.git
cd monkeyslegion-dev-server
composer install
Running Tests
composer test
License
This package is open-source software licensed under the MIT license.
Credits
- Author: MonkeysCloud Team
- Maintainer: [Your Name]
- Inspired by: Symfony Local Server, Laravel Valet, and PHP's built-in web server
Support
- Issues: GitHub Issues
- Documentation: Full Docs
- Community: Discord
Changelog
1.0.1 (2025-11-19)
- ✨ Added
restartcommand - ✨ Added
statuscommand - 🐛 Fixed stop command not working reliably
- 🐛 Fixed hot reload with proper opcache settings
- 🔧 Improved process group management
- 🔧 Added fallback kill-by-port mechanism
- 📝 Comprehensive documentation
1.0.0 (2024-01-01)
- 🎉 Initial release
- ✨ Basic start/stop functionality
- ✨ Hot reload with entr support
- ✨ Custom host/port configuration
Made with ❤️ by the MonkeysCloud team