PHPackages                             decodelabs/commandment - 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. [CLI &amp; Console](/categories/cli)
4. /
5. decodelabs/commandment

ActiveLibrary[CLI &amp; Console](/categories/cli)

decodelabs/commandment
======================

Console command interface

v0.3.1(9mo ago)05.3k10MITPHPPHP ^8.4CI passing

Since May 19Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/decodelabs/commandment)[ Packagist](https://packagist.org/packages/decodelabs/commandment)[ RSS](/packages/decodelabs-commandment/feed)WikiDiscussions develop Synced today

READMEChangelog (8)Dependencies (7)Versions (10)Used By (10)

Commandment
===========

[](#commandment)

[![PHP from Packagist](https://camo.githubusercontent.com/d6cfc652e72a96ac9bbf6f47f420827d1c88a1a25f4fb9f0706cb4e870140ad9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6465636f64656c6162732f636f6d6d616e646d656e743f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/commandment)[![Latest Version](https://camo.githubusercontent.com/4250dda07b711218cd1b7b6bb43a555c767abbffc279d9431177ec13650ff9ec/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6465636f64656c6162732f636f6d6d616e646d656e742e7376673f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/commandment)[![Total Downloads](https://camo.githubusercontent.com/cd28059a532ffc7c4456c77c70548fa76aeb89878ed4ee04fbed90cf7cc56b96/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6465636f64656c6162732f636f6d6d616e646d656e742e7376673f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/commandment)[![GitHub Workflow Status](https://camo.githubusercontent.com/77c29a3057b457a63dee01dde1d211a286708bc5f518cf972ccca7b99358c808/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6465636f64656c6162732f636f6d6d616e646d656e742f696e746567726174652e796d6c3f6272616e63683d646576656c6f70)](https://github.com/decodelabs/commandment/actions/workflows/integrate.yml)[![PHPStan](https://camo.githubusercontent.com/e25c14ce011edabdd0fbd2e10415b41cc5d66ed11ef3e5b7edd074c5bdd35a2d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d656e61626c65642d3434434331312e7376673f6c6f6e6743616368653d74727565267374796c653d666c6174)](https://github.com/phpstan/phpstan)[![License](https://camo.githubusercontent.com/ae0a462f53fb24f57d5c0e711407423e217ba4b60b5d11bccf1e423e9211527a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6465636f64656c6162732f636f6d6d616e646d656e743f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/commandment)

### Console command interface

[](#console-command-interface)

Commandment provides a unified system for building and dispatching console actions, mirroring the dispatcher and middleware stack of [Harvest](https://github.com/decodelabs/harvest).

---

Installation
------------

[](#installation)

This package requires PHP 8.4 or higher.

Install via Composer:

```
composer require decodelabs/commandment
```

Usage
-----

[](#usage)

Build your Action to interact with the command line. The `Request` object provides the raw console arguments and the means to parse them in a structured way.

Use `Argument` attributes on your Action class to define the arguments you want to accept. Constructor arguments are automatically injected into your Action class - import the Terminus `Session` to write to the output stream to keep your Actions portable.

```
namespace MyThing\Action;

use DecodeLabs\Commandment\Action;
use DecodeLabs\Commandment\Argument;
use DecodeLabs\Commandment\Request;
use DecodeLabs\Terminus\Session;

#[Argument\Value(
    name: 'input',
    description: 'Input value',
    required: true,
    default: 'default'
)]
#[Argument\Flag(
    name: 'verbose',
    shortcut: 'v',
    description: 'Enable verbose output'
)]
#[Argument\Option(
    name: 'potatoes',
    shortcut: 'p',
    description: 'How many potatoes?',
    default: 5
)]
class MyAction implements Action
{
    public function __construct(
        protected Session $io
    ) {
    }

    public function execute(
        Request $request
    ): bool {
        $this->io->writeLine('Hello world!');

        $this->io->writeLine('Input: '. $request->parameters->tryString('input'));

        if($request->parameters->asBool('verbose')) {
            $this->io->writeLine('Verbose output enabled');

            for($potato = 0; $potato < $request->parameters->asInt('potatoes'); $potato++) {
                $this->io->writeLine('Potato #'. ($potato + 1));
            }
        }

        return true;
    }
}
```

```
effigy my-action "this is my input" -v --potatoes=3
```

### Dispatching

[](#dispatching)

To run your Action, create a `Dispatcher` and a `Request` object, then call the `dispatch()` method:

```
use DecodeLabs\Archetype;
use DecodeLabs\Commandment\Dispatcher;
use DecodeLabs\Monarch;

$dispatcher = new Dispatcher(
    Monarch::getService(Archetype::class)
);

$request = $dispatcher->newRequest(
    command: 'my-action',
    arguments: [
        'this is my input',
        '-v',
        '--potatoes=3'
    ],
    attributes: [
        'arbitrary' => 'data'
    ],
    server: [
        'override' => '$_SERVER'
    ]
);

$dispatcher->dispatch($request);
```

If you want to provide extra objects for dependency injection, you can add them to the `Slingshot` instance, either on the `Dispatcher` or on the `Request` object:

```
use MyThing\PotatoPeeler;
use MyThing\PotatoMasher;

$dispatcher->slingshot->addType(new PotatoPeeler());

$request = $dispatcher->newRequest('my-action', ['input ...']);
$request->slingshot->addType(new PotatoMasher());
$request->slingshot->addParameter([
    'arbitrary' => 'data'
]);

$dispatcher->dispatch($request);
```

You can then reference these types in your Action constructor:

```
namespace MyThing\Action;
use DecodeLabs\Commandment\Action;
use DecodeLabs\Commandment\Request;
use DecodeLabs\Terminus\Session;
use MyThing\PotatoPeeler;
use MyThing\PotatoMasher;

class MyAction implements Action
{
    public function __construct(
        protected Session $io,
        protected PotatoPeeler $peeler,
        protected PotatoMasher $masher,
        protected string $arbitrary
    ) {
    }

    public function execute(
        Request $request
    ): bool {
        // Do the thing
        return true;
    }
}
```

### Middleware

[](#middleware)

Commandment supports simple middleware which can be used to modify the request before the Action is executed. It doesn't need to handle the `$next` middleware like traditional middleware as the CLI context doesn't require traditional response handling. Instead, just return a modified `Request` object.

```
use DecodeLabs\Commandment\Middleware;

class MyMiddleware implements Middleware
{
    public function handle(
        Request $request,
    ): Request {
        // Do something with the request

        $request = $request->rewrite(
            command: 'redirected-action',
            arguments: [
                'new-argument'
            ],
        );

        return $request;
    }
}
```

Add the middleware to the dispatcher before dispatching:

```
use MyThing\Middleware\MyMiddleware;

$dispatcher->addMiddleware(new MyMiddleware());
$request = $dispatcher->newRequest('my-action', ['input ...']);
$dispatcher->dispatch($request);
```

Licensing
---------

[](#licensing)

Commandment is licensed under the MIT License. See [LICENSE](./LICENSE) for the full license text.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance76

Regular maintenance activity

Popularity21

Limited adoption so far

Community17

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~19 days

Recently: every ~34 days

Total

8

Last Release

273d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8a241d64d12b3b5ee94197862ec1ec30b82ed2efa34a0cd7f4c3565a021daddd?d=identicon)[betterthanclay](/maintainers/betterthanclay)

---

Top Contributors

[![betterthanclay](https://avatars.githubusercontent.com/u/1273586?v=4)](https://github.com/betterthanclay "betterthanclay (38 commits)")

### Embed Badge

![Health badge](/badges/decodelabs-commandment/health.svg)

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

PHPackages © 2026

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