pickeringtech / harbour
Lightweight isolated Laravel environments for parallel development.
Requires
- php: ^8.4
- composer-runtime-api: ^2.0
- illuminate/console: ^13.0
- illuminate/contracts: ^13.0
- illuminate/database: ^13.0
- illuminate/events: ^13.0
- illuminate/filesystem: ^13.0
- illuminate/process: ^13.0
- illuminate/support: ^13.0
Requires (Dev)
- giorgiosironi/eris: ^1.1
- infection/infection: ^0.35.4
- larastan/larastan: ^3.8
- laravel/pint: ^1.25
- orchestra/testbench: ^11.2
- phpunit/phpunit: ^12.5
- vimeo/psalm: ^6.16
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v0.0.7
- v0.0.6
- v0.0.5
- v0.0.4
- v0.0.3
- v0.0.2
- v0.0.1
- dev-rpickz/feature-add-first-class-orca-ide-lifecycle-integ
- dev-rpickz/quality-reach-100-coverage-and-enforce-the-gate
- dev-chore/add-parallel-work-planning-skill
- dev-rpickz/feature-add-first-class-worktrunk-lifecycle-inte
- dev-feature/release-hardening-2-5
- dev-docs/harbour-in-five-minutes
- dev-rpickz/reduce-releases-to-one-human-pr-without-weakenin
- dev-fix/stable-owned-port-reservations
- dev-fix/stale-workspace-recovery
- dev-release/v0.0.5-declaration
- dev-release/v0.0.5
- dev-feat/zero-friction-install
- dev-rpickz/normalize-release-signing-key
- dev-rpickz/declare-v0-0-4
- dev-rpickz/prepare-v0-0-4
- dev-rpickz/automate-immutable-releases-from-an-append-only
- dev-fix/selected-stack-preflight
- dev-rpickz/harden-setup-retry-diagnostics-and-installer-fin
This package is auto-updated.
Last update: 2026-09-17 10:27:01 UTC
README
Harbour
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
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 thedocker-compose.*equivalents; - Herd services from
herd.yml; - Laravel choices and host ports from
.envand.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
- Getting started — installation, discovery, and the first workspace
- Workspaces — clones, worktrees, identity, setup, and teardown
- Environment templates — variables, precedence, and secrets
- Databases and Laravel state isolation — databases, Redis, cache, sessions, queues, and Horizon
- Vite and Reverb — collision-free development processes
- Docker and Docker Compose — optional workspace resources
- Orca — lifecycle contract and current upstream blocker
- Worktrunk — first-class blocking create, merge, and remove lifecycle integration
- Herdr — copy/pasteable integration recipe
- Safety and resource ownership — why teardown is trustworthy
- Support matrix — the automated evidence behind every selectable integration
- Architecture — lifecycle and design decisions
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.