What Is php artisan dev?
Laravel 13.16 shipped a first-party artisan dev command that consolidates everything you need during local development into a single terminal session. Before this, the application skeleton wired things together with a dev script in composer.json that piped four commands through npx concurrently. That script still exists, but it now does nothing except delegate to the new command:
php artisan dev
Under the hood the command still shells out to concurrently, and since Laravel 13.18 it passes --kill-others-on-fail, so one crashing process brings down the rest instead of leaving you with a half-running stack.
Default Processes
Out of the box, artisan dev starts four processes:
| Name | Command |
|---|---|
| server | php artisan serve --host=localhost |
| queue | php artisan queue:listen --tries=1 --timeout=0 |
| logs | php artisan pail --timeout=0 |
| vite | npm run dev |
The logs process relies on pcntl_fork, so it is skipped on Windows. The vite process automatically detects your lockfile and uses the correct package manager—pnpm run dev in a pnpm project, yarn run dev in a Yarn project, and so on—without any configuration.
Registering Custom Processes
The real power comes from the DevCommands class, which lets you replace or extend the defaults from your AppServiceProvider:
namespace App\Providers;
use Illuminate\Foundation\DevCommands;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
if (! $this->app->environment('local')) {
return;
}
// Replace the default queue worker with Horizon
DevCommands::artisan('horizon', 'queue');
// Start Laravel Reverb in debug mode
DevCommands::artisan('reverb:start --debug', 'reverb')->purple();
// Forward Stripe webhooks via the Stripe CLI
DevCommands::register(
'stripe listen --forward-to '.config('app.url').'/stripe/webhook',
'stripe'
)->orange();
// TypeScript type-checking in watch mode
DevCommands::nodeExec('tsc --noEmit --watch --preserveWatchOutput', 'types')->yellow();
}
}
Registration Methods
artisan()— prefixes the command withphp artisan.node()— prefixes with the detected package manager's run command.nodeExec()— uses the exec variant (npx,pnpx, etc.).register()— accepts a raw shell command for anything else.
Replacing a Default
Process names are identities. Registering a process with the name queue replaces the default queue:listen worker. The same pattern overrides any built-in:
DevCommands::artisan('serve --host=localhost --port=9000', 'server');
Application-registered processes always outrank framework defaults, which in turn outrank anything registered from vendor.
Inspecting and Filtering the Process List
Added in Laravel 13.17, php artisan dev:list prints every registered process, its command, and the file and line it was registered from—without starting anything.
You can also limit which processes run at start-up:
// Only start the server and Vite
DevCommands::only('server', 'vite');
// Start everything except the queue worker
DevCommands::except('queue');
These are runtime filters, not deletions, so the excluded process still appears in dev:list and can be restored by removing one line.
Key Takeaways
php artisan devis available from Laravel 13.16 and replaces the Composerdevscript.- Four processes run by default: dev server, queue worker, Pail log tail, and Vite.
- Vite auto-detects npm, pnpm, Yarn, or Bun from your lockfile.
- Custom processes are registered via
DevCommandsinAppServiceProvider. - Reusing a process name (e.g.
queue) replaces the framework default. php artisan dev:list(13.17+) shows every registered process and its source location.--kill-others-on-fail(13.18+) ensures a single crash stops the entire stack cleanly.
Source: Laravel artisan dev: Run Server, Queue, Logs, and Vite — Laravel News