Docs

Projects

Create new Sail projects, clone from Git, import existing folders, and manage starts and stops.


Create a new project

Click Create in the project list and pick "New project". The form scaffolds a fresh Laravel + Sail app via Docker, so no PHP install needed.

Form fields

  • Name. Letters, numbers, and hyphens. Has to start with a letter. Becomes the folder name and (with local URLs on) the subdomain.
  • PHP version. 8.2, 8.3, or 8.4.
  • Starter kit. None, Breeze, or Jetstream. Picks what laravel new ships with.
  • Services. Tick which Sail services you want. They're grouped by Database, Cache, Search, Mail, Storage, and Tools. See the full list.
  • Custom services. Free-form names you can add to the compose file. Useful for things outside the built-in 13.

What happens when you click Create

  1. The app pulls the laravelsail/php{X}-composer Docker image (cached after first time).
  2. Runs laravel new --no-interaction inside that container, against your projects folder.
  3. Runs composer require laravel/sail --dev followed by php artisan sail:install --with=... for the services you picked.
  4. Allocates host ports for every service and writes them into .env (APP_PORT, FORWARD_DB_PORT, FORWARD_REDIS_PORT, etc.).
  5. Sets COMPOSE_PROJECT_NAME so containers don't collide with other projects.
  6. If local URLs are on, regenerates the Traefik config so http://<name>.<tld> resolves to your new project.

The build output streams live, so you can see what's happening.

Clone from Git

For projects that already exist somewhere remote. Click Create and pick "Clone from Git".

  • Repository URL. HTTPS, SSH, or shorthand like git@github.com:org/repo all work.
  • Project name. Optional. If you leave it blank, the app derives one from the URL.
  • Branch. Optional. Falls back to whatever the remote's default is.
  • PHP version. Used if the repo doesn't already have Sail installed.

After cloning, the app checks if the repo has Sail. If not, it runs composer require laravel/sail --dev and sail:install inside the same composer Docker image used for new projects. Either way it allocates ports and registers the project.

Import an existing folder

For projects you already have on disk. Click Create and pick "Import existing".

  • Browse to the folder, or paste the path. ~ gets expanded.
  • The folder must contain a compose.yaml (or docker-compose.yml) and a .env file.
  • Ports are read from the FORWARD_* keys in .env. The app doesn't change anything.
  • If compose.yaml is present but Sail isn't fully installed, the app won't try to fix it. The folder gets registered as-is.

Start, stop, delete

Start a project

  1. Click the play button on the project row, or open the project and click Start.
  2. The app runs docker compose up -d --wait so it blocks until the containers report healthy.
  3. It runs php artisan migrate --force so a fresh project doesn't 500 on every page (Laravel 11+ uses the database session driver by default).
  4. Any enabled auto-commands fire next.

Stop a project

Stop runs docker compose down. Service-mode auto-commands get killed cleanly first.

Bulk actions

On the project list, you'll see "Start all" and "Stop all" buttons. They iterate sequentially with a small delay between each, so Docker doesn't get hammered.

Delete a project

From the project's overview, click the trash icon. You'll get a confirmation modal with two options:

  • Remove from Sail Manager only. Stops the containers and unregisters. Files stay on disk.
  • Remove and delete folder. Same as above, plus deletes the project folder.

The Docker image cache and your Docker volumes are not touched either way.

How ports get assigned

Sail's defaults pin every project to the same host ports (80, 3306, 6379, etc.), which is why you can only run one project at a time out of the box. Sail Manager fixes this by giving every service in every project a unique host port.

On Mac, just probing 127.0.0.1 isn't enough. Docker holds the IPv6 wildcard ([::]) when it binds a port, so a port can look free on IPv4 and conflict anyway. The allocator binds both 0.0.0.0:<port> and [::]:<port> before claiming a port.

All of this gets written into the project's .env. The compose file is never touched, so pulling teammate changes never conflicts with what the app set up.