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

Nova Advanced Command Runner Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Verify compatibility before you install anything. The last release was 2020-08-14. Check the package's composer.json against your Laravel and Nova majors before composer require:

composer show binarybuilds/nova-advanced-command-runner --all | grep -E 'versions|requires'

If you're on Nova 4/5 or Laravel 9+, expect a port rather than an install. Treat a disposable container as your first target.

2. Install and register the tool.

composer require binarybuilds/nova-advanced-command-runner
php artisan vendor:publish --tag=nova-advanced-command-runner-config
php artisan nova:publish   # confirm the tool's Vue assets actually land
// app/Providers/NovaServiceProvider.php
use BinaryBuilds\NovaAdvancedCommandRunner\NovaAdvancedCommandRunner;

public function tools(): array
{
    return [
        (new NovaAdvancedCommandRunner())->canSee(fn ($request) => $request->user()->isAdmin()),
    ];
}

3. Look at the config file first — it is the actual API. Everything you'll do day-to-day happens in config/nova-advanced-command-runner.php. Open it before you open the UI. It's where commands are declared; the Vue panel is just a renderer for that list.

'commands' => [
    [
        'key'     => 'cache-clear',
        'label'   => 'Clear application cache',
        'command' => 'php artisan cache:clear',
    ],
],

4. Read the process-execution layer before you trust it. Find the controller (typically src/Http/Controllers/) and the service that calls proc_open/shell_exec/Symfony\Process. Know exactly: how the command string is assembled, whether it's escaped, whether user input reaches it, what timeout is applied, and how exit codes and stdout/stderr are captured. This is ~15 minutes and it determines every guardrail you'll need to add.

5. First use case: one benign command, end to end, non-production. Add cache:clear to the config, load the Nova dashboard, launch the tool, select it, run it, watch output and exit status. That single loop (config entry → UI selection → output + exit code) validates install, assets, auth, and process permissions simultaneously. It's also the template you'll repeat for every command you add.

6. Reproduce as the web user. Before you blame the package, run the exact command yourself under the same identity:

sudo -u www-data php artisan cache:clear   # from the app root

If that fails, the tool will fail identically — and now you know it's an environment problem, not a package problem.

Implementation Patterns

Treat the config as a curated runbook, not a terminal. The package's real value is that operators pick from named, pre-approved operations instead of recalling syntax. Every recurring maintenance task should get its own entry with a stable key, a plain-language label, and one unambiguous intent:

'commands' => [
    ['key' => 'cache-clear',   'label' => 'Clear app cache',        'command' => 'php artisan cache:clear'],
    ['key' => 'config-clear',  'label' => 'Clear config cache',     'command' => 'php artisan config:clear'],
    ['key' => 'queue-restart', 'label' => 'Restart queue workers',  'command' => 'php artisan queue:restart'],
    ['key' => 'migrate-status','label' => 'Show migration status',  'command' => 'php artisan migrate:status'],
    ['key' => 'storage-link',  'label' => 'Link storage directory', 'command' => 'php artisan storage:link'],
    ['key' => 'schedule-list', 'label' => 'List scheduled tasks',   'command' => 'php artisan schedule:list'],
],

Keep key values immutable — they're your audit-log join key and your external references in runbooks and docs. Maintain this file like code: reviewed, diffed, versioned.

Split the catalog by environment. Production should see a narrow, read-mostly list; staging/local can see the destructive stuff. Branch in the config rather than maintaining two packages:

$safe = [
    ['key' => 'queue-restart', 'label' => 'Restart queue workers', 'command' => 'php artisan queue:restart'],
    ['key' => 'migrate-status','label' => 'Show migration status', 'command' => 'php artisan migrate:status'],
];

$dev = array_merge($safe, [
    ['key' => 'migrate-fresh', 'label' => 'Rebuild database (DESTRUCTIVE)', 'command' => 'php artisan migrate:fresh --seed'],
]);

return ['commands' => app()->environment('production') ? $safe : $dev];

Authorize in code, not in menus. Hiding the tool from the navigation is not access control — the underlying routes still exist. Use canSee() on the tool and a policy or gate, and make sure Nova's own route middleware covers the tool's endpoints. Anyone who can reach this panel can execute as the web user.

Prefer many static commands over one free-text input. The safest pattern this package supports is a long list of argument-free, named commands. If the installed version supports placeholders ({path}-style), validate and escape inputs yourself before they hit the command string — never let a request parameter concatenate into a shell line unchecked. If it doesn't support placeholders, don't fake it with shell syntax; add separate entries for migrate --status and migrate.

Wrap anything non-trivial in your own Artisan command. Keep complexity in code you own, and expose the wrapper through the tool:

// app/Console/Commands/RefreshStagingData.php — real logic, argument validation, logging
// config entry:
['key' => 'refresh-staging', 'label' => 'Refresh staging dataset', 'command' => 'php artisan app:refresh-staging'],

This is the primary extension point. It gives you argument validation, structured logging, idempotency, and a command you can also run from cron or CI. The Nova tool stays a thin launcher.

Add audit logging yourself — it isn't first-class. Log actor, command key, the resolved command string, timestamp, exit code, and an output snippet. A small listener or a wrapper around the tool's controller action is enough:

Log::channel('ops')->info('nova-command-runner', [
    'user_id'  => auth()->id(),
    'key'      => $key,
    'command'  => $command,
    'exit'     => $exitCode,
    'duration' => $ms,
    'output'   => Str::limit($output, 2000),
]);

This is the first thing you'll reach for when a run has an unexpected effect — and the first thing an auditor will ask for.

Prefer Laravel-native and idempotent commands. cache:clear, config:clear, queue:restart, storage:link, schedule:list are portable, well-understood, and safe to re-run. Raw bash reduces portability and widens the blast radius. When you must shell out, use absolute paths and an explicit PHP binary — the web user's PATH is not yours:

/usr/bin/php8.2 /var/www/app/artisan cache:clear

Capture long output to a file. For migrations, imports, and anything over a few seconds, redirect to storage/logs and read the result back through a log viewer or a follow-up command entry. Don't design workflows that depend on the UI streaming — it doesn't.

Compose, don't orchestrate. Use this tool for small maintenance tasks; keep deployments, rollbacks, and multi-step data migrations in CI/CD, Envoyer, or Horizon. It replaces "SSH in to clear a cache," not your deploy pipeline.

Gotchas and Tips

The web user is not you, and that's the whole ballgame. Commands run as the PHP-FPM/Nginx user. PATH, environment variables, .env resolution, umask, and file ownership all differ from your SSH session. When a command "works on the server but not in the tool," this is why. Always debug by reproducing as that user first.

Package age is the dominant risk, not a footnote. August 2020, zero dependents, no release since. Nova 4/5 changed tool registration and the asset pipeline; PHP 8.1+ surfaces deprecations in old code. Pin to a specific commit, vendor the source into your repo if you adopt it, and budget for a fork-and-port rather than assuming upstream fixes.

Config caching will silently lie to you. Edit the command list, see stale entries in the UI, and lose 20 minutes. If config is cached, php artisan config:clear after every change. Add it to your deploy checklist next to config:cache.

Timeouts consume a web worker for the whole run. max_execution_time, PHP-FPM's request_terminate_timeout, and any reverse-proxy timeout all apply. A five-minute migration is a five-minute occupied worker and a likely 504. Anything long belongs in a queued job or a CLI run.

There is no real streaming. Output lands when the command completes. Interactive commands — anything that prompts for confirmation or input — will hang or fail silently. Never expose them; if you need migrate in production, wrap it with --force inside your own command rather than expecting a prompt to work.

Empty output is usually a signal, not a bug. Confirm the command ran at all: check storage/logs/laravel.log, inspect the network response for the tool's request in devtools (status code, response body), then run the exact string manually as the web user. That three-step sequence resolves most "the tool is broken" reports.

proc_open/shell_exec may be disabled outright. Hardened container images and many shared hosts disable them via disable_functions. Check with php -i | grep disable_functions before assuming a code problem.

Production safety is entirely your responsibility. A single misconfigured migrate:fresh entry in the wrong environment is catastrophic and unrecoverable. Gate the tool behind an explicit env flag, exclude production from the config by default, require a second reviewer on changes to the command list, and never add a destructive command without a matching backup or snapshot procedure documented next to it.

The config file is the only sanctioned extension point. Add commands there; don't fork to add "one small feature" unless you've decided to own the package. If you genuinely need allowlists, per-user capability checks, output caps, redaction, and structured audit logs, that's a small fork — or, at roughly 200 lines of equivalent in-house tooling, a legitimate build. Decide deliberately; the middle path of bolting hardening on from outside doesn't really exist.

Watch what the web user can reach. It can read .env, hold DB credentials, and touch cloud keys. A command that dumps environment or config (env, config:show on sensitive keys) is a data-exfiltration primitive, not a diagnostic. Redact output, and audit the config list with that lens.

Re-run the compatibility and permission checks after every platform upgrade. With no upstream maintenance, a Laravel or Nova bump is a change that can break this tool. Put it on the upgrade checklist with a smoke test of one benign command.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
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
cgv/localized-resource