pdphilip/omniterm

This is my package OmniTerm

Fund package maintenance!
PDPhilip

Installs: 29 069

Dependents: 4

Suggesters: 0

Security: 0

Stars: 1

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/pdphilip/omniterm

v2.0.1 2026-02-20 14:45 UTC

This package is auto-updated.

Last update: 2026-02-21 11:23:49 UTC


README

OmniTerm

Latest Version on Packagist GitHub Tests Action Status Total Downloads

Terminal UI toolkit for Laravel

Rich CLI output using HTML and Tailwind CSS classes, rendered as ANSI in your terminal.

Progress Bars

About

OmniTerm is a terminal rendering engine for Laravel. Write your CLI output as HTML with Tailwind CSS classes and OmniTerm compiles it to ANSI escape sequences.

The Tailwind-for-terminal concept was pioneered by Termwind. OmniTerm builds on that idea with its own rendering engine that adds:

  • 16 million color support - full RGB truecolor, with automatic 256-color fallback for older terminals
  • Gradients - bg-gradient-to-r, from-{color}, via-{color}, to-{color} for smooth per-character color transitions
  • Arbitrary RGB classes - text-[R,G,B] and bg-[R,G,B] for computed/dynamic colors
  • Content repeat - content-repeat-[char] to fill widths with box-drawing characters

On top of the rendering engine, OmniTerm ships with a set of pre-built components for common CLI patterns: status messages, data tables, progress bars, spinners, live tasks, and an interactive split-pane browser.

Requirements

  • PHP 8.2+
  • Laravel 10, 11, or 12

Installation

composer require pdphilip/omniterm

Built-in Components

Add the HasOmniTerm trait to any Artisan command:

use OmniTerm\HasOmniTerm;

class MyCommand extends Command
{
    use HasOmniTerm;

    public function handle()
    {
        $this->omni->success('Ready');
    }
}

Status Messages

One-line status badges:

$this->omni->success('Task completed');     // Green GOOD badge
$this->omni->error('Something went wrong'); // Red FAIL badge
$this->omni->warning('Check your config');  // Amber WARN badge
$this->omni->info('Processing...');         // Blue INFO badge
$this->omni->disabled('Feature off');       // Gray OFF badge

Detailed status blocks with title, message, and help lines:

$this->omni->statusSuccess('Migration Complete', 'All 42 records processed', ['Run cache:clear']);
$this->omni->statusError('Connection Failed', 'Could not reach database', ['Check .env', 'Ensure MySQL is running']);

Status Messages

Data Tables

Key-value rows with status indicators:

$this->omni->tableHeader('Setting', 'Value', 'Notes');
$this->omni->tableRow('Database', 'mysql', 'Production server');
$this->omni->tableRowSuccess('Connection', 'Active');
$this->omni->tableRowError('SSL Certificate', 'Expired');
$this->omni->tableRowWarning('Memory', '85% used');

Data Tables

Visual Elements

Title bars, boxes, and horizontal rules:

$this->omni->titleBar('My Application', 'sky');
$this->omni->roundedBox('Welcome', 'text-cyan-500', 'text-white');
$this->omni->hr();
$this->omni->hrSuccess();

Visual Elements

Progress Bars

Fluent builder API with three styles: simple, framed, and gradient. Color steps transition from rose through amber to emerald as progress increases.

$bar = $this->omni->progressBar(100)->framed()->steps();
$bar->start();

foreach ($items as $item) {
    // work...
    $bar->advance();
}

$bar->finish();

Other variants:

$this->omni->progressBar(50);                              // Simple bar (sky)
$this->omni->progressBar(50)->steps();                     // Simple with color steps
$this->omni->progressBar(50)->framed()->color('indigo');   // Framed with custom color
$this->omni->progressBar(50)->gradient();                  // Gradient (amber → emerald)
$this->omni->progressBar(50)->framed()->gradient('rose', 'sky'); // Custom gradient

Progress Bars

Live Tasks

Run a callback in a background process with an animated spinner:

use OmniTerm\Async\Spinner;

$this->omni->newLoader(Spinner::Sand);

$result = $this->omni->runTask('Processing data...', function () {
    sleep(3);
    return ['state' => 'success', 'message' => 'Done'];
});

One-liner with task():

$this->omni->task('Processing batch job', function () {
    sleep(3);
    return ['state' => 'success', 'message' => 'Batch complete', 'details' => '500 records'];
}, Spinner::DotsCircle, ['text-indigo-500', 'text-violet-500']);

For fine-grained control with live-updating counters:

$task = $this->omni->liveTask('Syncing records', Spinner::Dots);
$task->row('Processed', 0);
$task->row('Skipped', 0);

$result = $task->run(function () use ($task) {
    foreach ($records as $record) {
        $record->sync()
            ? $task->increment('Processed')
            : $task->increment('Skipped');
    }
    return ['state' => 'success', 'message' => 'Sync complete'];
});

$task->finish('All done');

The Spinner enum provides 10 animation types: Dots, Dots2, Dots3, DotsCircle, Sand, Clock, Material, Pong, Progress, ProgressLoader.

Interactive Browser

Split-pane TUI: scrollable list on the left, detail view on the right. Items can be closures (rendered with full omni output), associative arrays (auto-formatted), or plain arrays.

+-- Server Dashboard ---------------+-----------------------------------+
| > web-01                          |  ✓ GOOD  Healthy                  |
|   web-02                          |  All checks passing               |
|   db-primary                      |                                   |
|   cache-01                        |  Metric    Value                  |
+-----------------------------------+  CPU        23%                   |
                                    +-----------------------------------+
  ↑/↓ Navigate  Enter Select  q/Esc Exit
use OmniTerm\OmniTerm;

$selected = $this->omni->browse('Server Dashboard', [
    'web-01' => function (OmniTerm $omni) {
        $omni->statusSuccess('Healthy', 'All checks passing');
        $omni->tableHeader('Metric', 'Value');
        $omni->tableRowSuccess('CPU', '23%');
        $omni->tableRow('Memory', '4.2 GB / 8 GB');
    },
    'db-primary' => ['status' => 'running', 'cpu' => '45%', 'memory' => '28 GB / 32 GB'],
]);
// Returns selected key, or null on Esc

Interactive Prompts

$name = $this->omni->ask('What is your name?');
$color = $this->omni->ask('Choose a color:', ['red', 'green', 'blue']);

DIY - The Rendering Engine

The built-in components are just Blade templates compiled through OmniTerm's rendering engine. You can use the same engine directly to build anything.

render()

Write HTML with Tailwind classes, get ANSI output:

$this->omni->render('<div class="flex">
    <span class="bg-emerald-600 text-white font-bold px-1">PASS</span>
    <span class="flex-1 text-zinc-400 px-1">Database connection verified</span>
    <span class="text-zinc-600 text-right w-12">12ms</span>
</div>');

liveView()

Redraws in place, for live-updating displays:

$live = $this->omni->liveView('<div>Starting...</div>');

for ($i = 1; $i <= 100; $i++) {
    $live->reRender("<div>Progress: {$i}%</div>");
    usleep(50000);
}

$this->omni->endLiveView();

parse()

Convert HTML to an ANSI string without printing:

$ansi = $this->omni->parse('<span class="text-sky-500">Hello</span>');

terminal()

Terminal dimensions:

$width = $this->omni->terminal()->getWidth();
$height = $this->omni->terminal()->getHeight();

Supported Classes

Tailwind Classes

Layout

Class Effect
flex Horizontal layout
flex-1 Fill remaining space
w-{n} Fixed width in characters
space-x-{n} Gap between children

Spacing

Class Effect
px-{n}, pl-{n}, pr-{n} Horizontal padding
mx-{n}, ml-{n}, mr-{n} Horizontal margin
mt-{n}, mb-{n} Vertical margin (blank lines)

Typography

Class Effect
font-bold Bold
text-center Center-align
text-right Right-align

Colors

All Tailwind colors with shades 50-950: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose.

Class Effect
text-{color}-{shade} Text color, e.g. text-sky-500
bg-{color}-{shade} Background color, e.g. bg-red-600
text-[R,G,B] Arbitrary RGB text, e.g. text-[255,100,50]
bg-[R,G,B] Arbitrary RGB background

Gradients

Per-character color interpolation across an element's width.

Class Effect
bg-gradient-to-r Left-to-right gradient
bg-gradient-to-l Right-to-left gradient
from-{color}-{shade} Start color
via-{color}-{shade} Midpoint color
to-{color}-{shade} End color
$this->omni->render('<div class="flex">
    <span class="flex-1 bg-gradient-to-r from-indigo-800 via-purple-500 to-pink-400 text-white text-center">
        Smooth gradient
    </span>
</div>');

Content

Class Effect
content-repeat-[char] Repeat character to fill width

Color Mode Detection

OmniTerm auto-detects your terminal's color capability:

  • Truecolor (16M) - full RGB. iTerm2, Kitty, WezTerm, most modern terminals.
  • 256-color - automatic fallback for older terminals (e.g. Apple Terminal). Colors mapped to nearest match.

No configuration needed.

Using Blade Templates

Since OmniTerm is a Laravel package, you can write your CLI output as Blade views and render them through the engine. This is how all the built-in components work:

// resources/views/cli/deploy-status.blade.php
<div class="flex">
    <span class="bg-{{ $color }}-600 text-white font-bold px-1">{{ $badge }}</span>
    <span class="flex-1 text-zinc-400 px-1">{{ $message }}</span>
</div>

// In your command
$this->omni->view('cli.deploy-status', [
    'badge' => 'DEPLOY',
    'color' => 'emerald',
    'message' => 'Production updated',
]);

Samples

OmniTerm includes sample commands for every feature. Copy them into your app:

mkdir -p app/Console/Commands/OmniTermSamples
cp vendor/pdphilip/omniterm/samples/Commands/*.php app/Console/Commands/OmniTermSamples/

Update the namespace in each file to App\Console\Commands\OmniTermSamples, then:

php artisan omniterm:full-demo          # One of every feature
php artisan omniterm:status-messages    # Status messages
php artisan omniterm:data-tables        # Key-value tables
php artisan omniterm:visual-elements    # Boxes and horizontal rules
php artisan omniterm:title-bars         # Title bar colors
php artisan omniterm:progress-bars      # All progress bar styles
php artisan omniterm:spinners           # All 10 spinner animations
php artisan omniterm:async-tasks        # Async task execution
php artisan omniterm:live-task-demo     # LiveTask with feedback rows
php artisan omniterm:browser-demo       # Interactive split-pane browser
php artisan omniterm:tailwind-classes   # Every supported CSS class
php artisan omniterm:interactive        # Interactive prompts
php artisan omniterm:custom-colors      # Custom color schemes
php artisan omniterm:global-functions   # Render & live view functions

Testing

composer test        # Lint + PHPStan + Pest
composer test:unit   # Pest only
composer types       # PHPStan only
composer format      # Laravel Pint

License

MIT. See License File.