consolidation/annotated-command
PHP library for building CLI commands from annotations/attributes. Define command names, options, arguments, and hooks in docblocks, then let it parse input and run methods. Used by Drush and other tools for fast, structured command definitions.
Start by requiring the package: composer require consolidation/annotated-command. (⚠️ Note: Typo in some docs—use annotated, not annoted.) Next, create a command class (e.g., src/Command/Deploy.php) with a method annotated like:
/**
* @command deploy:release
* @description Deploy the latest release to production
* @option env The environment (e.g. dev, staging, prod)
* @arg target The target server
*/
public function deploy($target, $options = ['env' => 'prod']): int
{
// ...
return 0;
}
Then bootstrap your Console application:
use Consolidation\AnnotatedCommand\AnnotatedCommandFactory;
use Symfony\Component\Console\Application;
$application = new Application();
$factory = new AnnotatedCommandFactory();
$factory->addCommandsFromDirectory(__DIR__ . '/src/Command');
$application->addCommands($factory->getCommands());
$application->run();
First use case: Replace verbose Command subclasses with lean, self-documenting annotated methods—ideal for internal devops tools or microservice CLIs.
AnnotatedCommandFileLoader or addCommandsFromDirectory() to auto-register commands in src/Command/*—keep related logic grouped by module (e.g., src/Command/DB/, src/Command/Cache/).AnnotatedCommandBase (if available) or create traits for cross-cutting concerns (e.g., OutputsJsonTrait, HandlesCredentialsTrait).@validate annotations not built-in); pre-validate inputs in the method body or via custom annotations (see Gotchas).DeployTest::testDeployCalculatesArtifactVersion()). For integration, mock InputInterface/OutputInterface and call the annotated method directly—no app kernel needed.services/api/src/Command/, services/worker/src/Command/) and load each independently.NOASSERTION means no license is asserted—legally risky for production use. Verify intent with maintainers; consider alternatives (e.g., Laravel Echo’s laravel-zero/framework with native Artisan patterns) if compliance matters.dump-autoload, double-check PSR-4 mapping in composer.json matches your directory structure. Run composer dump-autoload -o and inspect registered commands via $application->all()['deploy:release'].@option env won’t auto-cast to string/int—validate manually (e.g., if (!in_array($options['env'], ['dev', 'prod'])) { ... }) or add custom annotation processing.$application->find('deploy:release') to see Symfony’s parsed definition (arguments/options resolved). Use var_dump($factory->getCommands()) to verify discovery.AnnotatedCommandFactory.php, AnnotationData.php, and AnnotatedCommandBase.php for advanced behavior (e.g., custom annotation handlers, event hooks).CommandEventSubscriberInterface (if present) or override AnnotatedCommand::create() to inject services (e.g., Doctrine EntityManager) via constructor injection into command classes.How can I help you explore Laravel packages today?