Scotty: a beautiful SSH task runner original

by Freek Van der Herten – 5 minute read

We just released Scotty, a beautiful SSH task runner. It lets you define deploy scripts and other remote tasks, run them from your terminal, and watch every step as it happens. It supports both Laravel Envoy's Blade format and a new plain bash format.

Deploy output

Why we built Scotty

Even though services like Laravel Cloud make it possible to never think about servers again, I still prefer deploying to my own servers for some projects. I know my way around them, I can pick whichever server provider I want, and I have full control over the environment.

Tools like Laravel Forge have built-in deploy functionality, and it works well. But I've always preferred running deploy scripts manually from my terminal. I want to see exactly what's happening while it runs, and when something goes wrong, I want to be staring at the output the moment it happens, not clicking through a web UI to find a log.

For years, I used Laravel Envoy for this. It does the job, but I wanted nicer output while tasks are running, and the ability to pause execution mid-deploy. Envoy uses a Blade-based file format, which works fine for us. But not everyone wants to write Blade syntax for their deploy scripts. So Scotty also offers a plain bash format for people who prefer that.

Scotty was built with the help of AI, using the Envoy codebase as a source. Even though Scotty is a rebuild from scratch, in spirit it is a fork of Envoy. Credits to Laravel for providing the foundation. You can read the full acknowledgement in the Scotty repo.

Using Scotty

Defining tasks and deploying

You define your tasks in a Scotty.sh file. It's just plain bash with some annotation comments. Your editor highlights it correctly, you get full shell support out of the box. Here's what that looks like:

#!/usr/bin/env scotty

# @servers remote=deployer@your-server.com

# @task on:remote
deploy() {
    cd /var/www/my-app
    git pull origin main
    php artisan migrate --force
}

Deploy with a single command:

scotty run deploy

Scotty connects to your server, runs each task in order, and shows you what's happening in real time. Each task displays its name, a step counter, elapsed time, and the command currently being executed. When everything finishes, you get a summary table with timing for each step.

These screenshots are from deploying this very blog. You can find the deploy file on GitHub.

Deploy output

If a task fails, its output is shown and execution stops right there so you can investigate.

Task failure

Writing plain bash instead of Blade

In addition to being able to read Envoy.blade.php files, Scotty introduces a new Scotty.sh format. Every line is real bash. Tasks are just bash functions with a # @task annotation that tells Scotty which server to run them on. Macros group tasks into a sequence. Variables are plain bash variables, available everywhere.

Because it's all valid bash, you can use helper functions, computed values like $(date +%Y%m%d-%H%M%S), and any shell construct you'd normally use. No Blade directives, no PHP @setup blocks, no {{ $variable }} interpolation.

You can also pass variables from the command line. Running scotty run deploy --branch=develop makes $BRANCH available in your tasks. The key is automatically uppercased.

You can list all available tasks and macros with scotty tasks:

scotty tasks

Pausing, resuming, and pretending

You can press p at any time during execution to pause after the current task finishes. Press Enter to resume, or Ctrl+C to cancel. This is handy when you want to check something on the server mid-deploy before continuing.

Pause and resume

There's also a pretend mode (scotty run deploy --pretend) that shows you exactly which SSH commands would be executed without actually running them. And a summary mode (scotty run deploy --summary) that hides task output and only shows results.

Validating your setup with doctor

Before your first deploy to a new server, you can run scotty doctor to validate your setup. It checks that your file parses correctly, verifies SSH connectivity to each server, and confirms that tools like php, composer, node, and git are available on the remote machine.

scotty doctor

Migrating from Envoy

If you're already using Laravel Envoy, Scotty can read your Envoy.blade.php file directly. No changes needed. Just run scotty run deploy and it works. From there, you can gradually migrate to the Scotty.sh format if you want to, or keep using Blade.

If you're new to all of this, the Your first deploy script page in the docs walks you through everything step by step.

In closing

Scotty gives you a clean, modern way to run deploy scripts and other SSH tasks from your terminal. Plain bash, beautiful output, and full control over every step.

You can find the full documentation on our docs site and the source code on GitHub. This is one of the many tools and packages we've created at Spatie. If you want to support our open source work, consider picking up one of our paid products.

Join 9,500+ smart developers

Get my monthly newsletter with what I learn from running Spatie, building Oh Dear, and maintaining 300+ open source packages. Practical takes on Laravel, PHP, and AI that you can actually use.

No spam. Unsubscribe anytime. You can also follow me on X.

Found something interesting to share? Submit a link to the community section.