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

Console Laravel Package

teepluss/console

teepluss/console lets you run Artisan commands directly from Laravel routes and controllers, offering a simple, fluent API for dispatching console commands and capturing their output without leaving your application code.

View on GitHub
Deep Wiki
Context7

Getting Started

Install (dev only):

composer require teepluss/console --dev

Register the provider. This package predates Laravel 5.5 auto-discovery, so add it manually to config/app.php unless you're on a newer version where discovery works:

Teepluss\Console\ConsoleServiceProvider::class,

Publish the config (and views, if you plan to style the console):

php artisan vendor:publish --provider="Teepluss\Console\ConsoleServiceProvider"

Look here first:

  1. config/console.php — the only file that matters on day one. It controls the route prefix, middleware stack, and which commands are allowed. Nothing else tells you what's exposed.
  2. The package's src/ for the command runner — confirm whether it shells out via Symfony\Component\Process or calls Artisan::call(), because that determines timeout and output behavior.
  3. php artisan route:list | grep -i console to find the actual URI once it's registered.

First use case: open http://yourapp.test/console in local, run route:list to confirm the runner works end-to-end, then cache:clear and view:clear — the two commands you'll actually reach for when you can't be bothered to switch to a terminal. If output renders, you're done; if the page loads but returns blank, you have a process/user/permission problem, not a routing problem.

Gate it before anything else: wrap provider registration in an environment check so it never loads in production.

Implementation Patterns

Treat it as an artisan proxy, not a shell. The value is triggering whitelisted, first-party commands from a browser tab — not arbitrary execution. Keep config/console.php's allowlist tight: route:list, migrate:status, queue:restart, cache:clear, config:show, plus your own commands.

Auth layering. Set the middleware in config to your app's stack plus an explicit gate:

'middleware' => ['web', 'auth', 'can:use-console'],

Define use-console as a Gate::define that checks $user->isAdmin() and app()->environment('local', 'staging'). Belt and braces — config can be stale after a deploy.

Wrap registration in an environment guard in AppServiceProvider::register():

if ($this->app->environment('local', 'staging')) {
    $this->app->register(\Teepluss\Console\ConsoleServiceProvider::class);
}

This makes it impossible to accidentally ship it enabled, regardless of what the config file says.

Expose your own commands. Any class in app/Console/Commands registered with Artisan is runnable immediately unless filtered. This is the highest-leverage pattern: write a thin command (ops:reindex, ops:sync-tenant, ops:clear-stale-locks) that does the work, and trigger it from the console. You get an audit trail via storage/logs, argument validation via Symfony's InputArgument, and a real CLI fallback for when the browser is the wrong tool.

Fast-return pattern for long work. Don't run migrate or a sync in the request. Have the console-triggered command dispatch a queued job and return immediately, then read the result from Horizon/logs. This sidesteps PHP-FPM timeouts and orphaned processes entirely.

Programmatic equivalent. If you'd rather build your own UI on top of the same idea, skip the package and use:

Artisan::call('route:list', ['--json' => true]);
$output = Artisan::output();

You get the same capability with full control over middleware, output formatting, and which commands are reachable.

Custom middleware for auditing. Wrap the runner route with middleware that logs user_id, command, and timestamp to a dedicated console log channel. If you're going to have a web RCE surface, at least know who used it and when.

Gotchas and Tips

This is remote code execution by design. The single most important line in your config is the one that disables it outside local. On a public-facing server this package is a full compromise waiting for one leaked credential. If you genuinely need it on staging, put it behind VPN + SSO, not just auth.

Whitelisting is not sandboxing. Any allowlist that includes tinker, or anything accepting arbitrary --execute/-- payloads, is bypassable. php artisan tinker --execute="..." runs arbitrary PHP. Never expose it. Same for migrate:fresh, db:wipe, queue:flush.

Unmaintained since April 2017. Expect breakage on Laravel 8+ (route registration API, provider signatures) and PHP 8 (type coercion, Str helpers). Before adopting, composer require it into a throwaway app at your exact framework version and run the route. If it errors, budget for a fork — or just build the 30-line Artisan::call() wrapper yourself, which is what most teams end up doing.

No TTY = hangs. Interactive prompts (migrate confirmation, db:seed questions, make:* prompts) will block or fail. Always pass --force/--no-interaction/--ansi=false, or accept that those commands aren't console-friendly.

ANSI escape codes leak into HTML. Symfony console output is [32m...-decorated. In a browser it renders as literal garbage. Either append --no-ansi to every command or strip with preg_replace('/\e\[[0-9;]*m/', '', $output) before rendering. Verify how the package's views handle this — many of these wrappers don't.

Timeouts and orphaned processes. PHP's max_execution_time and FPM's request_terminate_timeout will kill the response but not necessarily the child process. Long queue:work or migrate runs leave zombies. Cap command runtime in config if the package supports it, or queue the work (see above).

CSRF / 419s. If the console is registered with bare middleware rather than the web group, POSTs from its form fail with 419. Add web to the middleware array. Conversely, a 404 usually means the route prefix in config doesn't match what you're hitting.

Config cache is sticky. php artisan config:cache freezes console.enabled and the middleware list. Changing .env and reloading won't help until config:clear + config:cache. This is the #1 reason "it's disabled in production but it's still there."

Argument injection. If the UI lets users type arguments, validate with a strict whitelist ([A-Za-z0-9_\-:] only) before passing to Process. Never interpolate raw input into a shell string. If the package does this for you, read its escaping code — it's from 2017.

Extension points worth knowing: published config (filters/middleware/prefix), published views (override to add your own branding/audit footer), and the standard app/Console/Commands directory for adding reachable commands. Anything deeper means forking.

Debug checklist when it breaks: php artisan route:list | grep console (is it registered?) → storage/logs/laravel.log (did it throw?) → confirm base_path('artisan') resolves and is executable by the web user → check config('console.enabled') post-cache. In that order.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons