llabbasmkhll/artisan-route
llabbasmkhll/artisan-route exposes Artisan commands as HTTP routes in Laravel, letting you trigger maintenance or custom commands from the browser or external services. Configure routes, pass arguments and options, and protect endpoints with middleware for secure, convenient command execution.
Install the package and let Laravel discover its service provider:
composer require llabbasmkhll/artisan-route
Then inspect three things before using it:
php artisan vendor:publish and select the artisan-route provider/tag, then open config/artisan-route.php. Look for route path, enabled flag, middleware, command allowlist, and auth/token options.php artisan route:list | grep -i artisan and note the URI, HTTP methods, middleware, and route name.vendor/llabbasmkhll/artisan-route/src and routes/ to see exactly how commands are accepted and executed.A safe first use is in local or staging, behind auth, with a harmless command such as about or cache:clear:
# adjust URI/parameter to match the published config and route:list
curl -X POST https://app.test/artisan \
-H "Cookie: ..." \
-d "command=cache:clear"
Before enabling anywhere shared, add authentication, authorization, throttling, and an environment gate. The package is small and low-maturity, so treat it as an operational utility, not a general-purpose API.
Use it as a guarded operational endpoint, not as a replacement for real deployment tooling.
// config/artisan-route.php
'middleware' => [
'web',
'auth',
'can:run-artisan',
'throttle:10,1',
],
Gate::define('run-artisan', fn (User $user) => $user->is_admin);
abort_unless(app()->environment(['local', 'staging']), 404);
Route::middleware(['web', 'auth', 'can:run-artisan', 'throttle:6,1'])
->post('/ops/artisan', function (Request $request) {
abort_unless(app()->environment(['local', 'staging']), 404);
$allowed = ['about', 'cache:clear', 'queue:restart'];
$command = $request->string('command')->toString();
abort_unless(in_array($command, $allowed, true), 403);
Artisan::call($command);
return response()->json([
'command' => $command,
'output' => Artisan::output(),
]);
});
Use it for short, non-interactive commands. Good candidates are cache:clear, config:clear, route:clear, view:clear, queue:restart, and storage:link. Avoid interactive commands, long migrations, and anything that can run for minutes.
Log every invocation. Record user ID, IP, command, parameters, duration, and result. This is especially important if the endpoint can mutate production-like environments.
Prefer POST for mutations. GET requests can be triggered by crawlers, link previews, prefetching, or browser history. Require POST plus CSRF or a signed request for anything that changes state.
Use deployment tools when possible. On hosts with shell access, run php artisan in CI/CD or your deploy script. Use the route only where shell access is unavailable, such as some shared-hosting or webhook-only environments.
Queue long work. If an operational action may take more than a few seconds, dispatch a job and return immediately.
Security is the main risk. A route that executes Artisan commands is effectively remote command execution if poorly protected. Never leave it open in production without authentication, authorization, IP restrictions, and an allowlist.
Check the middleware order. auth before can, throttle early, and CSRF protection intact for web routes. A missing CSRF token typically produces 419; a failed gate produces 403; a disabled route often produces 404.
Config and route caching can hide changes. After editing package config or .env, run:
php artisan config:clear
php artisan route:clear
Do not disable CSRF globally. If you need machine-to-machine calls, use a signed URL, token middleware, or a separate route group with explicit auth rather than weakening the whole app.
Validate command parameters carefully. If the package shells out instead of using Artisan::call(), quoting and injection become critical. Prefer array-based Artisan calls over string concatenation.
Interactive commands fail over HTTP. Commands that prompt for confirmation, such as production migrations, need --force or should not be exposed through this route.
Watch execution limits. PHP max_execution_time, web server timeouts, and proxy timeouts can kill long-running commands. Use jobs for anything nontrivial.
Output can be large. Artisan::output() may buffer a lot of text. Limit output, log it, or return only a success/failure summary.
Multi-server environments are tricky. Hitting one route only runs the command on the server that handled the request. If you run multiple app servers, use deployment tooling to run the command everywhere or ensure the command is safe to run on one node only.
File ownership can differ between CLI and web requests. Commands that write to storage/ or bootstrap/cache may create files owned by the web user, causing later CLI permission problems.
Package maturity is low. With 22 stars and a low assessment score, pin the version, read the source, and test in staging. If your needs are more than a simple guarded endpoint, a small custom controller is often safer and easier to audit.
Debugging checklist: php artisan route:list -v, check storage/logs/laravel.log, confirm environment and config values, verify the authenticated user passes the gate, and confirm the route is not cached with stale middleware.
How can I help you explore Laravel packages today?