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

Artisan Remote Laravel Package

philo/artisan-remote

philo/artisan-remote is a Laravel package for executing Artisan commands on remote applications through a secure, configurable connection. Run migrations, clear caches, and inspect command output without SSH, simplifying maintenance across environments.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its config:

composer require philo/artisan-remote
php artisan vendor:publish --provider="PhiloNL\ArtisanRemote\ArtisanRemoteServiceProvider"

Add the shared secret to .env (the package reads it from the published config/artisan-remote.php):

ARTISAN_REMOTE_TOKEN=some-long-random-string

The package registers a single JSON endpoint (default POST /artisan-remote, configurable via the route key). Send the command name in the request body:

curl -X POST https://your-app.test/artisan-remote \
  -H "Authorization: Bearer ${ARTISAN_REMOTE_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"command":"cache:clear"}'

First useful case: wire it into a deploy script or an admin "ops" panel so non-engineers (or your CI) can trigger cache:clear, queue:restart, migrate --force, or storage:link without SSH access.

Before you rely on it, read two files in the repo to understand the contract precisely: the service provider (route registration + middleware) and the controller (how the command payload is parsed and how output/exit code are returned). These two files are the API surface; the config is trivial by comparison.

Implementation Patterns

Whitelist-driven ops endpoint. The config exposes a commands array — treat it as the allowlist. Populate it with the specific commands you want callable (e.g. cache:clear, queue:restart, horizon:terminate) rather than leaving it open. Anything not listed should be rejected by the controller.

Deploy-pipeline hook. Call the endpoint at the end of a deploy so post-release cache/config refreshes happen over HTTP instead of an SSH step:

curl -fsS -X POST "$APP_URL/artisan-remote" \
  -H "Authorization: Bearer $ARTISAN_REMOTE_TOKEN" \
  -H "Accept: application/json" \
  -d '{"command":"config:cache"}' | jq -e '.exit_code == 0'

Using -f plus checking the returned exit code gives you a failing build when the artisan command fails.

Admin panel "Run" buttons. In a Filament/Nova/Blade admin, POST to the endpoint from a small authenticated route in your app rather than letting the browser talk to artisan-remote directly. That keeps the remote token server-side and lets you record an audit trail (who ran what, when, exit code).

Queue long commands. Because the request runs synchronously, wrap slow commands (migrate, db:seed, horizon:snapshot across a fleet) in a queued job in your app that calls the remote endpoint, or have the endpoint dispatch a job and return immediately. Never hold an HTTP request open for a multi-minute command.

Multi-server fan-out. Since it's just HTTP, you can hold a list of app hosts and fire the same POST at each — a poor-man's fleet runner for queue:restart or optimize:clear. Pair with curl --parallel or a Laravel Http::pool().

Response handling. Expect JSON containing the command output and an exit code. Log the raw payload on non-zero exit — output capture quirks are the most common failure mode (see below).

Gotchas and Tips

Synchronous, unbuffered execution. The controller calls Artisan::call() and reads Artisan::output(). There is no streaming, no progress bar, no timeout beyond your web server's. Long commands will hit PHP max_execution_time or Nginx's 60s default. Raise the timeout in the vhost for the route, or don't route slow commands through it.

Interactive commands silently fail. Anything that prompts (migrate with confirmations, db:seed asking questions, commands using $this->ask()) will hang or fail because there is no TTY. Always pass the non-interactive flags (--force, --no-interaction) and bake them into the allowlist entries or the command strings you send.

The 2021 release pin is a real risk. Last tagged in Jan 2021, this predates Laravel 9/10/11's changes to command signatures and the Artisan facade output handling. On modern Laravel, check that composer require actually resolves and that the service provider's route/controller still work. If it doesn't, the controller is ~50 lines — fork it into app/Http/Controllers/RemoteArtisanController.php and keep the config contract; you'll lose nothing.

Route caching. If you run php artisan route:cache, config changes to route after that point won't take effect until you re-cache. Publish and edit the config before your first optimize, and include route:clear in deploy steps that touch this package's config.

Token handling. The token check is a simple comparison — ensure it's a long random value, never commit the .env, and consider adding IP allowlisting or your own auth middleware on top of the package's route group (the config lets you append middleware). Exposing this route publicly without extra middleware is effectively remote code execution limited only by your allowlist.

Output capture is global-ish. Artisan::output() returns output from the last command run in the process. In a normal FPM request that's fine, but if you ever reuse the endpoint from a queued job handling multiple commands, capture output per-call yourself by using Artisan::call($cmd) return value (the exit code) plus Artisan::output() immediately after — don't interleave.

Arguments and options. The endpoint expects the full command string (or name plus flags) as you'd type it on the CLI. Sending {"command":"migrate --force"} works; sending structured arguments/options objects generally does not unless the controller has been extended to build the array form. Verify the parsing in the controller before building UI around it.

Add your own middleware for audit logging. The package's extension point is the route/middleware config array plus the controller. Push an audit-log middleware into the route group so every remote command run is recorded with user, IP, command, and exit code — this is the single highest-value addition for a team using it day-to-day.

Healthcheck pattern. A tiny {"command":"about"} or {"command":"inspire"} call is a cheap way to verify the endpoint, token, and allowlist are wired correctly after a deploy — use it as a smoke test before enabling the rest of your ops automations.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
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