midsonlajeanty/composer-workspace-plugin

Bun-style monorepo workspaces for Composer: auto-registered path repositories (no repositories blocks needed) and fan-out commands across every member.

Maintainers

Package info

github.com/midsonlajeanty/composer-workspace-plugin

Type:composer-plugin

pkg:composer/midsonlajeanty/composer-workspace-plugin

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.1 2026-06-11 18:10 UTC

README

Composer Workspace Plugin - Bun-style monorepo workspaces for Composer

Build Status Total Downloads Latest Stable Version License

Bun-style monorepo workspaces for Composer

Features

  • No repositories blocks. Workspace libraries are auto-registered as symlinked path repositories the moment Composer runs anywhere inside the monorepo.
  • A workspace version tag. Every workspace library resolves as dev-workspace, so a member can declare "acme/support": "dev-workspace" — a valid constraint that can only ever be satisfied locally, never by Packagist.
  • Fan-out commands. Run scripts and Composer project-management commands across every member from the root: composer ws run test, composer ws update, composer ws require, …

Getting started

Requires PHP 8.3+ and Composer 2.3+.

Install globally so the plugin is active for every composer install run anywhere inside your monorepo (do the same in CI):

composer global require midsonlajeanty/composer-workspace-plugin
composer global config allow-plugins.midsonlajeanty/composer-workspace-plugin true

Or require it in the monorepo root only — fan-out commands then work from the root, and member installs driven by composer ws install inherit it.

Usage

Declaring a workspace

The workspace root is any composer.json declaring member globs under extra.packages:

{
    "extra": {
        "packages": [
            "./packages",
            "./services"
        ]
    }
}

Every immediate child of those directories containing a composer.json is a workspace member. Members of type project (applications) are never published as dependencies; everything else (libraries, plugins) is auto-registered.

The root is discovered by walking up from the current directory, like git discovers .git. In containers or other layouts where the monorepo structure is not preserved, point the plugin at the root explicitly:

export COMPOSER_WORKSPACE_ROOT=/var/monorepo

Depending on workspace libraries

Inside any member, just require the library — no repositories entry needed:

{
    "require": {
        "acme/support": "dev-workspace"
    }
}

@dev constraints also resolve against the workspace. The packages are symlinked, so edits to a library are live in every consumer instantly.

Fan-out commands

Besides list and run, any Composer command is proxied to every member. Each member runs in its own isolated process — scripts, plugins, and autoloaders never leak between members — and flags are forwarded verbatim, no -- separator needed:

composer ws list                                  # members and their scripts
composer ws run test                              # run a script everywhere it exists
composer ws run lint --filter=packages/*          # glob filter, repeatable
composer ws install                               # composer install in every member
composer ws update --with-all-dependencies        # flags forwarded as-is
composer ws update phpstan/phpstan                # one package, everywhere
composer ws require spatie/laravel-data           # add a dependency
composer ws require rector/rector --dev --filter=audit
composer ws remove laravel/pao --dev
composer ws dump-autoload --optimize
composer ws outdated
composer ws audit                                 # any Composer command works
composer ws run test --continue-on-error          # don't stop at the first failure

--filter and --continue-on-error belong to ws and are not forwarded; everything else reaches the proxied command untouched.

Contributing

You have a lot of options to contribute to this project! You can:

License

MIT