php-school/cli-menu
Build interactive command-line menus in PHP. Create selectable lists, checkboxes and radio items, submenus, and styled output with custom colors and layouts. Handle keyboard navigation and callbacks for a smooth TUI experience.
Start by installing via Composer:
composer require php-school/cli-menu
Then create a basic menu in your console command or standalone script:
use PHPSchool\CliMenu\CliMenu;
use PHPSchool\CliMenu\MenuBuilder;
require 'vendor/autoload.php';
$menu = (new MenuBuilder)
->setTitle('My CLI Tool')
->addOption('A', 'Run setup', function () { echo "Setting up...\n"; })
->addOption('B', 'Exit', function () { echo "Goodbye!\n"; return false; })
->build();
$menu->open();
This gives you a responsive, keyboard-navigable menu—arrow keys select, Enter confirms, Esc exits. Perfect for quick tooling like project scaffolding, config setup, or dev utility scripts.
false from a callback to exit the menu loop (e.g., for “Exit” or fatal-error handlers). Return null or omit to return to the menu.build().addSubMenu() to create hierarchical navigation:
->addSubMenu('Database', (new MenuBuilder)
->addOption('M', 'Migrate', $migrateCallable)
->addOption('S', 'Seed', $seedCallable)
)
$menu = $builder->build();
$menu->getRenderable()
->setOptionPaddingLeft(3)
->setSelectedStyle(new \PHPSchool\CliMenu\Style\SelectedStyle('bg_white', 'black'))
->setClosedBorderChars('═', '║', '╔', '╗', '╚', '╝');
addMultiSelect() for group selections (e.g., modules to enable), and render a summary before execution.xterm or modern cmd.exe/PowerShell. Ensure stream_isatty(STDOUT) is supported or fallback gracefully.open()—avoid mixing with event loops (ReactPHP/Swoole). For async flows, defer long-running tasks to background processes or spawn threads.setDisabled(true) on options for context-aware UI (e.g., “Next step only if DB configured”). Users can still navigate over disabled items, but Enter does nothing.? for help) by extending CliMenu and overriding handleKey(), or pre-pend addHelpItem() for standard help.STDERR—the menu overwrites the screen, so errors vanish unless explicitly captured.--ansi and check PHP_EOL differences across platforms—use PHPSchool\CliMenu\Terminal::getTerminal() for reliable auto-detection.How can I help you explore Laravel packages today?