Search by

pickeringtech / harbour

rpickz

Lightweight isolated Laravel environments for parallel development.

Package info

github.com/pickeringtech/harbour

Homepage

pkg:composer/pickeringtech/harbour

Statistics

Installs: 41

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 11

v0.0.7 2026-09-05 07:38 UTC

README

Harbour

CI License: MIT

Lightweight isolated Laravel environments for parallel development.

Share infrastructure where practical. Isolate mutable state where necessary. Make every Laravel checkout immediately usable.

Harbour gives every Laravel clone or Git worktree its own ports, database, Redis namespaces, sessions, queues, and environment—without launching another complete PHP, database, Redis, and Node stack. PHP and Node stay native; shared infrastructure stays shared.

Harbour in 5 minutes

Requires Laravel 13+, PHP 8.4+, Composer, and Node for Vite. Host PHP needs the PDO driver for your chosen database. Docker is needed only when you choose Docker Compose services.

Once, in the primary checkout

composer require --dev pickeringtech/harbour
php artisan workspace:install

Choose auto-detection or select the services yourself. Choose Docker Compose if Harbour should provide them. Accept setup, dependency installation when offered, and Launch Laravel and Vite now? Harbour prints the application URL when it is ready.

Press Ctrl+C to stop Laravel and Vite, then commit the project files Harbour lists. This shares the Harbour policy with every worktree; local workspace state stays gitignored.

On each parallel agent worktree

composer install
composer workspace:dev

The first command installs that checkout's dependencies. The second creates its isolated ports, database, namespaces, and .env, then launches Laravel and Vite. Press Ctrl+C to stop them.

Before removing a worktree

composer workspace:teardown -- --force

This removes only that worktree's Harbour-owned resources and restores its previous .env. It does not touch another worktree or shared infrastructure.

Why Harbour

Without Harbour, each worktree runs a full stack. With Harbour, native worktrees use isolated namespaces on shared infrastructure.

We love Sail. It does an excellent job of giving a Laravel project a complete, reproducible Docker development stack. Harbour addresses a narrower need: when many clones or worktrees run in parallel, repeating that complete stack for every checkout is unnecessarily heavyweight. Harbour keeps the native Laravel workflow and shares infrastructure while isolating each workspace's mutable state. The two tools serve different development modes and work well together.

Installation details

Run these once in the Laravel project's primary checkout:

composer require --dev pickeringtech/harbour
php artisan workspace:install

The first command adds Harbour as a development-only dependency. It starts nothing and changes no infrastructure.

The second command opens a keyboard-driven installer. Its first choice is deliberately simple:

  • Auto-detect from this project reads the existing project and shows one reviewable proposal; or
  • Choose components manually opens focused selectors for the database, cache, and mail transport, followed by a multi-select list for any additional components.

Auto-detection understands:

  • existing Sail/Compose services from compose.yaml, compose.yml, or the docker-compose.* equivalents;
  • Herd services from herd.yml;
  • Laravel choices and host ports from .env and .env.example; or
  • SQLite, file-backed state, and log mail when no infrastructure is configured.

Both the accepted auto-detect path and the manual path ask whether to set up the first workspace. The manual path can either connect Laravel to shared infrastructure or generate a workspace-managed docker-compose.harbour.yml. Installation separately asks whether to configure worktree lifecycle hooks. Choosing No is equivalent to --worktree-hooks=none and neither reads nor writes integration configuration. Worktrunk adds its project-scoped blocking setup and pre-removal hooks. Orca selection is present but fails closed on current releases because their archive hook does not yet block checkout deletion. After setup, the installer offers to launch Laravel and Vite as one attached development session. Press Ctrl+C to stop those application processes while leaving the selected infrastructure ready.

After that final selection, Harbour checks the exact runtime requirements for the chosen stack. It offers to install all missing project-level Composer integrations in one reviewed operation. Redis and Valkey use portable Predis by default, avoiding a host Redis extension entirely. Auto-detection retains PhpRedis when the host can load it and otherwise selects Predis; a project may still require PhpRedis explicitly. Machine-level requirements such as pdo_pgsql are reported separately with platform-specific guidance and an exact retry command that preserves the completed selection. Compose mode also requires Docker with the Compose v2 plugin.

Harbour creates .env.harbour and config/harbour.php, safely appends its state paths to .gitignore, and adds Composer workspace aliases when those names are free. Compose mode also creates docker-compose.harbour.yml. Existing project files and scripts are never replaced by default. --reconfigure replaces only files carrying Harbour's generated-file marker; project-authored files, .gitignore, and Composer scripts keep their non-destructive rules. Without that flag, the installer prints the exact protected paths to remove.

--worktree-hooks=orca is reserved for a runtime with a machine-readable, verified blocking-archive capability. No current Orca release qualifies, so the selection reports unsupported before changing project files. Supported Worktrunk 0.76.x remains available through .config/wt.toml. See the Orca status and Worktrunk guide.

Harbour reads Sail and Herd configuration; it does not silently start, rewrite, or take ownership of either tool. It configures native Laravel processes to use their published host ports and shared services safely. The accepted proposal names the host/port prerequisites that must already be listening. Detection never silently changes shared infrastructure into Compose.

For deterministic agent or CI installation, accept discovery without prompts:

php artisan workspace:install --detect --no-interaction

Or make every choice explicit:

php artisan workspace:install \
    --database=postgresql \
    --cache=redis \
    --mail=mailpit \
    --with=meilisearch,minio \
    --compose \
    --start \
    --install-dependencies \
    --worktree-hooks=worktrunk \
    --no-interaction

--compose generates isolated service containers while PHP and Node remain native. --start immediately performs workspace:setup, and --install-dependencies authorizes the project-local Composer remediation in non-interactive runs. Interactive users can choose --launch to skip the final launch prompt. The main groups also accept -d, -c, and -m. See the installation guide for the supported Sail-compatible services and exact detection rules.

Daily worktree workflow

Commit the project-level files created by workspace:install. Then a new clone or worktree needs only:

composer install
composer workspace:dev

composer install restores vendor/, which Git worktrees do not share. workspace:dev identifies this checkout, atomically reserves ports, creates its isolated database and Laravel namespaces, preserves and renders .env, runs normal migrations, and starts only explicitly configured optional Docker resources. It then starts Laravel and Vite together in the foreground; Ctrl+C stops both cleanly. Automation that supplies its own process manager can keep using composer workspace:setup. Configured seeding runs on first setup and after --fresh, not on every convergent setup; pass --seed when an intentional repeat is required.

Inspect it:

composer workspace:status
php artisan workspace:debug

Before the external tool removes the worktree:

composer workspace:teardown -- --force

Teardown removes only resources Harbour can prove it owns and restores the original .env. --force skips interaction; it never weakens ownership or path safety.

Core commands

Command Purpose
workspace:install Prepare and commit the project's Harbour policy once.
workspace:setup Create or reconcile this checkout's isolated environment.
workspace:dev Set up and launch Laravel plus Vite as one attached session.
workspace:status Read its concise persisted status without scanning the machine.
workspace:env Emit table, JSON, dotenv, or safely escaped shell variables.
workspace:render Re-render .env from current state without clobbering hand edits.
workspace:debug Explain variable provenance while redacting secrets.
workspace:teardown Remove proven-owned resources and restore .env.
workspace:uninstall Tear down the workspace and remove only Harbour-managed project policy.

Commands intended for automation support stable JSON output and HARBOUR_- prefixed error codes. Non-interactive fresh setup and teardown require --force; that flag never weakens ownership checks.

To remove Harbour later, run composer workspace:uninstall -- --force, then composer remove --dev pickeringtech/harbour. The first command removes only policy still carrying Harbour's generated marker and exact Composer aliases. Unmarked replacements and project-defined aliases are retained for review.

Setup and render also checksum the current Harbour-rendered .env. If it was edited, move durable values into .env.harbour or pass --force to replace it.

Environment template

Harbour renders one deliberately small template, .env.harbour. Interpolation supports only ${VARIABLE}; an unresolved variable fails instead of becoming an empty string.

APP_NAME=Acme
APP_ENV=local
APP_KEY=${APP_KEY}
APP_URL=${APP_URL}
APP_PORT=${APP_PORT}

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=${DB_DATABASE}

REDIS_PREFIX=${REDIS_PREFIX}
CACHE_PREFIX=${CACHE_PREFIX}
SESSION_COOKIE=${SESSION_COOKIE}
REDIS_QUEUE=${REDIS_QUEUE}
HORIZON_PREFIX=${HORIZON_PREFIX}

VITE_PORT=${VITE_PORT}
REVERB_PORT=${REVERB_PORT}
REVERB_SERVER_PORT=${REVERB_PORT}

Laravel's default public/hot file is already local to each worktree, so Harbour keeps Laravel and Vite on that shared convention. Normal Laravel Vite projects need no hot-file customization. workspace:dev passes the allocated strict port to Vite automatically. Advanced custom hot files are also supported without an AppServiceProvider edit.

Proven in real worktrees

The release acceptance job creates a real Laravel 13 application and two real Git worktrees, installs them concurrently, launches Vite and Reverb on distinct ports, proves PostgreSQL and Redis isolation, exercises optional Docker and Compose resources, tears one workspace down without affecting the other, then repeats cleanup after a deliberately failed setup.

The quality gate also includes PostgreSQL, MySQL/MariaDB, SQLite, Redis, Docker, Compose, multi-process concurrency, failure injection, property/fuzz testing, strict Larastan, formatting, mutation testing, and a 100% executable-statement coverage requirement enforced by the same composer test command locally and in CI.

Documentation

Requirements and non-goals

Harbour supports PHP 8.4+, Laravel 13+, Linux, and macOS. The installer derives PHP extensions and Laravel client packages from the stack the user actually selects and checks them before creating project files. Docker and the Compose v2 plugin are needed only when Compose resources are selected.

Harbour does not create Git worktrees, manage coding agents, install PHP or Node runtimes, run background daemons, manage Reverb/queues/schedulers, require Docker, replace Compose or Sail, deploy production systems, or support non-Laravel frameworks. Its optional workspace:dev session keeps only Laravel and Vite attached to the current terminal.

Security

Please report vulnerabilities privately as described in SECURITY.md. See CONTRIBUTING.md for development and release quality gates.

License

Harbour is open-source software licensed under the MIT License.

Made with love by Pickering Technologies (PickTech).

Sail less. Ship more.