Search by

alex-kassel / workspace-development-toolkit

Alexander Macenko

Multi-workspace local package development toolkit for Laravel: manage, symlink, and develop isolated packages with ease.

Package info

github.com/alex-kassel/workspace-development-toolkit

pkg:composer/alex-kassel/workspace-development-toolkit

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.1 2026-09-11 23:16 UTC

This package is auto-updated.

Last update: 2026-09-11 23:17:21 UTC


README

Multi-workspace local package development toolkit for Laravel: manage, symlink, and develop isolated packages across git-ready workspaces.

RequirementsInstallationQuick StartCommandsTestingChangelog

Audit Verified Latest Version Laravel Support PHP Support PHPStan Level 8 License

Requirements

  • PHP: ^8.2 (PHP 8.2, 8.3, or 8.4)
  • Laravel: ^11.0, ^12.0, or ^13.0
  • Composer: ^2.2 with path repository support

Installation

Install the package via Composer into your Laravel application (typically as a dev dependency):

composer require alex-kassel/workspace-development-toolkit --dev

The package service provider (AlexKassel\WorkspaceDevelopmentToolkit\WorkspaceDevelopmentToolkitServiceProvider) and facade (Workspace) are automatically discovered by Laravel.

Optionally, publish the package configuration:

php artisan vendor:publish --tag=workspace-config

Table of Contents

  1. Requirements
  2. Installation
  3. Introduction & Philosophy
  4. Key Highlights
  5. Usage
  6. Command Reference
  7. Smart Developer Experience (DX)
  8. Under the Hood: Architecture & Manifest
  9. Real-World Recipes & Patterns
  10. Troubleshooting & Domain Exceptions
  11. Testing
  12. License

Introduction & Philosophy

Modern Laravel engineering often demands managing dozens of distinct codebases simultaneously:

  • Custom domain packages (DDD / modular monoliths).
  • Client-specific micro-applications and customizations.
  • Open-source libraries slated for Packagist publication.

Traditional approaches force developers into agonizing compromises: awkward repositories configurations in root composer.json, manual .gitignore edits, git submodules, or constantly jumping between disconnected project windows.

Workspace Development Toolkit bridges this gap by making your host Laravel application the centralized staging ground and mission control center:

  • Every package lives in its own directory with its own independent composer.json and can be initialized as a separate Git repository.
  • Workspaces are registered automatically as Composer path repositories with instant symlinking.
  • Zero custom logic is placed in the host application — the toolkit remains fully autonomous.

Key Highlights

  • 🚀 Zero-Friction Scaffolding: Create production-ready Laravel packages (with ServiceProvider, PSR-4 autoloading, and manifests) with a single artisan command.
  • 📦 Dual Workspace Architecture:
    • Nested (Multi-Vendor): packages/{vendor}/{package}/ for public libraries and diverse vendors.
    • Flat (Fixed-Vendor): labs/{package}/ or clients/{package}/ without redundant vendor subdirectories.
  • 🔗 Automated Symlinking: Optional instant installation into require or require-dev on package creation.
  • 🛡️ Defensive Developer Experience:
    • Auto-sanitizes namespaces and paths (e.g. Acme\Billing! -> acme/billing).
    • Forgiving input parser accepting Windows backslashes (\) or standard slashes (/).
    • Actionable <comment>How to fix:</comment> blocks on every error.
    • Context-aware <comment>Hint:</comment> blocks suggesting your next logical command.
  • 📋 Interactive CLI Manual: Built-in workspace:help command providing real-time cheatsheets and workflow guidance.

Usage

The toolkit supports both multi-vendor libraries and dedicated client or internal modules through flexible workspace paradigms.

The Two Workspace Paradigms

