spatie/scotty
Scotty is a beautiful SSH task runner for running scripted tasks on remote servers. Define tasks and macros in a simple Scotty.sh (bash + annotations), then run them with clear output. Fully compatible with Laravel Envoy as a drop-in replacement.
@servers, @task, @macro) and Blade templating support. This ensures seamless integration with Laravel deployments, CI/CD pipelines, and existing SSH workflows.--pretend, --continue, and confirmation prompts (confirm="...") align with Laravel’s emphasis on reliable, auditable deployments.~/.ssh/config) and dynamic options (CLI/env vars), enabling integration with Laravel’s .env system or Forge/Sail environments.envoy run with scotty run).# GitHub Actions
- name: Deploy
run: ./scotty run deploy --branch=${{ github.ref_name }}
local= servers for testing deploy scripts before production.| Risk Area | Mitigation Strategy |
|---|---|
| SSH Key Management | Use Laravel Forge/Sail or ~/.ssh/config for key management; avoid hardcoding credentials. |
| Task Failures | Leverage --continue for graceful degradation; log failures to Laravel’s logs/deploy.log. |
| Blade vs. Bash | Prefer Scotty.sh (bash) for simplicity; use Blade only if dynamic Laravel logic is needed. |
| Performance | For large deployments, test with --pretend first; consider parallelizing tasks with & in bash. |
| Dependency Bloat | Scotty is a single PHAR file (~1MB), adding negligible overhead. |
Deployment Complexity:
scotty run rollback or integrate with Laravel’s migrate:rollback.Security:
~/.ssh/config? Scotty inherits this setup.php artisan key:generate) be excluded from logs? Use --summary or redirect output to /dev/null.Monitoring:
logs directory.if ! ./scotty run deploy --summary; then
echo "Deployment failed!" | tee -a storage/logs/deploy-failures.log
fi
Team Adoption:
--no-interaction flag.Future-Proofing:
| Component | Compatibility Notes |
|---|---|
| Laravel | ✅ Full support (Envoy replacement, Blade templates, Artisan command integration). |
| PHP | ✅ Works with any PHP project; no Laravel dependency. |
| SSH | ✅ Uses native SSH (OpenSSH); supports ~/.ssh/config, jump hosts, and non-standard ports. |
| CI/CD | ✅ GitHub Actions, GitLab CI, CircleCI (via SSH keys). |
| Forge/Sail | ✅ Integrates with Forge servers; Sail’s ssh command can be replaced with Scotty. |
| Docker | ⚠️ Possible but not native (SSH requires host access; use Docker-in-Docker for isolation). |
Assessment Phase:
Pilot Migration:
deploy.sh → Scotty.sh).--pretend and --summary modes.# Before (Envoy)
@servers(['web' => 'deploy@example.com'])
@task('deploy', ['on' => 'web'])
run(['cd /var/www/app', 'git pull origin main']);
# After (Scotty)
# @servers web=deploy@example.com
# @task on:web
deploy() {
cd /var/www/app
git pull origin main
}
Full Rollout:
envoy run with scotty run in CI/CD pipelines.scotty ssh instead of manual SSH).envoy commands remain).Advanced Integration:
// app/Console/Commands/Deploy.php
public function handle() {
$exitCode = shell_exec('php artisan scotty run deploy --summary');
if ($exitCode !== 0) $this->error('Deployment failed!');
}
// app/Listeners/LogDeployment.php
public function handle() {
DeployLog::create([
'status' => $this->scottyExitCode === 0 ? 'success' : 'failed',
'branch' => $_ENV['BRANCH'],
]);
}
| Feature | Scotty Support | Notes |
|---|---|---|
Envoy @servers |
✅ Yes | Identical syntax (@servers web=...). |
Envoy @task |
✅ Yes | Supports on: parameter and macros. |
| Blade Templating | ✅ Yes | Useful for dynamic Laravel logic (e.g., @if(config('deploy.enabled'))). |
| Parallel Tasks | ❌ No | Workaround: Use & in bash or split into multiple Scotty files. |
| Local Task Execution | ✅ Yes | Use local=127.0.0.1 for testing. |
| SSH Agent Forwarding | ✅ Yes | Inherits from SSH config. |
Phase 1: Replace Envoy (2–4 weeks)
Phase 2: Enhance Workflows (1–2 weeks)
--branch, --env=production).Phase 3: Monitor & Optimize (Ongoing)
--continue usage.curl -L https://.../scotty -o scotty).Scotty.sh files are version-controlled and readable.How can I help you explore Laravel packages today?