iviphp/console

Console commands, input parsing and terminal output for the IviPHP ecosystem.

Maintainers

Package info

github.com/iviphp/console

pkg:composer/iviphp/console

Transparency log

Statistics

Installs: 9

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

v0.1.0 2026-07-21 16:40 UTC

This package is not auto-updated.

Last update: 2026-07-21 23:13:44 UTC


README

Console commands, command-line input parsing and terminal output for the IviPHP ecosystem.

iviphp/console provides a framework-independent foundation for creating CLI applications, registering commands, parsing arguments and options, displaying command help and returning process exit codes.

Requirements

  • PHP 8.2 or later
  • iviphp/contracts
  • iviphp/support

Installation

composer require iviphp/console

Features

  • Closure-backed console commands
  • Custom command implementations
  • Command aliases
  • Hidden commands
  • Positional argument parsing
  • Long and short option parsing
  • Boolean, string and integer option helpers
  • Repeated options
  • Standard output and error streams
  • Optional ANSI terminal colors
  • Automatic command listings
  • Built-in help behavior
  • Application version output
  • Unknown-command suggestions
  • Configurable exception handling
  • Framework-independent contracts

Core concepts

Console manager

ConsoleManager coordinates:

  • command registration;
  • command resolution;
  • input parsing;
  • terminal output;
  • command execution;
  • help pages;
  • command listings;
  • version output;
  • exception handling;
  • process exit codes.

Console API

Console is the public application-facing wrapper around ConsoleManager.

Command

A command defines:

  • a unique name;
  • a description;
  • optional aliases;
  • a usage expression;
  • whether it is hidden;
  • execution logic.

Input

ArgvInput parses an argv-compatible array into:

  • executable script;
  • command name;
  • positional arguments;
  • named options;
  • original tokens.

Output

ConsoleOutput writes regular messages to standard output and errors to standard error.

ANSI terminal decoration can be detected automatically or configured explicitly.

Creating a console application

<?php

declare(strict_types=1);

use Ivi\Console\Console;
use Ivi\Console\ConsoleManager;

$manager = new ConsoleManager(
    applicationName: 'My Application',
    applicationVersion: '1.0.0'
);

$console = new Console($manager);

Creating a command

<?php

declare(strict_types=1);

use Ivi\Console\Contracts\InputInterface;
use Ivi\Console\Contracts\OutputInterface;

$console->command(
    name: 'hello',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        $output->writeln('Hello from IviPHP.');

        return 0;
    },
    description: 'Display a greeting.'
);

Run the command:

php console hello

Output:

Hello from IviPHP.

Command exit codes

Command handlers must return an integer between 0 and 255.

The console manager provides common exit-code constants:

use Ivi\Console\ConsoleManager;

ConsoleManager::SUCCESS;
ConsoleManager::FAILURE;
ConsoleManager::INVALID;

Their values are:

SUCCESS = 0
FAILURE = 1
INVALID = 2

Example:

$console->command(
    name: 'project:check',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        $output->success('Project configuration is valid.');

        return ConsoleManager::SUCCESS;
    }
);

Returning an exit code outside the supported range throws ConsoleException.

Positional arguments

$console->command(
    name: 'greet',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        $name = $input->argument(
            0,
            'Developer'
        );

        $output->writeln(
            "Hello, {$name}."
        );

        return 0;
    },
    description: 'Greet a person.',
    usage: 'greet [name]'
);

Run it:

php console greet Gaspard

Output:

Hello, Gaspard.

Retrieve all positional arguments:

$arguments = $input->arguments();

Check whether an argument exists:

if ($input->hasArgument(0)) {
    $name = $input->argument(0);
}

Argument indexes start at zero.

Long options

The parser supports boolean long options:

php console build --verbose

Retrieve the option:

$verbose = $input->option(
    'verbose',
    false
);

Options may use an equals sign:

php console build --environment=production
$environment = $input->option(
    'environment',
    'development'
);

Options may also use the following token as their value:

php console build --environment production

Disabled boolean options

Options prefixed with --no- are stored as false.

php console build --no-cache

Retrieve the normalized option name:

$cacheEnabled = $input->booleanOption(
    'cache',
    true
);

The value is false.

Short options

Single short options are supported:

php console build -v
$verbose = $input->hasOption('v');

Combined short flags are also supported:

php console build -abc

This creates the following options:

[
    'a' => true,
    'b' => true,
    'c' => true,
]

A short option may contain a value:

php console server:start -p=8080
$port = $input->integerOption(
    'p',
    8000
);

Stopping option parsing

The special -- token stops option parsing.

Every following token becomes a positional argument.

php console inspect -- --example --verbose

The command receives:

[
    '--example',
    '--verbose',
]

as positional arguments.

Repeated options

Repeated options are stored as arrays.

php console test --group=unit --group=integration
$groups = $input->option('group');

The result is:

[
    'unit',
    'integration',
]

Typed option helpers

Boolean options

$verbose = $input->booleanOption(
    'verbose',
    false
);

Recognized true values:

1
true
yes
on

Recognized false values:

0
false
no
off

String options

$environment = $input->stringOption(
    'environment',
    'development'
);

Integer options

$port = $input->integerOption(
    'port',
    8000
);

An invalid integer value throws ConsoleException.

Command aliases

$console->command(
    name: 'cache:clear',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        $output->success('Cache cleared.');

        return 0;
    },
    description: 'Remove all cached values.',
    aliases: [
        'cache:flush',
        'cc',
    ]
);

All of these execute the same command:

php console cache:clear
php console cache:flush
php console cc

Command names and aliases must be unique across the registry.

Usage expressions

$console->command(
    name: 'user:create',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        return 0;
    },
    description: 'Create an application user.',
    usage: 'user:create <email> [--admin]'
);

Display the command help:

php console help user:create

Output includes:

user:create

Description:
  Create an application user.

Usage:
  console user:create <email> [--admin]

Hidden commands

Hidden commands remain executable but are excluded from normal command listings.

$console->command(
    name: 'internal:sync',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        $output->writeln(
            'Internal synchronization complete.'
        );

        return 0;
    },
    hidden: true
);

Registering command objects

Commands may be created explicitly.

<?php

declare(strict_types=1);

use Ivi\Console\Command;
use Ivi\Console\Contracts\InputInterface;
use Ivi\Console\Contracts\OutputInterface;

$command = new Command(
    name: 'status',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        $output->success(
            'Application is running.'
        );

        return 0;
    },
    description: 'Display application status.',
    aliases: [
        'health',
    ],
    usage: 'status',
    hidden: false
);

$console->register($command);

Create a command from another callable:

$command = Command::fromCallable(
    name: 'queue:work',
    handler: [$worker, 'run'],
    description: 'Process queued jobs.'
);

Custom command classes

Applications may implement:

Ivi\Console\Contracts\CommandInterface

Example:

<?php

declare(strict_types=1);

use Ivi\Console\Contracts\CommandInterface;
use Ivi\Console\Contracts\InputInterface;
use Ivi\Console\Contracts\OutputInterface;

final class AboutCommand implements CommandInterface
{
    public function name(): string
    {
        return 'about';
    }

    public function description(): string
    {
        return 'Display application information.';
    }

    public function aliases(): array
    {
        return [];
    }

    public function usage(): string
    {
        return 'about';
    }

    public function isHidden(): bool
    {
        return false;
    }

    public function execute(
        InputInterface $input,
        OutputInterface $output
    ): int {
        $output->writeln(
            'Built with IviPHP.'
        );

        return 0;
    }
}

Register it:

$console->register(
    new AboutCommand()
);

Registering multiple commands

$console->registerMany([
    new AboutCommand(),
    new StatusCommand(),
    new CacheClearCommand(),
]);

Replace commands with matching primary names:

$console->registerMany(
    $commands,
    replace: true
);

Command registry

Retrieve the registry:

$registry = $console->registry();

Determine whether a command or alias exists:

if ($registry->has('cache:clear')) {
    $command = $registry->get(
        'cache:clear'
    );
}

Check only primary command names:

$exists = $registry->hasPrimary(
    'cache:clear'
);

Check aliases:

$isAlias = $registry->hasAlias('cc');

Resolve an alias to its primary name:

$name = $registry->resolveName('cc');

Result:

cache:clear

Listing commands

Return all commands:

$commands = $console->commands();

Exclude hidden commands:

$commands = $console->commands(
    includeHidden: false
);

Return command names:

$names = $console
    ->registry()
    ->names();

Return aliases:

$aliases = $console
    ->registry()
    ->aliases();

Example:

[
    'cache:flush' => 'cache:clear',
    'cc' => 'cache:clear',
]

Replacing a command

$console->replace(
    $updatedCommand
);

The command must already be registered under the same primary name.

Removing commands

$console->forget('cache:clear');

An alias may also be supplied:

$console->forget('cc');

The command and all its aliases are removed.

Built-in command list

When no command is supplied, the console displays the application name, version and visible commands.

php console

The same list is available through:

php console list

The built-in list behavior is used only when an application command named list is not registered.

Built-in help

Display all commands:

php console help

Display help for one command:

php console help cache:clear

A command may also request its help page through an option:

php console cache:clear --help

or:

php console cache:clear -h

The built-in help behavior is used only when an application command named help is not registered.

Version output

php console --version

or:

php console -V

Example output:

My Application 1.0.0

Render the version programmatically:

$console->renderVersion();

Terminal output

$output->write('Loading...');

Write with a newline:

$output->writeln('Complete.');

Semantic output methods are also available:

$output->info(
    'Reading configuration.'
);

$output->success(
    'Application installed.'
);

$output->warning(
    'Configuration file already exists.'
);

$output->error(
    'Unable to connect to the database.'
);

Regular messages are written to standard output.

Errors are written to standard error.

Creating console output

<?php

declare(strict_types=1);

use Ivi\Console\Output\ConsoleOutput;

$output = new ConsoleOutput();

Disable ANSI decoration:

$output = new ConsoleOutput(
    decorated: false
);

Enable it explicitly:

$output = new ConsoleOutput(
    decorated: true
);

Change it later:

$output->setDecorated(false);

Check the current setting:

if ($output->isDecorated()) {
    echo 'ANSI decoration enabled.';
}

Custom output streams

$outputStream = fopen(
    'php://memory',
    'w+'
);

$errorStream = fopen(
    'php://memory',
    'w+'
);

$output = new ConsoleOutput(
    outputStream: $outputStream,
    errorStream: $errorStream,
    decorated: false
);

Externally supplied streams remain owned by the application.

Streams created internally by ConsoleOutput are closed automatically.

Blank lines

The concrete ConsoleOutput implementation provides a newline helper:

$output->newLine();

Write several blank lines:

$output->newLine(2);

Writing directly to standard error

$output->writeError(
    'Raw error output.',
    newline: true
);

No semantic color is applied by writeError().

Creating input manually

<?php

declare(strict_types=1);

use Ivi\Console\Input\ArgvInput;

$input = new ArgvInput([
    'console',
    'server:start',
    '--host=127.0.0.1',
    '--port=8080',
]);

Retrieve parsed information:

$script = $input->script();

$command = $input->command();

$arguments = $input->arguments();

$options = $input->options();

$tokens = $input->tokens();

Creating input without a script token

$input = ArgvInput::fromTokens(
    [
        'cache:clear',
        '--store=files',
    ],
    script: 'ivi'
);

Reading global argv

$input = ArgvInput::fromGlobals();

This reads PHP's global $argv value.

Executing custom input

<?php

declare(strict_types=1);

use Ivi\Console\Input\ArgvInput;
use Ivi\Console\Output\ConsoleOutput;

$input = ArgvInput::fromTokens([
    'hello',
    'Gaspard',
]);

$output = new ConsoleOutput();

$exitCode = $console->run(
    $input,
    $output
);

Running the console application

A minimal executable file may look like this:

#!/usr/bin/env php
<?php

declare(strict_types=1);

require dirname(__DIR__)
    . '/vendor/autoload.php';

use Ivi\Console\Console;
use Ivi\Console\ConsoleManager;
use Ivi\Console\Contracts\InputInterface;
use Ivi\Console\Contracts\OutputInterface;