1. Multi-Vendor Workspace (Nested Structure)

  • Configuration: "vendor": null
  • Path Pattern on Disk: {workspace}/*/*
  • Directory Structure:
    packages/
    ├── alex-kassel/
    │   └── toolkit/
    └── spatie/
        └── custom-backup/
    
  • Best Suited For: Public open-source packages, vendor forks, or mixed teams.
  • Creating a Package:
    php artisan package:make my-vendor/my-package --workspace=packages

2. Fixed-Vendor Workspace (Flat Structure)

  • Configuration: "vendor": "my-vendor"
  • Path Pattern on Disk: {workspace}/*
  • Directory Structure:
    labs/
    ├── billing/          # composer name: "my-vendor/billing"
    ├── crm/              # composer name: "my-vendor/crm"
    └── notifications/    # composer name: "my-vendor/notifications"
    
  • Best Suited For: Internal company modules, domain services, or client workspaces where repeating the vendor name in the filesystem is redundant.
  • Creating a Package:
    php artisan package:make billing --workspace=labs
    (Composer package name automatically generated as my-vendor/billing, namespace: MyVendor\Billing).

Quick Start Tutorial (60 Seconds)

Step 1: Create a Flat Workspace with a Fixed Vendor

php artisan workspace:add labs --vendor=alex-kassel-labs --default
  • Adds labs/* path repository to root composer.json.
  • Adds /labs to .gitignore.
  • Marks labs as default workspace.

Step 2: Create and Install a Local Module

php artisan package:make ai-assistant --install --dev
  • Scaffolds labs/ai-assistant/src/AiAssistantServiceProvider.php.
  • Sets package manifest to alex-kassel-labs/ai-assistant.
  • Immediately runs composer require alex-kassel-labs/ai-assistant --dev.
  • Everything is active in your Laravel app!

Step 3: Inspect Workspaces

php artisan workspace:list

Interactive Help & CLI Guide

Run php artisan workspace:help at any time to view the interactive color-coded guide:

php artisan workspace:help

You can also view standard Laravel help for any specific command:

php artisan help package:make
php artisan help workspace:add

Command Reference

workspace:help

Displays a comprehensive, colorized interactive cheatsheet, detailing paradigms and practical workflows.

php artisan workspace:help

workspace:add

Registers a new workspace directory into composer.json (as a path repository), .gitignore, and workspace.json.

# Add a multi-vendor nested workspace:
php artisan workspace:add packages

# Add a flat workspace with a fixed vendor:
php artisan workspace:add labs --vendor=alex-kassel-labs

# Add and set as default:
php artisan workspace:add modules --vendor=app-core --default

Options:

  • --vendor=: Fixed vendor name for flat 1-level package structure.
  • --default: Set this workspace as the default workspace for package:make.

workspace:list

Lists all registered workspaces, their designated vendor, directory structure mode (Flat vs Nested), package count, and member packages.

php artisan workspace:list

Sample Output:

+-----------+---------+------------------+-----------+----------------+-------------------------------------------+
| Workspace | Default | Vendor           | Structure | Packages Count | Packages                                  |
+-----------+---------+------------------+-----------+----------------+-------------------------------------------+
| labs      | No      | alex-kassel-labs | Flat      | 2              | ai-assistant                              |
|           |         |                  |           |                | telemetry                                 |
| packages  | Yes     | (none / multi)   | Nested    | 1              | alex-kassel/workspace-development-toolkit |
+-----------+---------+------------------+-----------+----------------+-------------------------------------------+

workspace:default

Sets the active default workspace. Any subsequent package:make call without --workspace will target this workspace.

php artisan workspace:default labs

workspace:clone

Clones a package repository from Git/GitHub into a target workspace, registers it in workspace.json, and optionally symlinks it via Composer.

# Clone via shorthand (resolved using repository_template, e.g. GitHub SSH/HTTPS):
php artisan workspace:clone spatie/laravel-ray --workspace=packages

# Clone via full SSH or HTTPS URL:
php artisan workspace:clone git@github.com:vendor/package.git

# Clone and immediately symlink as development dependency:
php artisan workspace:clone vendor/package --install --dev

# Recursively clone internal dependencies from trusted organizations:
php artisan workspace:clone vendor/package --recursive

# Clone the toolkit itself into a local workspace for active contribution:
php artisan workspace:clone --self

php workspace restore (Standalone CLI Runner)

Restores and clones missing workspace packages on fresh machines before running composer install — runs with zero framework dependencies:

# Checks workspace.json and git clones any missing packages:
php workspace restore

# Verify presence of all workspace packages on disk:
php workspace status

Tip

This command is automatically registered in your root composer.json under pre-install-cmd and pre-update-cmd, ensuring all local workspace repositories exist before Composer resolves path dependencies!

workspace:remove

Unregisters a workspace from root composer.json and workspace.json.

php artisan workspace:remove labs

Note

Physical files and directories on disk are never deleted by workspace:remove. An actionable hint will remind you how to remove the folder manually if desired.

package:make

Scaffolds a new minimal Laravel package with a ServiceProvider, composer.json, and PSR-4 autoloading.

# In a multi-vendor workspace (requires vendor/package):
php artisan package:make my-vendor/my-package --workspace=packages

# In a fixed-vendor workspace (single-word allowed):
php artisan package:make analytics --workspace=labs

# Create and link immediately as dev-dependency:
php artisan package:make billing --workspace=labs --install --dev

Options:

  • --workspace=: The target workspace (defaults to current default workspace).
  • --install: Immediately trigger composer require for the package upon creation.
  • --dev: Install into require-dev instead of require (used in conjunction with --install).

package:alias

Assigns a clean, customized directory alias to a package residing in a flat (fixed-vendor) workspace without altering its Composer package name.

# Assign a directory alias using arguments:
php artisan package:alias billing MyBilling

# Or using the --as option:
php artisan package:alias billing --as=MyBilling

Options:

  • --as=: Alternate option to specify the new directory alias.
  • --alias=: Synonym for --as.

Note

Directory aliasing renames the folder on disk, adjusts workspace.json, and triggers composer dump-autoload automatically to refresh PSR-4 autoload mappings.

package:install

Links an existing workspace package into the root application using Composer.

# By canonical name:
php artisan package:install alex-kassel-labs/ai-assistant --dev

# Or by short name (if belonging to a fixed-vendor workspace):
php artisan package:install ai-assistant --dev

package:uninstall

Removes a package from root composer.json via composer remove.

# By canonical name:
php artisan package:uninstall alex-kassel-labs/ai-assistant

# Or by short name:
php artisan package:uninstall ai-assistant

Tip

package:uninstall automatically detects whether the package is located in require or require-dev and applies --dev automatically.

package:delete

Permanently uninstalls the package from root Composer (if installed) and deletes the package directory from disk.

# Interactive confirmation:
php artisan package:delete ai-assistant

# Force deletion without prompt:
php artisan package:delete ai-assistant --force

Note

package:delete includes built-in Git safety checks (via GitInspector) preventing accidental removal of dirty trees, unpushed commits, or stashed changes unless --force is provided.

package:skills

Discovers and materializes AI agent skills (SKILL.md) from a package's resources/skills into the host application's .agents/skills/ directory (or configured skills destination).

# Materialize published skills into the project (copy mode):
php artisan package:skills my-package

# Symlink skills for live development (changes sync immediately):
php artisan package:skills my-package --symlink

# Overwrite skills if already present:
php artisan package:skills my-package --force

# Remove all installed skills for this package from the project:
php artisan package:skills my-package --remove

Options:

  • --symlink: Create symlinks instead of copying files (ideal for live development within local workspaces).
  • --force: Force overwrite existing skills even if already present.
  • --remove: Remove all materialized skills associated with this package from the project.

Tip

The command strictly honors skill publishing lifecycle rules: skills in draft status (where status != 'published' in the SKILL.md frontmatter) are skipped automatically unless --force is specified.

package:check

Runs automated quality gates across local packages (Composer validation, Pint, PHPStan, PHPUnit/Pest).

# Check a single package (deep tier by default: Composer + Pint + PHPStan + Tests):
php artisan package:check my-package

# Run quick tier checks only (Composer + Pint in seconds):
php artisan package:check my-package --quick

# Run specific checks only:
php artisan package:check my-package --only=pint,phpstan

# Automatically fix code style with Pint:
php artisan package:check my-package --fix

# Run tests in an isolated temporary Laravel environment:
php artisan package:check my-package --isolated

# Check all registered packages across workspaces:
php artisan package:check --all

# Check all registered packages with quick checks:
php artisan package:check --all --quick

Options:

  • --quick: Run quick tier checks only (composer validation and pint style check). Default is deep tier (composer, pint, phpstan, tests).
  • --fix: Automatically format and fix code style issues using Pint.
  • --only=: Comma-separated list of checks to run (composer, pint, phpstan, tests, isolated).
  • --isolated: Install and test an independent temporary copy of the package in isolation.
  • --all: Verify all packages across all registered workspaces.

package:readme

Validates that a package's README.md adheres to compliance standards (required sections, heading, absence of placeholder tokens).

php artisan package:readme my-package

package:release-check

Runs pre-flight verification before releasing or tagging a package (checks git cleanliness, .gitattributes export-ignore, code quality, and README compliance).

# Full release pre-flight (includes isolated environment test):
php artisan package:release-check my-package

# Fast release pre-flight:
php artisan package:release-check my-package --fast

Smart Developer Experience (DX)

1. Robust Input Sanitization

The toolkit forgives unconventional inputs:

  • Pasted Class Names / Namespaces: php artisan package:make "AcmeStudio\SuperWidget" -> safely converted to acmestudio/superwidget.
  • Capital Letters & Symbols: php artisan package:make "MyVendor/Special_Package!" -> normalized to myvendor/special-package.
  • Slashes: Supports standard forward slashes (/), Windows backslashes (\), and repeated slashes (//).

2. Actionable <comment>How to fix:</comment> Guidance

Commands never fail silently with obscure system errors. Whenever validation fails, the terminal outputs clear instructions and exact copy-pasteable commands:

Invalid package name [billing]. Workspace [packages] requires a vendor prefix in 'vendor/package' format.
  How to fix: Specify both vendor and package name:
  php artisan package:make my-vendor/billing --workspace=packages

3. Contextual Next-Step Hints

After successful operations, commands guide you on what to do next:

Package [acme/billing] created successfully in [packages/acme/billing].

  Hint: To link this package into your application via Composer, run:
  php artisan package:install acme/billing
  Or as a dev-dependency: php artisan package:install acme/billing --dev

Under the Hood: Architecture & Manifest

Manifest Format (workspace.json)

The central registry is stored at the root of your Laravel project:

{
    "default": "labs",
    "workspaces": {
        "labs": {
            "vendor": "alex-kassel-labs",
            "packages": [
                "ai-assistant",
                "telemetry"
            ]
        },
        "packages": {
            "vendor": null,
            "packages": [
                "alex-kassel/workspace-development-toolkit"
            ]
        }
    }
}

Path Repositories in composer.json

  • For packages (vendor: null):
    {
        "name": "workspace-packages",
        "type": "path",
        "url": "packages/*/*"
    }
  • For labs (vendor: "alex-kassel-labs"):
    {
        "name": "workspace-labs",
        "type": "path",
        "url": "labs/*"
    }

Real-World Recipes & Patterns

Pattern A: Agency & Multi-Client Management

Create separate workspaces for each client project:

php artisan workspace:add clients/client-alpha --vendor=alpha-corp
php artisan workspace:add clients/client-beta --vendor=beta-corp

php artisan package:make payment-gateway --workspace=clients/client-alpha
php artisan package:make crm-sync --workspace=clients/client-beta

Pattern B: Modular Monolith / DDD

Organize domain modules cleanly in modules/:

php artisan workspace:add modules --vendor=my-app --default
php artisan package:make billing
php artisan package:make ordering
php artisan package:make inventory

Pattern C: Open-Source Library Incubator

Develop public packages ready for GitHub and Packagist:

php artisan workspace:add packages --default
php artisan package:make my-handle/laravel-cache-warmer --install --dev

Troubleshooting & Domain Exceptions

All exceptions thrown by the toolkit extend AlexKassel\WorkspaceDevelopmentToolkit\Exceptions\WorkspaceException and include a built-in solution suggestion:

Exception Class Cause Resolution
WorkspaceNotFoundException Specified workspace path is not registered. Run php artisan workspace:add <path> or check workspace:list.
PackageNotFoundException Target package was not found in any workspace. Check spelling or create it with package:make.
DefaultWorkspaceNotConfiguredException No default workspace is configured. Run php artisan workspace:default <path>.
ComposerProcessException Composer command failed or timed out. Inspect Composer error output; check dependency conflicts.
InvalidJsonException Corrupted composer.json or workspace.json. Fix syntax errors in the JSON file indicated in the error message.

Testing

The package includes a comprehensive PHPUnit test suite covering workspace manifest handling, package lifecycle, git safety, skill installation, and command interactions:

# Run tests from the host Laravel application:
php artisan test packages/alex-kassel/workspace-development-toolkit/tests --compact

# Or run PHPUnit directly:
vendor/bin/phpunit packages/alex-kassel/workspace-development-toolkit/tests

License

The MIT License (MIT). Please see License File for more information.