PHPackages                             milpa/runtime - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. milpa/runtime

ActiveLibrary[Framework](/categories/framework)

milpa/runtime
=============

The bootable Milpa kernel: composes milpa/core, milpa/container, milpa/events, milpa/http and milpa/resolver into container -&gt; dispatcher -&gt; architecture gate -&gt; plugin boot in the resolver's loadOrder -&gt; route registration, with zero Doctrine and zero legacy Web coupling. The active-plugins list is config/filesystem-driven, never a database entity.

v0.7.7(2w ago)01.2k—4.8%5Apache-2.0PHPPHP &gt;=8.3CI passing

Since Jul 9Pushed 1mo agoCompare

[ Source](https://github.com/getmilpa/runtime)[ Packagist](https://packagist.org/packages/milpa/runtime)[ RSS](/packages/milpa-runtime/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (9)Dependencies (65)Versions (21)Used By (5)

 [   ![Milpa](https://raw.githubusercontent.com/getmilpa/core/main/art/lockup/milpa-lockup-v-color-light.svg)  ](https://github.com/getmilpa)

Milpa Runtime
=============

[](#milpa-runtime)

> The **bootable Milpa kernel** — composes `milpa/core`, `milpa/container`, `milpa/events`, `milpa/http` and `milpa/resolver` into a running app with a config-driven plugin registry, architecture resolution before boot, and lifecycle events. Zero database, zero magic.

[![CI](https://github.com/getmilpa/runtime/actions/workflows/ci.yml/badge.svg)](https://github.com/getmilpa/runtime/actions/workflows/ci.yml)[![Packagist](https://camo.githubusercontent.com/58d1c93b80f7c7314bf15eabebdc2c266a6825641bbd868bebba986fd0aa418f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d696c70612f72756e74696d652e737667)](https://packagist.org/packages/milpa/runtime)[![PHP](https://camo.githubusercontent.com/ca03f11ea27dac4dedc8ad56a7bdfc4a9ff5feb825055f9d2983616115076607/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d254532253839254135253230382e332d3737376262342e737667)](https://www.php.net/)[![License](https://camo.githubusercontent.com/798509b4df525f56802b56f8096862487f08023e3d7561c68656f8dab10d0d6e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4170616368652d2d322e302d626c75652e737667)](LICENSE)[![Docs](https://camo.githubusercontent.com/c6dc6a3411e15b0ac7cc4583e8e6a8144181caedb82f5d98753353decda06d77/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646f63732d4150492532307265666572656e63652d626c75652e737667)](https://getmilpa.github.io/runtime/)

`milpa/runtime` is where the rest of the family stops being separate packages and becomes an app. `Kernel::boot()` wires a DI container, an event dispatcher, a pre-boot architecture resolution over every configured plugin, an ordered boot loop that emits lifecycle events at each step, and a route table assembled from whatever plugins contribute one. The active-plugins list is whatever `list` the caller passes in — a config array, a file `require`d into that array, or filesystem discovery the caller performs beforehand. **No Doctrine, no legacy `Milpa\Web`, no database-backed plugin registry** — those, if you want them, live in your host application or a plugin you add on top.

Install
-------

[](#install)

```
composer require milpa/runtime
```

Quick example
-------------

[](#quick-example)

A plugin declares itself with `#[PluginMetadata]` and, optionally, contributes routes by implementing `RouteProviderInterface`:

```
use Milpa\Attributes\PluginMetadata;
use Milpa\Http\HttpMethod;
use Milpa\Http\Routing\HandlerReference;
use Milpa\Http\Routing\Route;
use Milpa\Http\Routing\RouteResult;
use Milpa\Interfaces\Di\DIContainerInterface;
use Milpa\Interfaces\Plugin\PluginInterface;
use Milpa\Runtime\Http\RouteProviderInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

final class HelloController
{
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $name = $request->getAttribute(RouteResult::ATTRIBUTE)?->parameter('name', 'world') ?? 'world';

        return new \Nyholm\Psr7\Response(200, ['Content-Type' => 'text/plain'], "hello, {$name}");
    }
}

#[PluginMetadata(version: '1.0.0', author: 'Acme', site: 'https://example.test', name: 'HelloPlugin', type: 'Web')]
final class HelloPlugin implements PluginInterface, RouteProviderInterface
{
    public function __construct(private readonly DIContainerInterface $container)
    {
    }

    public function boot(): void
    {
    }

    public function install(): void
    {
    }

    public function uninstall(): void
    {
    }

    public function enable(): void
    {
    }

    public function disable(): void
    {
    }

    /** @return list */
    public function routes(): array
    {
        return [
            new Route(
                path: '/hello/{name}',
                methods: HttpMethod::GET,
                name: 'hello',
                handler: new HandlerReference(HelloController::class, 'handle'),
            ),
        ];
    }
}
```

`Kernel::boot()` builds the container, resolves the architecture, boots the configured plugins in the order the resolution's own report dictates — its `loadOrder[]`, still `provides` → `requires`, ties keeping the config order — and assembles the route table; `RequestHandler` matches a real PSR-7 request against it and dispatches to the resolved controller:

```
use Milpa\Runtime\Http\RequestHandler;
use Milpa\Runtime\Kernel;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\ServerRequest;

$kernel = Kernel::boot(['plugins' => [HelloPlugin::class]]);
$kernel->bootedPluginNames(); // -> ['HelloPlugin']

$handler = new RequestHandler($kernel, new Psr17Factory());
$response = $handler->handle(new ServerRequest('GET', '/hello/milpa'));

$response->getStatusCode();    // -> 200
(string) $response->getBody(); // -> 'hello, milpa'
```

No plugin can leave the boot loop undetected: `boot()` resolves the whole architecture graph through `milpa/resolver` (each plugin's `#[PluginMetadata]` ingested by `AttributeLoader`, the graph resolved by `GraphResolver`) and throws `ArchitectureBlockedException` — a `PluginDependencyException` subclass, so every existing catch keeps working — *before* any plugin boots when the graph is blocked. The exception carries the full `ResolutionReport` on `->report`, and its message is the report's own learnable first line: the error code, why it failed, the first fix, and an Academy learn link. The same resolution also *orders* the boot: the report's `loadOrder[]` (a dependency cycle blocks pre-boot as a learnable `MILPA_DEPENDENCY_CYCLE`, never a bare "circular dependency" crash). Capability entries ride in both shapes `#[PluginMetadata]`sanctions — a bare interface FQCN or a structured capability record — with every `requires`entry dispatched through `CapabilityRequirement::parse()`, so a rich record closes (or learnably blocks) the graph like any other dependency. Pass `hostProfile` (a `HostProfile::fromArray()` shape) in the config to resolve against your own architectural profile — absent, a deliberately permissive default keeps every graph that booted before booting still — and `evaluatedAt` (ISO-8601) as the clock for accepted-risk expiry. Every step along the way — `architecture.resolved` (carrying the resolver's full `ResolutionReport`, dispatched right before the unchanged `capability.resolved`), `plugin.booting` (vetoable via an `InterceptionSlot`), `plugin.booted`, `kernel.booted` — fires on the wired event dispatcher for observability or feature-flag plugins to hook into.

Composes the family
-------------------

[](#composes-the-family)

`milpa/runtime` doesn't reimplement anything the family already ships — it wires the pieces together and adds the boot sequence on top:

PackageOwns`milpa/core`Contracts (`PluginInterface`, `PluginMetadata`, events) the whole family builds on.`milpa/container`The DI container every plugin and controller is resolved through.`milpa/events`The dispatcher every lifecycle event (`plugin.booting`/`plugin.booted`, `architecture.resolved`, `capability.resolved`, `kernel.booted`) fires on.`milpa/http`Routing contracts — `Route`, `RouteResult`, `RouterInterface` — the route table is built from.`milpa/resolver`The pre-boot architecture gate AND the boot order — `AttributeLoader` ingests each plugin's `#[PluginMetadata]`, `GraphResolver` resolves the whole graph into the `ResolutionReport` that `architecture.resolved` carries, and that report's `loadOrder[]` is the sequence the boot loop follows.**`milpa/runtime`** (this package)**`Kernel::boot()`** itself: the wiring, the pre-boot architecture resolution call, the ordered boot loop with lifecycle events, and `Router`/`RequestHandler` — a minimal `RouterInterface` implementation and PSR-15 entry point over the assembled route table.Requirements
------------

[](#requirements)

- PHP **≥ 8.3**
- [`milpa/core`](https://packagist.org/packages/milpa/core) **^0.6**
- [`milpa/command`](https://packagist.org/packages/milpa/command) **^0.1**
- [`milpa/container`](https://packagist.org/packages/milpa/container) **^0.1**
- [`milpa/events`](https://packagist.org/packages/milpa/events) **^0.2**
- [`milpa/http`](https://packagist.org/packages/milpa/http) **^0.1.4**
- [`milpa/resolver`](https://packagist.org/packages/milpa/resolver) **^0.5.2**

Documentation
-------------

[](#documentation)

**Full API reference: [getmilpa.github.io/runtime](https://getmilpa.github.io/runtime/)** — generated straight from the source DocBlocks and dressed with the Milpa design system.

Contributing
------------

[](#contributing)

Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Please report security issues via [SECURITY.md](SECURITY.md), and note that this project follows a [Code of Conduct](CODE_OF_CONDUCT.md).

License
-------

[](#license)

[Apache-2.0](LICENSE) © Rodrigo Vicente - TeamX Agency.

---

Milpa is designed, built, and maintained by **[Rodrigo Vicente - TeamX Agency](https://teamx.agency/?utm_source=github&utm_medium=readme&utm_campaign=milpa&utm_content=runtime)**.

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance94

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 69% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

19

Last Release

16d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1993784?v=4)[rodrigomx](/maintainers/rodrigomx)[@rodrigomx](https://github.com/rodrigomx)

---

Top Contributors

[![rodrigoteamx](https://avatars.githubusercontent.com/u/269849276?v=4)](https://github.com/rodrigoteamx "rodrigoteamx (20 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (9 commits)")

---

Tags

bootableframeworkkernelmilpaphpphpframeworkpsr-15runtimebootstrapkernelmilpa

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/milpa-runtime/health.svg)

```
[![Health](https://phpackages.com/badges/milpa-runtime/health.svg)](https://phpackages.com/packages/milpa-runtime)
```

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.4k87.4M2.2k](/packages/symfony-symfony)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

86337.5k](/packages/flow-php-flow)[cakephp/cakephp

The CakePHP framework

8.9k20.0M1.9k](/packages/cakephp-cakephp)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[shopware/platform

The Shopware e-commerce core

3.4k1.5M3](/packages/shopware-platform)[tempest/framework

The PHP framework that gets out of your way.

2.3k37.6k21](/packages/tempest-framework)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
