Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cli Laravel Package

adhocore/cli

A lightweight PHP library to build interactive CLI apps with commands, options, prompts, and colored output. Create structured command-line tools quickly, with input helpers and utilities suited for both simple scripts and larger console applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require adhocore/cli
    

    Add to composer.json under autoload-dev if using for dev tools:

    "require-dev": {
        "adhocore/cli": "^2.0"
    }
    
  2. First Command Create a basic command class in app/Console/Commands/ (or your preferred directory):

    use Adhocore\Cli\Command;
    
    class HelloCommand extends Command
    {
        protected $name = 'app:hello';
        protected $description = 'Prints a greeting';
    
        public function handle()
        {
            $this->info('Hello, Laravel!');
        }
    }
    
  3. Register the Command In app/Console/Kernel.php, add to $commands:

    protected $commands = [
        \App\Console\Commands\HelloCommand::class,
    ];
    
  4. Run It

    php artisan app:hello
    

First Use Case: CLI Utility Script

For standalone scripts (e.g., deploy.php), bootstrap the CLI system:

require __DIR__.'/vendor/autoload.php';

$cli = new \Adhocore\Cli\Cli();
$cli->addCommand(new class() extends \Adhocore\Cli\Command {
    protected $name = 'deploy';
    protected $description = 'Deploys the application';

    public function handle() {
        $this->info('Deploying...');
    }
});
$cli->run();

Run with:

php deploy.php deploy

Implementation Patterns

Command Structure

Hierarchical Commands Leverage subcommands for modularity:

class UserCommand extends Command
{
    protected $name = 'user';
    protected $description = 'User management';

    public function handle()
    {
        $this->addSubcommand(new ListUsersCommand());
        $this->addSubcommand(new CreateUserCommand());
        $this->runSubcommand();
    }
}

Option/Argument Definitions Define in $options/$arguments arrays:

protected $arguments = [
    ['name', 'n', 'Required: User name', true],
];

protected $options = [
    ['--force', 'f', 'Force creation', false, false],
    ['--role', 'r', 'User role', false, 'admin'],
];

Access parsed values in handle():

$userName = $this->argument('name');
$force = $this->option('force');

Workflows

Interactive Prompts Use $this->ask() for user input:

$name = $this->ask('Enter user name', 'John Doe');
$confirm = $this->confirm('Proceed?', false);

Progress Bars For long-running tasks:

$progress = $this->createProgressBar(100);
for ($i = 0; $i <= 100; $i++) {
    $progress->advance();
    sleep(0.1);
}
$progress->finish();

Output Styling Use methods like:

  • $this->info() (green)
  • $this->warning() (yellow)
  • $this->error() (red)
  • $this->table() for tabular data.

Dependency Injection Pass services via constructor:

class DeployCommand extends Command
{
    protected $repository;

    public function __construct(UserRepository $repository)
    {
        $this->repository = $repository;
    }

    public function handle() {
        $this->repository->deploy();
    }
}

Integration Tips

Laravel Artisan Integration Extend Illuminate\Console\Command and use adhocore/cli for parsing:

use Adhocore\Cli\Parser;

class CustomCommand extends Command
{
    protected function getArguments()
    {
        return Parser::parseArguments($this->input->arguments());
    }
}

Standalone Scripts For non-Laravel projects, use the Cli facade:

$cli = new \Adhocore\Cli\Cli();
$cli->addCommand(new MyCommand());
$cli->run();

Configuration Load from .env or config files:

$config = new \Adhocore\Cli\Config('path/to/config.php');
$this->config = $config->get('key');

Gotchas and Tips

Pitfalls

  1. Argument/Option Naming Conflicts Avoid overlapping short flags (e.g., -v for --verbose and --version). Use unique prefixes:

    ['--verbose', 'v', '...'], // OK
    ['--version', 'V', '...'], // Avoids conflict with -v
    
  2. Case Sensitivity in Commands Command names are case-sensitive. Use snake_case consistently:

    // Correct:
    protected $name = 'app:deploy';
    
    // Avoid:
    protected $name = 'App:Deploy'; // Fails!
    
  3. Subcommand Execution Order Subcommands run in declaration order. Explicitly order critical ones:

    $this->addSubcommand(new CriticalTaskCommand());
    $this->addSubcommand(new OptionalTaskCommand());
    
  4. Output Buffering Issues Ensure STDOUT/STDERR are flushed for real-time progress:

    $this->output->flush();
    

Debugging

Enable Verbose Mode Add to handle():

$this->verbose('Debug info: ' . print_r($data, true));

Run with:

php artisan command:name --verbose

Inspect Parsed Input Dump raw input for troubleshooting:

$this->line('Raw arguments: ' . json_encode($this->input->arguments()));

Validation Errors Handle validation failures gracefully:

if ($this->option('required_flag') === null) {
    $this->error('Flag --required is mandatory.');
    return 1;
}

Tips

  1. Reuse Command Logic Extract shared logic into traits or base classes:

    trait HandlesDeployment
    {
        protected function deploy()
        {
            // Shared deployment logic
        }
    }
    
  2. Custom Help Sections Override getHelp() for structured output:

    public function getHelp()
    {
        return $this->formatHelp(
            "Usage: {$this->name} [options]",
            [
                ['--env=ENV', 'Specify environment (default: local)'],
            ],
            "Examples:"
            . "\n  {$this->name} --env=production"
        );
    }
    
  3. Environment Awareness Use APP_ENV for context-aware commands:

    if (app()->environment('local')) {
        $this->warning('Running in local mode; dry run enabled.');
    }
    
  4. Testing Commands Mock the CLI system in tests:

    $cli = new \Adhocore\Cli\Cli();
    $cli->addCommand(new MyCommand());
    $cli->run(['command:name', '--option=value']);
    
  5. Performance Optimization For heavy CLI tools, lazy-load dependencies:

    private $repository;
    public function getRepository() {
        return $this->repository ??= new UserRepository();
    }
    
  6. Cross-Platform Path Handling Use DIRECTORY_SEPARATOR or realpath() for paths:

    $path = realpath($this->argument('path'));
    
  7. Signal Handling Gracefully handle interrupts (Ctrl+C):

    \Adhocore\Cli\Signal::register(function() {
        $this->error('Operation cancelled.');
        exit(1);
    });
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky