cloud-castle / command
Быстрый раннер консольных команд для PHP 8.1+ без зависимостей: реестр с псевдонимами и ленивыми фабриками, строковые сигнатуры, команды из замыканий, подсказки при опечатке, хуки жизненного цикла, автодополнение, встроенные list/help, буферизованный раздельный вывод.
Requires
- php: >=8.1
- cloud-castle/cli: ^2.0
Requires (Dev)
- deptrac/deptrac: ^3.0 || ^4.0
- ergebnis/composer-normalize: ^2.45
- friendsofphp/php-cs-fixer: ^3.75
- icanhazstring/composer-unused: ^0.9
- infection/infection: ^0.29 || ^0.33
- minicli/minicli: ^4.2
- mnapoli/silly: ^1.10
- nette/command-line: ^1.8
- php-parallel-lint/php-parallel-lint: ^1.4
- phpmd/phpmd: ^2.15
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^1.12 || ^2.1
- phpstan/phpstan-deprecation-rules: ^1.2 || ^2.0
- phpstan/phpstan-phpunit: ^1.4 || ^2.0
- phpstan/phpstan-strict-rules: ^1.6 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.5
- psalm/plugin-phpunit: ^0.19 || ^0.20
- rector/rector: ^1.2 || ^2.0
- roave/security-advisories: dev-latest
- splitbrain/php-cli: ^1.3
- squizlabs/php_codesniffer: ^3.12 || ^4.0
- symfony/console: ^6.4
- vimeo/psalm: ^6.0
- webmozart/assert: ^1.11
Suggests
- cloud-castle/di: Ленивое создание команд из контейнера зависимостей
This package is auto-updated.
Last update: 2026-07-31 14:19:38 UTC
README
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CloudCastle Command
Быстрый раннер консольных команд: реестр по имени с псевдонимами и ленивыми фабриками, определения входа с проверкой и значениями по умолчанию, строковые сигнатуры, команды из замыканий, подсказки при опечатке, хуки жизненного цикла, встроенные
list/help/completion, буферизованный раздельный вывод и красивое оформление из коробки черезcloud-castle/cli. Без привязки к фреймворку.
Установка
composer require cloud-castle/command
Требуется PHP 8.1+. Единственная зависимость — cloud-castle/cli
(оформление вывода: ANSI-стили, таблицы, рамки) той же экосистемы.
Быстрый старт
<?php
use CloudCastle\Command\Application;
use CloudCastle\Command\Input;
use CloudCastle\Command\Output;
$app = new Application();
// Команда из замыкания — без отдельного класса.
$app->command('greet', static function (Input $input, Output $output): int {
$output->writeln('Привет, ' . ($input->getArgument(0) ?? 'мир'));
return 0;
}, 'Приветствие');
$output = new Output();
$app->handle(['greet', 'Мир'], $output);
echo $output->fetch(); // Привет, Мир
Строковые сигнатуры, значения по умолчанию и справка
<?php
use CloudCastle\Command\Application;
use CloudCastle\Command\Contract\ConfigurableCommand;
use CloudCastle\Command\HelpCommand;
use CloudCastle\Command\Input;
use CloudCastle\Command\InputDefinition;
use CloudCastle\Command\Output;
use CloudCastle\Command\Signature;
final class DeployCommand implements ConfigurableCommand
{
public function getName(): string { return 'app:deploy'; }
public function getDescription(): string { return 'Разворачивает сборку'; }
public function definition(): InputDefinition
{
// Декларативная сигнатура вместо ручных Argument/Option.
return Signature::define('deploy {target} {--f|format=json : Формат отчёта}');
}
public function execute(Input $input, Output $output): int
{
$output->writeln($input->getArgument(0) . ' / ' . $input->getOption('format'));
return 0;
}
}
$app = new Application();
$app->add(new DeployCommand());
$app->add(new HelpCommand($app->registry()));
$app->registry()->alias('d', 'app:deploy'); // псевдоним
$app->before(static fn (string $name) => error_log("start: $name")); // хук
$output = new Output();
$app->handle(['app:deploy', 'prod', '-f=yaml'], $output); // prod / yaml
$app->handle(['app:deploi'], $output); // подсказка: app:deploy
$app->handle(['help', 'app:deploy'], $output); // справка по сигнатуре
Возможности
- Реестр команд по имени —
add(),has(),get(),names(); запуск по имени с кодом завершения; перезапись одноимённых. - Псевдонимы —
registry()->alias('b', 'build'): короткие имена, не засоряющие список команд. - Ленивые фабрики —
registry()->factory('build', fn): команда создаётся при первом обращении (аналог CommandLoader), экономит время и память. - Команды из замыканий —
command('name', fn, 'описание'): команда без отдельного класса. - Строковые сигнатуры —
Signature::define('deploy {target} {--f|format=json}'): декларативное объявление входа одной строкой. - Определения входа —
Argument/Optionс проверкой обязательных, значениями по умолчанию, short-опциями (-f→--format), отрицаемыми флагами (--no-cache) и терминатором--. - Подсказки при опечатке — «возможно, вы имели в виду…» по расстоянию Левенштейна; скрытые команды не раскрываются.
- Хуки жизненного цикла —
before(),after(),onError()вокруг запуска. - Встроенные
list/help/completion— список с группировкой по пространству имён, справка по сигнатуре, автодополнение имён для оболочки. - Скрытые команды —
HiddenCommandне попадает в список и автодополнение. - Fail-safe запуск из argv — неизвестная команда, непройденная проверка и
исключение самой команды не роняют процесс: сообщение в поток ошибок, код
1. - Буферизованный раздельный вывод —
Outputкопит вывод и ошибки отдельно (fetch()/fetchErrors()), упрощая тестирование без глобального состояния. - Красивый вывод из коробки —
Outputреализует контрактcloud-castle/cli, поэтому ANSI-стили, таблицы и рамки пишутся прямо в вывод команд; встроенныйlistумеет цветной режим. Ленивое создание команд из контейнера —cloud-castle/di. Единственная runtime-зависимость —cloud-castle/cli.
Сравнение с аналогами
Сравнение — с раннерами и обработчиками CLI-ввода: symfony/console,
laravel/artisan, minicli, mnapoli/silly, splitbrain/php-cli,
nette/command-line. Оформление вывода (цвета, таблицы, прогресс-бар,
интерактив) вынесено в cloud-castle/cli и здесь не сравнивается. Все таблицы
содержат графу 🏆 Победитель.
Функциональность
| Возможность | command | symfony/console | laravel/artisan | minicli | mnapoli/silly | splitbrain/php-cli | 🏆 Победитель |
|---|---|---|---|---|---|---|---|
| Реестр команд по имени | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ | — |
| Псевдонимы команд | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | — |
| Ленивые фабрики команд | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | — |
| Команды из замыканий | ✅ | ❌ | ⚠️ | ✅ | ✅ | ❌ | — |
| Строковые сигнатуры входа | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | — |
| Определения аргументов/опций | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | — |
Отрицаемые флаги + терминатор -- | ✅ | ✅ | ✅ | ❌ | ✅ | ⚠️ | — |
| Подсказки при опечатке | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | — |
| Хуки жизненного цикла | ✅ | ✅ | ✅ | ❌ | ⚠️ | ❌ | — |
Встроенные list/help/completion | ✅ | ✅ | ✅ | ❌ | ✅ | ⚠️ | — |
| Скрытые команды | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | — |
| Буферизованный раздельный вывод | ✅ | ⚠️ | ⚠️ | ❌ | ⚠️ | ❌ | 🏆 command |
| Красивый вывод из коробки (стили, таблицы) | ✅ | ⚠️ | ⚠️ | ❌ | ⚠️ | ❌ | 🏆 command |
| Итого возможностей раннера | 13/13 | 10/13 | 12/13 | 3/13 | 10/13 | 3/13 | 🏆 command |
command — единственный, кто закрывает объединение раннер-возможностей всех
аналогов, сохраняя единственную инфраструктурную зависимость (cloud-castle/cli),
уникальный тестируемый буфер вывода и красивое оформление из коробки.
Производительность (2000 итераций, PHP 8.1.34)
| Библиотека | Время, мс | Относительно command | 🏆 Победитель |
|---|---|---|---|
| cloud-castle/command | 0.0013 | 1× | 🏆 |
| splitbrain/php-cli | 0.0015 | — * | |
| nette/command-line | 0.0024 | — * | |
| minicli/minicli | 0.0240 | ×18.5 | |
| symfony/console | 0.1386 | ×106.6 | |
| mnapoli/silly | 0.1634 | ×125.7 |
Потребление памяти (прирост на запуск)
| Библиотека | Память, КБ | 🏆 Победитель |
|---|---|---|
| cloud-castle/command | 0.1 | 🏆 |
| splitbrain/php-cli | 0.1 | |
| nette/command-line | 0.1 | |
| minicli/minicli | 0.1 | |
| symfony/console | 16.4 | |
| mnapoli/silly | 20.4 |
* — парсеры ввода (неполный цикл), вне ранжирования.
Числа — из реального изолированного прогона
benchmarks/compare.php(регистрация, разбор ввода и запуск, 2000 итераций, без Xdebug):XDEBUG_MODE=off php benchmarks/compare.php. Таблицы обновляются автоматически:composer docs:bench. splitbrain/php-cli и nette/command-line по модели — парсеры/single-command: они разбирают ввод, но исполнение делегируют коду приложения, поэтому их числа — нижняя оценка полного цикла (в их пользу); command всё равно быстрее и легче.
Безопасность
| Критерий | command | symfony/console | laravel/artisan | minicli | mnapoli/silly | 🏆 Победитель |
|---|---|---|---|---|---|---|
| Строгий вход: срез необъявленных опций | ✅ | ⚠️ | ⚠️ | ❌ | ⚠️ | 🏆 command |
| Разделение потоков вывода и ошибок | ✅ | ✅ | ⚠️ | ❌ | ✅ | — |
| Fail-safe: исключения не роняют процесс | ✅ | ✅ | ✅ | ⚠️ | ✅ | — |
| Неутечка скрытых команд в подсказках | ✅ | ⚠️ | ⚠️ | ❌ | ❌ | 🏆 command |
| Отсутствие глобального состояния | ✅ | ⚠️ | ❌ | ⚠️ | ⚠️ | 🏆 command |
| Минимальная поверхность атаки | ✅ | ❌ | ❌ | ✅ | ⚠️ | 🏆 command/minicli |
Качество кода
| Метрика | command | symfony/console | laravel/artisan | minicli | 🏆 Победитель |
|---|---|---|---|---|---|
| PHPStan | max + strict-rules | ~level 5 | ~level 5 | базовый | 🏆 command |
| Psalm | errorLevel 1 | не заявлен | не заявлен | не заявлен | 🏆 command |
| Покрытие тестами | 100% / файл | высокое | высокое | среднее | 🏆 command |
| Мутационное тестирование (MSI) | 100% | не публикуется | не публикуется | не публикуется | 🏆 command |
| Runtime-зависимостей | 1 (cli) | 3+ | много | 0 | 🏆 minicli |
Плюсы и минусы
Плюсы:
- Быстрее и легче всех сравниваемых — подтверждено реальными бенчмарками (см. таблицу выше), near-zero память на запуск.
- Суперсет раннер-возможностей без привязки к фреймворку: сигнатуры, замыкания, ленивые фабрики, подсказки, хуки, автодополнение.
- Красивый вывод из коробки — ANSI-стили, таблицы и рамки через
cloud-castle/cliпишутся прямо в вывод команд; безопасный строгий вход и fail-safe по умолчанию. - Тестируемость — буферизованный раздельный вывод, отсутствие глобального состояния; 100% покрытие и 100% MSI на самом пакете.
Минусы (честно):
- Моложе и менее распространён, чем symfony/console и laravel/artisan — меньше готовых интеграций и статей. Это единственный существенный компромисс.
- Одна инфраструктурная зависимость —
cloud-castle/cli(оформление вывода) той же экосистемы; для абсолютного нуля зависимостей уместнее minicli. - Нет привязки к конкретному фреймворку — by design; для глубокой интеграции с Laravel/Symfony их родные раннеры удобнее.
Рекомендации по применению
- Идеально: CLI-утилиты и консольные точки входа микросервисов, воркеры и cron-задачи, встраиваемые раннеры внутри библиотек — везде, где важны быстрый старт, малый вес и красивый вывод из коробки.
- С
cloud-castle/cli: утилиты с богатым выводом (цвета, таблицы, прогресс, интерактив) — экосистема ставится одной зависимостью. - symfony/console, laravel/artisan — предпочтительнее при глубокой интеграции с их экосистемами (бандлы, DI-контейнер фреймворка, планировщик).
- minicli — для сверхминималистичных скриптов без определений входа и справки.
Разработка
composer install
composer check # линтеры + статический анализ + тесты
composer fix # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci # полный CI-пайплайн локально
composer docs:bench # пересобрать таблицы производительности в документации
Полный список команд с описаниями: composer run-script --list.
Документация
- Репозиторий: https://gitverse.ru/cloud-castle/command
- Wiki (возможности, диаграммы, сравнения): https://gitverse.ru/cloud-castle/command/wiki
- История изменений: CHANGELOG.md
- Как внести вклад: CONTRIBUTING.md
- Кодекс поведения: CODE_OF_CONDUCT.md
- Политика безопасности: SECURITY.md
Лицензия
MIT © CloudCastle (alex-4-17@yandex.ru)
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano