A FIELD GUIDE TO LARAVEL · VOLUME II · THE ECOSYSTEM
ENTRY II.3 · REMOTE TASKS
Envoy
Laravel\Envoy · Package · first recorded 10 February 2014, v1.0.0 on Packagist
A task runner for remote servers, written in Blade. Envoy.blade.php names servers and tasks; envoy run deploy opens SSH to each and streams the output back. The deploy script kept in the repo, not in a dashboard.
Specification
Kind Composer package, run locally; nothing installed on the server
Interface Blade directives: @servers, @task, @story, @setup and hooks
Runs on Your machine (macOS, Linux, WSL2), over SSH to the targets
Installed by composer require laravel/envoy --dev
Voice none in artisan. php vendor/bin/envoy run deploy --branch=main
Scales by Listing servers in on; 'parallel' => true runs them at once
Range Cloud: n/a: Cloud runs commands from its Commands tab, not over SSH
Forge, VPS: yes. SSH as the forge user; or Forge's own deploy script
Vapor: no. There is no server to SSH into
Neighbours
Envoyer runs zero-downtime deploys as a service, across several servers, with rollback built in. Forge keeps a deploy script per site in its dashboard. Envoy keeps the script in the repo, written in Blade, and runs it over SSH from your machine; rollback is a task you write yourself.
Field marks
Envoy.blade.php at the root
vendor/bin/envoy
@servers([...]) on one line
laravel/envoy in require-dev
Fig. II.3.1 · One story, two servers, exploded
Parts
1 Envoy.blade.php, at the application root. @servers, on one line, names each host by a key the tasks refer to.
2 Story. @story('deploy') lists tasks by name, so one command runs update-code then install-dependencies.
3 Task. Shell lines between @task and @endtask, with Blade @if and {{ $branch }} from the command line.
4 Servers, the on list says which hosts a task runs on, over SSH, serially; 'parallel' => true runs them together.
5 Hooks. @before, @after, @error, @success and @finished run as PHP locally, never on the server.
6 Notification. @slack, @discord, @telegram or @microsoftTeams inside @finished, carrying the task's name.
Hidden joinery
The docs keep @servers on one line; the 2.x compiler now folds a multi-line array itself. 'confirm' => true makes a task ask before running, for the destructive ones. A 127.0.0.1 server runs the task locally. @import pulls in tasks from a vendor Envoy file. @finished gets the exit code, so a failed task still posts.
Checked line by line against laravel.com/docs/13.x/envoy, the 2.x source and Packagist on 2026-10-08.
TITLE
Envoy · one story, two servers
SOURCES
laravel.com/docs/13.x/envoy · github.com/laravel/envoy/blob/2.x/src/Compiler.php · packagist.org/packages/laravel/envoy · laravel.com/cloud/docs/compute · laravel.com/forge/docs/sites/deployments · docs.envoyer.io
STATUS
Verified · 2026-10-08
SHEET
II.3 of 48
REV
A · 2026-10-08
DRAWN
BS
FINISH
All faces, including the back