pdphilip/omniterm
OmniTerm is a Laravel terminal UI toolkit that renders HTML + Tailwind-style classes into ANSI output. Includes truecolor with fallback, gradients, arbitrary RGB classes, and content-repeat fills, plus ready-made components like status messages, tables, progress bars, spinners, tasks, and a split-pa...
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require pdphilip/omniterm
use OmniTerm\HasOmniTerm;
class MyCommand extends Command {
use HasOmniTerm;
}
public function handle() {
$this->omni->success('Task completed'); // Green status badge
}
php artisan omniterm:full-demo to see all features in action.// Simple status
$this->omni->success('Migration complete');
// Detailed status block
$this->omni->statusSuccess(
'Migration Complete',
'All 42 records processed',
['Run cache:clear']
);
// Simple progress bar
$bar = $this->omni->progressBar(100)->steps();
$bar->start();
// Update progress
foreach ($items as $item) {
$bar->advance();
}
$bar->finish();
$task = $this->omni->liveTask('Processing records', spinner: Spinner::Dots3)
->row('Created', 0, 'text-sky-500')
->row('Failed', 0, 'text-rose-500');
for ($i = 0; $i < 5; $i++) {
$result = $task->run(function () {
return ['created' => rand(1, 10), 'failed' => rand(0, 2)];
});
$task->increment('Created', $result['created']);
$task->increment('Failed', $result['failed']);
}
$task->finish('Done');
$selected = $this->omni->browse('Servers', [
'web-01' => function ($omni) {
$omni->statusSuccess('Healthy', 'All checks passing');
},
'db-01' => ['status' => 'running', 'cpu' => '45%'],
]);
$this->omni->render(<<<HTML
<div class="flex">
<span class="bg-emerald-600 text-white px-2">PASS</span>
<span class="text-zinc-400 flex-1">Database connection verified</span>
</div>
HTML
);
Store reusable UI in resources/views/cli/:
// resources/views/cli/status.blade.php
<div class="flex">
<span class="bg-{{ $color }}-600 text-white px-2">{{ $badge }}</span>
<span class="text-zinc-400 flex-1">{{ $message }}</span>
</div>
// In command
$this->omni->view('cli.status', [
'badge' => 'OK',
'color' => 'emerald',
'message' => 'System ready',
]);
Use runTask() for background processing:
$result = $this->omni->runTask('Processing...', function () {
return ['data' => 'processed'];
}, Spinner::Sand);
$width = $this->omni->terminal()->getWidth();
if ($width < 80) {
$this->omni->render('<div class="text-sm">Narrow terminal detected</div>');
}
Color Fallback:
text-{color}-{shade} (e.g., text-sky-500) instead of arbitrary RGB (text-[0,191,255]) for broader compatibility.Live Views:
$this->omni->endLiveView() can leave stale output.finally block or wrap in a try-catch:
try {
$live = $this->omni->liveView('...');
// ... updates
} finally {
$this->omni->endLiveView();
}
Progress Bar Stuck:
$bar->finish() is omitted, the bar remains indeterminate.finish() or stop():
$bar->stop(); // For manual control
Spinner Not Showing:
Spinner::Dots (ASCII-only).Blade Caching:
php artisan view:clear
Check ANSI Output:
parse() to inspect raw ANSI without printing:
$ansi = $this->omni->parse('<span class="text-red-500">Test</span>');
$this->line($ansi); // Log to terminal
Terminal Detection:
$this->omni->terminal()->force256Colors();
Gradient Issues:
via-{color} steps or switch to bg-{color}-{shade}.Custom Spinners:
Spinner enum or create a new animation class by implementing OmniTerm\Contracts\Spinner.New Components:
render() and Blade templates.Card component:
$this->omni->render(<<<HTML
<div class="border border-zinc-600 rounded-lg p-2">
<div class="font-bold">{{ $title }}</div>
<div>{!! $content !!}</div>
</div>
HTML
);
Dynamic Styling:
$status = 'error';
$this->omni->render("<span class='text-$status-500'>$status</span>");
Event Listeners:
OmniTerm class and overriding methods like compile().Configuration:
php artisan vendor:publish --provider="OmniTerm\OmniTermServiceProvider"
config/omniterm.php (e.g., set default_spinner to Spinner::Clock).Batch Rendering:
render() calls into one for complex UIs:
$this->omni->render(<<<HTML
<div>{$this->omni->statusSuccess('Ready')}</div>
<div>{$this->omni->tableHeader('Metrics')}</div>
HTML
);
Avoid Live Views for Simple Updates:
render() + \r (carriage return) for lightweight updates:
for ($i = 0; $i <= 100; $i++) {
$this->output->write("\rProgress: {$i}%");
usleep(50000);
}
$this->output->writeln();
Reuse Parsed ANSI:
$header = $this->omni->parse('<div class="font-bold">Header</div>');
$this->line($header);
| Terminal | Known Issue | Workaround |
|---|---|---|
| macOS Terminal | Limited truecolor support | Use text-{color}-{shade} |
| Windows CMD | No Unicode support | Use Spinner::Dots (ASCII) |
| WezTerm | May ignore some ANSI sequences | Test with this->omni->parse() |
| Alacritty | Gradients may render unevenly | Reduce via-{color} steps |
$this->omni->render(<<<HTML
How can I help you explore Laravel packages today?