$console = new Console(
    new ConsoleManager(
        applicationName: 'Ivi Application',
        applicationVersion: '1.0.0'
    )
);

$console->command(
    name: 'hello',
    handler: static function (
        InputInterface $input,
        OutputInterface $output
    ): int {
        $name = $input->argument(
            0,
            'Developer'
        );

        $output->success(
            "Hello, {$name}."
        );

        return 0;
    },
    description: 'Display a greeting.',
    usage: 'hello [name]'
);

exit($console->run());

Make it executable:

chmod +x bin/console

Run it:

./bin/console hello Gaspard

Exception handling

ConsoleManager catches command exceptions by default.

$manager = new ConsoleManager(
    catchExceptions: true
);

When a command fails, the manager writes the exception message and returns exit code 1.

Disable automatic exception catching:

$console->setCatchExceptions(false);

Exceptions are then propagated to the calling application.

Check the current configuration:

if ($console->catchesExceptions()) {
    echo 'Exceptions are handled by the console.';
}

Debug exception output

Detailed exception output is disabled by default.

Enable it:

$console->setDebug(true);

Debug output includes:

  • exception class;
  • source file;
  • source line;
  • stack trace;
  • previous exception chain.

Check the current mode:

if ($console->isDebug()) {
    echo 'Console debug mode enabled.';
}

Detailed exception output should not normally be enabled in production environments.

Unknown command suggestions

When an unknown command is executed, the manager searches for similar registered commands.

php console cach:clear

The console may suggest:

Did you mean this command?
  cache:clear

Retrieve suggestions programmatically:

$suggestions = $console->suggestCommands(
    'cach:clear'
);

Limit the number of suggestions:

$suggestions = $console->suggestCommands(
    'cach:clear',
    maximumSuggestions: 3
);

Custom input implementations

Applications may implement:

Ivi\Console\Contracts\InputInterface

Required methods:

public function script(): string;

public function command(): ?string;

public function arguments(): array;

public function hasArgument(int $index): bool;

public function argument(
    int $index,
    mixed $default = null
): mixed;

public function options(): array;

public function hasOption(string $name): bool;

public function option(
    string $name,
    mixed $default = null
): mixed;

public function tokens(): array;

Custom output implementations

Applications may implement:

Ivi\Console\Contracts\OutputInterface

Required methods:

public function write(
    string $message,
    bool $newline = false
): void;

public function writeln(
    string $message = ''
): void;

public function info(string $message): void;

public function success(string $message): void;

public function warning(string $message): void;

public function error(string $message): void;

public function isDecorated(): bool;

public function setDecorated(
    bool $decorated
): void;

Exceptions

Console-system failures are represented by:

Ivi\Console\Exceptions\ConsoleException

Examples include:

  • invalid command names;
  • duplicate command registration;
  • unknown commands;
  • invalid aliases;
  • alias conflicts;
  • invalid input;
  • invalid argument indexes;
  • invalid option names;
  • command execution failures;
  • invalid exit codes;
  • unavailable streams;
  • terminal write failures;
  • invalid configuration.
<?php

declare(strict_types=1);

use Ivi\Console\Exceptions\ConsoleException;

try {
    $command = $console->get(
        'missing:command'
    );
} catch (ConsoleException $exception) {
    echo $exception->getMessage();

    $context = $exception->context();
}

Exception context intentionally excludes raw command arguments and option values.

Clearing the registry

Remove every registered command and alias:

$console->clear();

Return the number of registered commands:

$count = $console->count();

Determine whether the registry is empty:

if ($console->registry()->isEmpty()) {
    echo 'No commands registered.';
}

Design principles

iviphp/console follows these principles:

  • framework-independent command execution;
  • explicit input and output contracts;
  • predictable command and alias resolution;
  • simple closure-backed commands;
  • support for custom command classes;
  • safe exception context;
  • separate standard output and error streams;
  • explicit process exit codes;
  • optional terminal decoration;
  • compatibility with application-specific CLI architectures.

License

Ivi Console is open-source software released under the MIT License.

Maintainer

Maintained by Gaspard Kirira and Softadastra.