Component-based Midnight Commander-style terminal application framework.
Create fullscreen, keyboard-driven interfaces with double-buffered rendering.
Build terminal UIs like you build web apps - with reusable components, clean architecture, and modern PHP.
// Simple as creating a PHP file
$app = new Application($symfonyApp);
$app->run(new CommandsScreen($commandDiscovery, $commandExecutor));
No complex setup. No learning curve. Just beautiful terminal UIs.
- π¨ Multiple Color Themes - Midnight Commander, Dark, and Light themes
- β‘ Double-Buffered Rendering - Flicker-free display with minimal ANSI sequences
- π§© Component-Based Architecture - Reusable UI components (Tables, Forms, Lists, Panels)
- β¨οΈ Full Keyboard Navigation - Function keys, arrow keys, and shortcuts
- π¦ Built-in Features - Command Browser, File Browser, Composer Manager
- π Extensible - Easy to create custom screens and components
- PHP 8.3 or higher
- Symfony Console 7.3+
- Terminal with ANSI color support (most modern terminals)
Install via Composer:
composer require cli/terminal
Create a simple PHP file (e.g., console
or ui
) that launches the Commander interface:
#!/usr/bin/env php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use Butschster\Commander\Application;
use Butschster\Commander\Feature\CommandBrowser\Screen\CommandsScreen;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandDiscovery;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandExecutor;
use Butschster\Commander\UI\Component\Layout\MenuBar;
use Butschster\Commander\UI\Theme\ColorScheme;
use Butschster\Commander\UI\Theme\MidnightTheme;
use Symfony\Component\Console\Application as SymfonyApplication;
// 1. Create Symfony Console Application
$symfonyApp = new SymfonyApplication('My App', '1.0.0');
// You can add your Symfony commands here:
// $symfonyApp->add(new YourCustomCommand());
// 2. Choose and apply theme
ColorScheme::applyTheme(new MidnightTheme());
// Available: MidnightTheme, DarkTheme, LightTheme
// 3. Create Commander application
$app = new Application($symfonyApp);
$app->setTargetFps(30);
// 4. Setup global menu bar (optional)
$globalMenu = new MenuBar([
'F1' => ' Help',
'F2' => ' Commands',
'F10' => ' Quit',
]);
$app->setGlobalMenuBar($globalMenu);
// 5. Register global shortcuts (optional)
$app->registerGlobalShortcut('F10', function () use ($app) {
$app->stop(); // Quit application
});
// 6. Create services and initial screen
$commandDiscovery = new CommandDiscovery($symfonyApp);
$commandExecutor = new CommandExecutor($symfonyApp);
$initialScreen = new CommandsScreen($commandDiscovery, $commandExecutor);
// 7. Run the application
$app->run($initialScreen);
chmod +x console
./console
That's it! You now have a fullscreen terminal UI with:
- β¨ Midnight Commander-style interface
- π Command browser with search and execution
- β¨οΈ Keyboard navigation (ββ, Enter, F10 to quit)
- β‘ Smooth, flicker-free rendering
If you're working within a Symfony/Laravel/Spiral application, you can create a Console command instead:
Click to see Symfony Console Command example
<?php
declare(strict_types=1);
namespace App\Console;
use Butschster\Commander\Application;
use Butschster\Commander\Feature\CommandBrowser\Screen\CommandsScreen;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandDiscovery;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandExecutor;
use Butschster\Commander\UI\Theme\ColorScheme;
use Butschster\Commander\UI\Theme\MidnightTheme;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'app:ui', description: 'Launch Commander UI')]
final class UICommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
$symfonyApp = $this->getApplication();
ColorScheme::applyTheme(new MidnightTheme());
$app = new Application($symfonyApp);
$commandDiscovery = new CommandDiscovery($symfonyApp);
$commandExecutor = new CommandExecutor($symfonyApp);
$screen = new CommandsScreen($commandDiscovery, $commandExecutor);
$app->run($screen);
return Command::SUCCESS;
}
}
Then run: php bin/console app:ui
Commander comes with three built-in themes:
Classic blue theme with cyan highlights - just like the original Midnight Commander.
use Butschster\Commander\UI\Theme\MidnightTheme;
ColorScheme::applyTheme(new MidnightTheme());
Modern dark theme with black background and green/cyan accents.
use Butschster\Commander\UI\Theme\DarkTheme;
ColorScheme::applyTheme(new DarkTheme());
Light theme with white background - perfect for well-lit environments.
use Butschster\Commander\UI\Theme\LightTheme;
ColorScheme::applyTheme(new LightTheme());
π‘ Tip: Call ColorScheme::applyTheme()
before creating your Application instance.
Commander includes several ready-to-use screens that you can integrate into your application:
Browse and execute all registered Symfony Console commands.
use Butschster\Commander\Feature\CommandBrowser\Screen\CommandsScreen;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandDiscovery;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandExecutor;
$commandDiscovery = new CommandDiscovery($symfonyApp);
$commandExecutor = new CommandExecutor($symfonyApp);
$screen = new CommandsScreen($commandDiscovery, $commandExecutor);
Features:
- β Lists all available Symfony commands
- π Search/filter commands by name or namespace
- π Shows command descriptions and arguments
- β‘ Execute commands directly from UI
- π Displays command output in real-time
Keyboard Shortcuts:
ββ
- Navigate commandsEnter
- Execute selected commandCtrl+R
- Refresh command list/
- Search commandsEscape
- Cancel/go back
Navigate and browse the filesystem with a two-panel layout.
use Butschster\Commander\Feature\FileBrowser\Screen\FileBrowserScreen;
use Butschster\Commander\Feature\FileBrowser\Service\FileSystemService;
$fileSystem = new FileSystemService();
$screen = new FileBrowserScreen(
$fileSystem,
$screenManager,
'/path/to/start/directory'
);
Features:
- π Two-panel layout (list + preview)
- π File/directory navigation
- ποΈ File preview with syntax highlighting
- π Shows file sizes and modification times
- π Sort by name, size, or date
Keyboard Shortcuts:
ββ
- Navigate filesEnter
- Open directory / view fileBackspace
- Go to parent directoryTab
- Switch between panelsF5
- Copy fileF6
- Move fileF8
- Delete file
Manage Composer packages with tabbed interface.
use Butschster\Commander\Feature\ComposerManager\Screen\ComposerManagerScreen;
use Butschster\Commander\Feature\ComposerManager\Service\ComposerService;
$composerService = new ComposerService('/path/to/project');
$screen = new ComposerManagerScreen($composerService);
$screen->setScreenManager($screenManager);
Features:
- π¦ View installed packages
- π Check for outdated packages
- π Security audit
- β¬οΈ Update packages
- β Install new packages
- β Remove packages
Tabs:
- Installed - All installed packages with version info
- Outdated - Packages that have newer versions available
- Security - Packages with known security vulnerabilities
Keyboard Shortcuts:
Ctrl+β/β
- Switch between tabsββ
- Navigate packagesEnter
- View package detailsU
- Update selected packageD
- Remove selected packageTab
- Switch between list and details panel
All screens support customization of keyboard shortcuts and behavior:
$app = new Application($symfonyApp);
$screenManager = $app->getScreenManager();
// F2: Switch to Command Browser
$app->registerGlobalShortcut('F2', function ($sm) use ($commandDiscovery, $commandExecutor) {
$screen = new CommandsScreen($commandDiscovery, $commandExecutor);
$sm->pushScreen($screen);
});
// F3: Switch to File Browser
$app->registerGlobalShortcut('F3', function ($sm) use ($fileSystem) {
$screen = new FileBrowserScreen($fileSystem, $sm, getcwd());
$sm->pushScreen($screen);
});
// F5: Switch to Composer Manager
$app->registerGlobalShortcut('F5', function ($sm) use ($composerService) {
$screen = new ComposerManagerScreen($composerService);
$screen->setScreenManager($sm);
$sm->pushScreen($screen);
});
// F10: Quit
$app->registerGlobalShortcut('F10', function () use ($app) {
$app->stop();
});
$globalMenu = new MenuBar([
'F1' => ' Help',
'F2' => ' Commands',
'F3' => ' Files',
'F5' => ' Composer',
'F9' => ' Settings',
'F10' => ' Quit',
]);
$app->setGlobalMenuBar($globalMenu);
// Start with command browser
$welcomeScreen = new CommandsScreen($commandDiscovery, $commandExecutor);
// User can navigate to other screens via shortcuts
$app->registerGlobalShortcut('F3', function ($sm) {
// Pop all screens and push file browser
$sm->popUntil(fn($screen) => $screen instanceof FileBrowserScreen);
if (!($sm->getCurrentScreen() instanceof FileBrowserScreen)) {
$screen = new FileBrowserScreen($fileSystem, $sm, getcwd());
$sm->pushScreen($screen);
}
});
$app->run($welcomeScreen);
Want to create your own screen? Check out these guides:
- π Creating Custom Screens
- π¨ Component System
- β¨οΈ Keyboard Handling
- π Styling with Themes
Quick Example:
use Butschster\Commander\UI\Screen\ScreenInterface;
use Butschster\Commander\Infrastructure\Terminal\Renderer;
final class MyCustomScreen implements ScreenInterface
{
public function render(Renderer $renderer): void
{
$size = $renderer->getSize();
// Render your content...
}
public function handleInput(string $key): bool
{
// Handle keyboard input...
return true;
}
public function getTitle(): string
{
return 'My Custom Screen';
}
// ... implement other required methods
}
Commander provides rich set of UI components:
ListComponent
- Scrollable list with selectionTableComponent
- Multi-column table with sortingTextDisplay
- Scrollable text viewer with word wrap
FormComponent
- Form container with validationTextField
- Text input fieldCheckboxField
- Checkbox/toggleArrayField
- Comma-separated array input
Panel
- Container with border and titleModal
- Overlay dialog (info/error/warning/confirm)MenuBar
- Top menu barStatusBar
- Bottom status bar with shortcutsTabContainer
- Tabbed interfaceGridLayout
- Column-based layout
Here's a complete example showing all features together (see the included console
file):
#!/usr/bin/env php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use Butschster\Commander\Application;
use Butschster\Commander\Feature\CommandBrowser\Screen\CommandsScreen;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandDiscovery;
use Butschster\Commander\Feature\CommandBrowser\Service\CommandExecutor;
use Butschster\Commander\Feature\ComposerManager\Screen\ComposerManagerScreen;
use Butschster\Commander\Feature\ComposerManager\Service\ComposerService;
use Butschster\Commander\Feature\FileBrowser\Screen\FileBrowserScreen;
use Butschster\Commander\Feature\FileBrowser\Service\FileSystemService;
use Butschster\Commander\UI\Component\Layout\MenuBar;
use Butschster\Commander\UI\Theme\ColorScheme;
use Butschster\Commander\UI\Theme\MidnightTheme;
use Symfony\Component\Console\Application as SymfonyApplication;
// Create Symfony Console Application
$symfonyApp = new SymfonyApplication('My Console Application', '1.0.0');
// Apply theme
ColorScheme::applyTheme(new MidnightTheme());
// Create and configure Commander application
$app = new Application($symfonyApp);
$app->setTargetFps(30);
$screenManager = $app->getScreenManager();
// Create services
$commandDiscovery = new CommandDiscovery($symfonyApp);
$commandExecutor = new CommandExecutor($symfonyApp);
$fileSystem = new FileSystemService();
// Setup global menu bar
$globalMenu = new MenuBar([
'F1' => ' Help',
'F2' => ' Commands',
'F3' => ' Files',
'F5' => ' Composer',
'F10' => ' Quit',
]);
$app->setGlobalMenuBar($globalMenu);
// Register global shortcuts for screen switching
$app->registerGlobalShortcut('F2', function ($sm) use ($commandDiscovery, $commandExecutor) {
// Switch to command browser
$sm->popUntil(fn($screen) => $screen instanceof CommandsScreen);
if (!($sm->getCurrentScreen() instanceof CommandsScreen)) {
$sm->pushScreen(new CommandsScreen($commandDiscovery, $commandExecutor));
}
});
$app->registerGlobalShortcut('F3', function ($sm) use ($fileSystem) {
// Switch to file browser
$sm->popUntil(fn($screen) => $screen instanceof FileBrowserScreen);
if (!($sm->getCurrentScreen() instanceof FileBrowserScreen)) {
$sm->pushScreen(new FileBrowserScreen($fileSystem, $sm, getcwd()));
}
});
$app->registerGlobalShortcut('F5', function ($sm) {
// Switch to composer manager
$sm->popUntil(fn($screen) => $screen instanceof ComposerManagerScreen);
if (!($sm->getCurrentScreen() instanceof ComposerManagerScreen)) {
$composerService = new ComposerService(getcwd());
$screen = new ComposerManagerScreen($composerService);
$screen->setScreenManager($sm);
$sm->pushScreen($screen);
}
});
$app->registerGlobalShortcut('F10', function () use ($app) {
$app->stop();
});
// Start with command browser screen
$welcomeScreen = new CommandsScreen($commandDiscovery, $commandExecutor);
$app->run($welcomeScreen);
This example demonstrates:
- β All three built-in screens (Commands, Files, Composer)
- β Global menu bar with function key shortcuts
- β Screen switching via F2, F3, F5
- β Proper screen stack management
- β Service initialization
- β Theme application
src/
βββ Application.php # Main application entry point
βββ Feature/ # Feature modules
β βββ CommandBrowser/ # Command browser feature
β βββ FileBrowser/ # File browser feature
β βββ ComposerManager/ # Composer manager feature
βββ Infrastructure/ # Core infrastructure
β βββ Terminal/
β βββ KeyboardHandler.php # Keyboard input processing
β βββ Renderer.php # Double-buffered rendering
β βββ TerminalManager.php # Terminal control
βββ UI/ # UI framework
βββ Component/ # Reusable components
βββ Screen/ # Screen management
βββ Theme/ # Color themes
- Screens - Full-screen views (like pages in a web app)
- Components - Reusable UI elements (tables, forms, panels)
- Double Buffering - Prevents flickering by rendering off-screen first
- Event System - Components communicate via callbacks
- Theme System - Customizable color schemes
Commander is perfect for:
- DevOps Tools - Server management, deployment dashboards
- CLI Dashboards - System monitoring, log viewers
- Development Tools - Code generators, project scaffolders
- Admin Panels - Database managers, configuration editors
- Interactive Wizards - Multi-step installation processes
- File Managers - Custom file browsers with preview
- Package Managers - Dependency management UIs
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License. See LICENSE file for details.
Inspired by Midnight Commander - the legendary file manager.