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

Tomato Artisan Laravel Package

tomatophp/tomato-artisan

Tomato Artisan brings Laravel's Artisan commands into your TomatoPHP admin panel, letting you browse, search, and run them from the browser with output shown inline—handy for quick maintenance tasks without opening a terminal.

View on GitHub
Deep Wiki
Context7

Getting Started

tomatophp/tomato-artisan is a TomatoPHP admin-panel plugin that puts an Artisan command runner inside your Laravel dashboard, so you can fire commands like optimize:clear, migrate, queue:restart, or storage:link from the browser instead of opening SSH.

Minimal steps:

composer require tomatophp/tomato-artisan
php artisan vendor:publish --tag=tomato-artisan-config
php artisan vendor:publish --tag=tomato-artisan-migrations
php artisan migrate

It expects the Tomato admin stack (tomatophp/tomato-admin, Filament-based) to already be installed and your AdminPanelProvider to exist. Register the plugin there:

->plugin(\TomatoPHP\TomatoArtisan\TomatoArtisanPlugin::make())

Where to look first:

  1. config/tomato-artisan.php — command allow-list, middleware, and guard settings.
  2. The generated TomatoArtisanPlugin registration in app/Providers/Filament/AdminPanelProvider.php.
  3. The plugin's src/Pages/ directory if you need to see how the command form and output view are composed.

First use case: give a support/ops user a "Clear cache" and "Restart queue" button in the panel so they stop pinging you for php artisan optimize:clear after a content change.

Implementation Patterns

Gate the whole surface behind a permission. Day-to-day, this is the pattern that matters most:

// AdminPanelProvider
->plugin(
    TomatoArtisanPlugin::make()
        ->canRun(fn () => auth()->user()?->hasRole('super-admin'))
)

Pair it with a Gate::define('run-artisan', ...) in a service provider so the check is reusable and testable outside the panel.

Whitelist rather than blacklist. Keep the config's allowed-command list narrow and grow it deliberately. A useful production set:

'allowed' => [
    'optimize:clear',
    'cache:clear',
    'config:cache',
    'route:cache',
    'queue:restart',
    'storage:link',
    'migrate --force',
],

Long-running commands go to the queue. Anything that takes more than a couple of seconds (imports, migrate on a large DB) should be dispatched as a job the panel command simply kicks off, then poll a status row. Running synchronously in a web request will hit PHP's max_execution_time and leave the browser hanging.

Environment scoping. Wrap the plugin registration in if (app()->environment(['local', 'staging'])) for teams that don't want a command runner in production, or keep it in production but restrict to a single super-admin role plus an audit log entry per invocation.

Custom commands ride along for free. Any php artisan make:command you write is immediately runnable from the panel — handy for one-off maintenance scripts (app:reindex-products) that you don't want to expose via Tinker.

Combine with tomato-settings to add a feature flag that flips the runner on/off without a deploy. Useful during incidents where you want to lock the panel down quickly.

v1.1.1 specifics: the release only touches the command UI's dark mode and RTL styling. Both are inherited automatically — there is nothing to configure and nothing to migrate. If you've published and customised the plugin views, diff them against upstream to pick up the new class names, otherwise the update is a no-op for you.

Gotchas and Tips

This is a remote-code-execution surface by design. Treat the allow-list as a security boundary, not a convenience. Never let a free-text command field reach Artisan::call() with unvalidated input. If the package version you're on exposes an arbitrary-input mode, disable it and rely solely on the allow-list.

Output truncation. Command output is captured and returned in the response; commands producing megabytes of output (verbose migrations, dump-autoload -v) can blow the response size or the memory limit. Use --quiet-style flags or redirect to a log file and link it.

Permissions follow the web user, not your shell user. storage:link or queue:restart run as www-data. If your deploy writes files as deploy, storage:link will fail with a confusing permission error — the fix lives in your deploy script's chown/chmod, not in the plugin.

Config caching bites during setup. After editing the allow-list, run php artisan config:clear locally; a stale cached config will silently keep the old command set and you'll spend ten minutes wondering why your new command doesn't appear.

Cache-busting commands need ordering. config:cache followed by route:cache can fail if a route closure exists. Surface failures clearly — check that the panel displays the exit code and stderr, not just stdout, or you'll chase phantom "successes."

RTL and dark mode (new in v1.1.1). Direction is driven by the panel's locale/direction setting, so Arabic/Hebrew locales now render the command table and form correctly. If you have published views with hardcoded text-left, ml-*, or bg-white utilities, they will not follow the new theme — swap them for logical properties (ms-*, text-start) and Filament's dark: variants.

Extension point for UI tweaks: publish the views (--tag=tomato-artisan-views) rather than subclassing the page classes; the page classes are thin and change between minor releases, while the Blade layer is where your branding belongs.

Debugging a command that works in the terminal but not the panel: log Artisan::output() and the exit code around the call inside a local wrapper command. Nine times out of ten it's a different working directory, a missing env var not present in the FPM pool, or a --no-interaction requirement.

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.
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
adachsoft/api-version-bundle
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
cgv/localized-resource