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 Command Center Laravel Package

farsi/nova-command-center

Adds a command center to Laravel Nova: run Artisan commands and quick actions from one panel without opening a terminal. Browse available commands, execute them with arguments and options, and review output right inside your admin UI - handy for routine maintenance and debugging.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register

composer require farsi/nova-command-center

Register the tool in your NovaServiceProvider (Nova 4 uses the tools() method; Nova 5 still honors it, or use Nova::tools([...]) in boot() — match whatever your app already does for other tools):

public function tools()
{
    return [
        new \Farsi\NovaCommandCenter\NovaCommandCenter,
    ];
}

Then clear Nova's caches so the new menu entry appears:

php artisan nova:publish --force   # only if you need assets
php artisan config:clear
php artisan route:clear

Authorize before you browse

A command runner is a root-adjacent surface. Before you open it, confirm:

  1. The tool appears only for users who pass Nova's gate (Gate::before for a super-admin, or a dedicated policy/canSee on the tool).
  2. The config file (publish with php artisan vendor:publish --tag=nova-command-center-config, or check the README for the tag) exposes a whitelist of permitted commands. Start with an empty/short list, not the default.

First use case

The 80% case is deploy-adjacent housekeeping that currently costs you an SSH session: php artisan optimize:clear, php artisan queue:restart, php artisan migrate --force, php artisan storage:link. Get one of those working end-to-end (run it, read the output, confirm exit status) before adding more.

Where to look first

  • The published config: this is where the allow-list, output limits, and any environment gating live.
  • NovaServiceProvider: your only integration point in application code.
  • The package's route/middleware definitions (vendor/farsi/nova-command-center/routes and src/Http): tells you what middleware protects the endpoint and whether it's web + Nova auth or something custom.

Implementation Patterns

Treat the allow-list as the primary API. The productive workflow is to curate a named set of commands per project — "cache", "queue", "migrate", "diagnostics" — rather than exposing a generic prompt. Group them so an on-call engineer sees exactly five buttons, each with a known blast radius:

  • Safe/read-only: php artisan about, php artisan queue:failed, df -h, php artisan migrate:status
  • Idempotent maintenance: optimize:clear, view:clear, queue:restart, schedule:run
  • Guarded/destructive: migrate --force, migrate:rollback, cache:clear in production

Gate by environment and role, not just by Nova access. Wrap the tool in a canSee() check so it's absent on local (where you have a terminal 30cm away) and present only for the ops role on staging/production:

public function tools()
{
    return [
        (new \Farsi\NovaCommandCenter\NovaCommandCenter)
            ->canSee(fn ($request) => $request->user()->hasRole('ops')),
    ];
}

(Verify canSee chaining against the package's tool class; if it isn't exposed, do the check in Nova::tools() or via a gate.)

Use it as a break-glass console, not a CI replacement. The healthy pattern: deploys and migrations still happen in your pipeline; the Nova tool exists for the 2am "queue is stuck, restart it" and "cache is poisoned, clear it" moments. If you find yourself clicking the same command daily, that's a scheduled task or a deploy step begging to be written.

Pair every mutating command with a read that proves it worked. Make queue:restart adjacent to a queue:monitor-style check, migrate adjacent to migrate:status. On a UI with no terminal scrollback, you want the verification one click away.

Diagnostics over administration. Shell commands are most valuable here for things Artisan can't do: tail -n 100 storage/logs/laravel.log, du -sh storage/*, ps aux | grep queue, free -m. These are read-only, low-risk, and save the most time.

Multi-server awareness. If you run more than one app node, remember the tool runs on whichever node answers the request — so queue:restart clears one worker pool, not all of them. For anything cluster-wide, you still want a real orchestration path (Envoyer, Forge, Horizon's own UI).

Audit trail. If the package doesn't ship one, log invocations yourself — a model observer, a middleware, or a Log::channel('commands') line capturing user, command, timestamp, exit code. In an incident review, "who ran migrate:rollback at 02:14" is the first question asked.

Gotchas and Tips

The PHP binary is the classic failure. Your web request runs under PHP-FPM with a different PATH and a different php.ini than your SSH shell. php artisan ... may resolve to nothing, or to a different PHP version with different extensions. Prefer PHP_BINARY over bare php, and verify by running php -v through the tool once and comparing to your terminal. Same story for composer, node, and anything installed via a version manager.

File ownership drift. Commands run as the web user (www-data, nginx, forge). A shell command that writes to storage/ or bootstrap/cache/ will leave root- or web-user-owned files that later break a deploy running as a different user. After using it, sanity-check with ls -l storage/framework if deploys start failing on permissions. Conversely, commands your deploy user needs to write should not be run here.

Timeouts and buffering. Long-running commands (migrate on a big table, queue:work) will hit max_execution_time, PHP-FPM's request_terminate_timeout, or your load balancer's idle timeout — often after the command has started mutating state, leaving you with a truncated output and no exit code. Keep migrations in the deploy pipeline, and never run a daemon (queue:work, horizon) synchronously from a web request; use queue:restart to bounce an existing supervisor instead.

No interactivity. Anything that prompts (migrate in production without --force, db:wipe, confirmation prompts) will hang or fail. Always pass --no-interaction / --force explicitly in the configured command string, which also makes the intent visible in the UI.

Config caching bites the allow-list. If you've run php artisan config:cache in production, editing the whitelist on the server does nothing until you re-cache. This is a feature (it prevents a compromised admin session from adding commands) but a confusing five minutes if you forget.

Output is not a log. Don't rely on the UI to retain output — page reloads and session timeouts lose it, and large outputs (migrate on 200 migrations, artisan route:list) can blow memory or get truncated. > storage/logs/x.log 2>&1 in the command string, then read the file, when output matters.

Destructive commands deserve a second gate. migrate:fresh, db:wipe, cache:clear on a Redis cluster, storage:link over an existing symlink — these are one misclick from an outage. Keep them out of the tool entirely, or isolate them behind a separate tool instance visible only to a super-admin role. Nova's own action-confirmation modals are worth mimicking in your UI expectations; don't assume the package provides one.

Keep the package updated, and read diffs. An 8-star package with a command-execution surface is a small trust boundary in your stack. Pin it, review changelogs before upgrading (especially anything touching middleware or auth), and confirm the release notes for Nova 5 compatibility — the version matrix matters here since Nova 4→5 changed tool registration and asset loading.

Extension point: wrap, don't fork. If you need custom commands with parameters, richer output formatting, or per-command permissions, the cleanest path is usually a thin first-party Nova tool that shells out via Symfony's Process component for the few cases the package doesn't cover — rather than patching vendor code that will be overwritten on the next composer update.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle