CLI Runtime
CLI entrypoint, lifecycle CliKernelu, command registry, exit codes a cron pattern se zámkem.
Overview
CLI runtime uses the same application composition model as HTTP runtime: ApplicationContext, merged Config, shared DI Container, service providers, and explicit integer exit codes. Command execution is coordinated by CliKernel and CommandRegistry.
CLI entrypoint
Applications normally run commands through the Composer binary vendor/bin/lemonade. The package binary resolves the application base path, builds ApplicationContext from the current environment, creates CliKernel through CliKernelFactory, and delegates to CliKernel::handle($argv).
vendor/bin/lemonade
vendor/bin/lemonade list
vendor/bin/lemonade app:example
CLI flow
Runtime flow: Composer binary -> package bin/lemonade -> CliEnvironmentResolver::resolveBasePath() -> ApplicationContextFactory::fromGlobals() -> CliKernelFactory::create() -> CliKernel::handle($argv) -> CliKernel::bootstrap() -> load shared and CLI config -> apply runtime app config -> register core providers -> register ConsoleServiceProvider -> register common framework providers -> register configured app providers -> build CommandRegistry -> execute CommandInterface::run($args) -> process exit code.
Command configuration
ConfigLoader maps app/Config/Commands.php to config key commands for CLI runtime. The file returns a list of command class-strings; each class must exist and implement CommandInterface.
<?php
declare(strict_types=1);
use App\Console\ExampleCommand;
return [
ExampleCommand::class,
];
Command contract
Each command must implement Lemonade\Framework\Cli\CommandInterface with name(), description() and run(array $args): int.
<?php
declare(strict_types=1);
namespace App\Console;
use Lemonade\Framework\Cli\CommandInterface;
final class ExampleCommand implements CommandInterface
{
public function name(): string
{
return 'app:example';
}
public function description(): string
{
return 'Run an example application command.';
}
/**
* @param list<string> $args
*/
public function run(array $args): int
{
fwrite(STDOUT, "Done\n");
return 0;
}
}
Running commands
The first CLI argument is the command name and the remaining values are passed unchanged to run(array $args). Empty command, list, --help, and -h print the command list and return exit code 0.
vendor/bin/lemonade
vendor/bin/lemonade list
vendor/bin/lemonade app:example --dry-run
Dependency injection
CommandRegistry resolves commands through the container ($container->get($commandClass)), so constructor injection works the same as in HTTP services/controllers. Service providers are the preferred place to register command dependencies.
Error handling
Exit code model from CliKernel: successful list/help returns 0, command result is forwarded from run(), unknown command returns 1, and unhandled exceptions are logged via ExceptionLogger, printed to stderr and return 1 (with stack trace in debug mode).
Use cases
CLI runtime is suitable for cron jobs, imports and exports, maintenance tasks, background workers and integrations where repeatable execution and process exit codes are required.
Boundary
ConsoleServiceProvider registers the command registry infrastructure. Application commands and their dependencies remain application code, while feature-specific framework commands can be added to Commands.php when their provider/package is used.