binarybuilds/nova-advanced-command-runner
Run artisan and shell commands directly from Laravel Nova. Advanced Command Runner provides a secure, permission-aware interface to execute, monitor, and review command output without SSH, simplifying routine maintenance and ops tasks for your team.
What is being evaluated. A Laravel Nova tool that adds a panel to the Nova admin dashboard for executing Artisan and shell/bash commands on the host serving the application. Mechanically it is thin: a Nova tool service provider, a Vue front-end, a controller that shells out, and output returned to the browser. MIT licensed, 18 stars, 0 dependents, last release 2020-08-14, composite score 2.16 with opportunity at 30.46.
Architecture fit. It plugs into a Laravel + Nova monolith cleanly — one entry in NovaServiceProvider::tools(), inheriting Nova's auth and middleware. But what it actually is architecturally is a remote command execution surface behind an admin panel. That runs against the direction mature Laravel estates move: queued jobs, signed deploy pipelines, CI/CD, Horizon-based observability. Treat it as an operator console bolted onto Nova, never as an application runtime component. The package's real public API is not code — it is the published config file that declares which commands the UI may expose.
Integration feasibility. Install effort is genuinely low (composer require, register, publish config/assets, edit the command list, run one benign command end-to-end). Three gates dominate feasibility:
composer.json constraints.proc_open/shell_exec enabled and the PHP-FPM user to hold whatever privileges the target commands require — both commonly locked down in hardened images.max_execution_time or proxy timeouts.Verdict: moderate feasibility on legacy Nova 2/3, poor on Nova 4/5 without an internal port.
Technical risk — the dominant factor.
Key questions to answer before committing:
composer.json actually permit them?.env, cloud keys, other tenants' data?Stack fit. Target a Laravel + Nova admin application, a small trusted admin/ops group, and a non-production or hardened internal pilot. Use it as a curated operations console — a named command catalog for cache/config clears, queue restarts, scheduler checks, migration status, storage:link, log tailing, staging resets, and support diagnostics. It is not a fit for customer-facing access, free-form bash in production, multi-tenant isolation, or anything requiring an SLA.
Migration path. Start in a disposable container or local environment with exactly one benign Artisan command. Confirm the full loop — config entry → UI selection → executed output → exit status — plus that Vue assets load after php artisan nova:publish. Only then widen the catalog. Do not touch shared infrastructure until the loop is proven and the process-execution code has been read.
Compatibility work, in order.
composer.json constraints against the pinned Laravel/Nova/PHP versions; decide port vs. abandon before writing config.config:clear, or the UI silently shows stale commands.sudo -u www-data php artisan …) before blaming the tool — PATH, env vars, .env loading, and file permissions all differ from an SSH shell.Sequencing (each step is a gate, not a task):
migrate --status, migrate --force) over one configurable shell input. Environment-branched lists: narrow for production, broader for staging/local.Extension discipline. Extend via the config file, not by forking behaviour into the package. When more logic is needed, wrap it in a custom Artisan command and expose the wrapper — complexity stays in code we own, and the tool stays a predictable launcher.
Maintenance. This is adopt-and-own. There is no upstream maintenance signal — no releases since August 2020, no dependents, no security response — so the internal team absorbs compatibility patches and security review. The config file must be treated as reviewed application code: every command addition goes through the same PR and review path, and misconfiguration is a production incident vector (a migrate:fresh entry is catastrophic). Budget a small fork-and-port line item rather than assuming zero carrying cost.
Support. No vendor, no SLA, no ecosystem validation. Support means an internal runbook plus a named owner. Document exactly which commands exist, what each does, who may run them, and what to do when output is empty. Publish the "web user is not you" debugging step as the first line of the runbook. Escalation for a broken tool is an internal engineer, so the tool's blast radius and its support burden land on the same small team.
Scaling. Two distinct problems. Vertically, each invocation occupies a web worker for its full duration — no streaming, so migrations and imports will hit max_execution_time or a proxy timeout and should be queued jobs or CLI runs instead. Horizontally, the command runs on whichever node serves the request, which means non-deterministic targets in a load-balanced fleet; either pin the tool to a designated node or accept that it is unsuitable for multi-node operational tasks. Neither limitation has a configuration fix.
Failure modes to plan for.
storage/logs/laravel.log and the tool's network response before retrying.Ramp-up. Installation ramp is trivial; operational ramp is not. The real onboarding is teaching operators to pick from the catalog rather than type commands, training reviewers to treat config diffs as production changes, and establishing audit review. Keep the catalog small and boring at first — idempotent, Laravel-native commands (cache:clear, queue:restart, config:clear, storage:link) before anything touching data.
How to measure whether it was worth it. Instrument from day one: command runs per week by key, support tickets resolved without SSH, mean time to recovery on routine ops incidents, and audit-log completeness. If usage concentrates on two or three commands and MTTR does not move, the durable answer is a thin in-house tool or simply better CI/CD — and the pilot has done its job cheaply. If usage is broad and ticket volume drops, that is the evidence needed to fund the hardened internal build rather than extend this package's life.
How can I help you explore Laravel packages today?