Console Contracts
This page covers the behavior you can rely on when building on the Console package.
Custom command contract
A custom command should extend Quantum\Console\CliCommand and implement exec():
use Quantum\Console\CliCommand;
class SendReportsCommand extends CliCommand
{
protected ?string $name = 'reports:send';
protected ?string $description = 'Send pending reports';
public function exec(): void
{
$this->info('Sending reports...');
}
}
Contract:
exec()is the command body- command metadata is declared through properties, not constructor arguments
- input and output helpers are available only during
exec()
Argument and option declaration contract
Arguments use this shape:
protected array $args = [
['module', 'required', 'The module name'],
];
Options use this shape:
protected array $options = [
['force', 'f', 'none', 'Force execution'],
['path', 'p', 'optional', 'Custom path'],
];
Rules:
- argument entries are interpreted as
[name, mode, description] - option entries are interpreted as
[name, shortcut, mode, description, default?] - unsupported modes are silently ignored by the base class
getArgument()andgetOption()return an empty string when the key is missing
Prompt contract
Use confirm($message) when the command should ask before destructive or overwrite-heavy work.
Contract:
- the prompt format is
message [y/N] - the default answer is
No - commands that add a
--yesoption usually skip the prompt themselves; the base class does not do that automatically
Output contract
The helper methods write formatted lines directly to Symfony output:
output()plain lineinfo()green/info-style linecomment()comment-style linequestion()question-style lineerror()error-style line
The package does not buffer or structure output for later inspection.
Exit-status caveat
CliCommand::execute() always returns Symfony's success code after exec() finishes.
That means:
- printing an error does not automatically fail the process
- returning early from
exec()still exits successfully - commands that need a hard failure must throw or terminate explicitly
This matters for automation: do not assume every printed failure message produces a non-zero shell exit code.
Discovery contract
CommandDiscovery::discover() returns only metadata for command classes it can instantiate immediately.
Practical consequences:
- avoid required constructor parameters in commands meant for discovery
- avoid expensive constructor work when possible
- discovery is best for registration, listing, or help screens, not for lazy dependency setup