pdphilip/omniterm
OmniTerm is a terminal UI toolkit for Laravel that lets you write CLI output as HTML with Tailwind classes and renders it as ANSI. It supports truecolor with 256-color fallback, gradients, arbitrary RGB colors, plus ready-made status badges, tables, progress bars, spinners, and live tasks.
Architecture fit. OmniTerm is a self-contained Laravel presentation library consumed through a HasOmniTerm trait on Artisan commands. It is additive and optional — it renders CLI output only, does not touch application runtime, DI containers, HTTP stack, queues, or persistence. Coupling to Laravel is shallow (Blade view compilation plus Symfony Console), and the engine itself is a bespoke HTML→ANSI compiler with its own Tailwind-class subset. From an architecture standpoint, this is a low-blast-radius "developer experience / internal tooling" dependency, not an infrastructure or domain component. It should not be evaluated as core platform; it should be evaluated as a UX accelerator for commands your teams run.
Integration feasibility. Very high. composer require pdphilip/omniterm, add a trait to a command class, and you can render immediately; incremental adoption is trivial because each component (success(), tableRow(), progressBar()) is independently opt-in. Constraints to verify before committing: PHP 8.2+, Laravel 11/12/13, Symfony Console 7/8 — Laravel 10 is explicitly unsupported as of v3.0.0. If any production or long-lived branch is on Laravel 10 or Symfony 6, this is a hard blocker unless you stay on an older version or fork.
Technical risk. The direct technical risk in production is low (CLI output is non-critical), but the ecosystem risk is meaningful:
symfony/console primitives or Termwind. Gradients, arbitrary RGB, content-repeat, and the layout subset are custom; bugs here are yours to triage or upstream.runTask(), liveTask(), browse(), and ask() introduce process spawning, in-place redraw, and TTY detection. These are the highest-defect-density features and the least automatable in CI.Key questions to answer before adopting.
CI=true, and NO_COLOR environments, or will engineers see raw ANSI in build logs?liveView, or does it require a minimum width?Symfony\Console and Illuminate\Contracts version pinning so that minor Laravel releases do not break rendering?Stack fit. Strong fit if the target workloads are developer-facing Artisan commands (scaffolding, diagnostics, migrations, data sync) running on Laravel 11+. Poor fit for automated batch processes, queue workers, scheduled jobs, or anything whose output is ingested by machines — the value is human-readable terminal output, and that value evaporates as soon as stdout is piped or captured.
Migration path. Adopt in three increments:
success/error/warning/info, titleBar, tableHeader/tableRow, and a progressBar. Run in the team's actual terminals, CI, and log pipelines. This produces an evidence set for step 2.progressBar + render() over liveTask for anything that might run unattended.runTask/browse/ask behind guarded usage (checking $this->input->isInteractive() or equivalent) so they never run in CI.Compatibility. Lock the version. The v3 line targets Laravel 11/12/13 and Symfony 7/8; pin to a specific minor and add to your dependency-review cadence. Verify at install time:
symfony/console resolution.illuminate/contracts resolution (v3 pins ^11||^12||^13).blade or view customizations that could interfere with the package's compiled templates.Sequencing (TPM view).
composer test / PHPStan / Pest), and CI matrix.omniterm:full-demo) in a dev terminal, in a captured log, and on a CI runner.Maintenance. Low operational footprint: no services, no database, no config schema. Maintenance is essentially dependency hygiene. The primary exposure is upstream version churn — v3.0.0 already dropped Laravel 10 and Symfony 6, so expect another breaking matrix update when Laravel 14 / Symfony 9 arrive. Budget for periodic version bumps and rendering regressions, and keep a fork-and-patch fallback viable given the small contributor base.
Support. Community, best-effort. There is no vendor SLA, no commercial support tier, and no downstream dependents to triangulate against. For an internal-only CLI convenience layer, this is acceptable; do not adopt it in front of a customer-facing deliverable or a revenue-blocking workflow. Document owners internally and treat the package as owned-by-your-team-even-if-maintained-upstream.
Scaling. Horizontal scaling is a non-issue for pure rendering; CPU cost is per-invocation and small. Vertical concerns are minor. The real scaling concern is the async surface: runTask() spawns background work and liveTask() redraws at animation frequency; many concurrent long-running commands could contend for process slots, file descriptors, and terminal I/O. Keep those features out of any high-concurrency scheduler or worker path.
Failure modes to design against.
NO_COLOR, pipe to plain text) in your own wrapper.resources/views/vendor/ are a support surface to track.content-repeat depend on terminal width detection; narrow terminals or resized panes can produce garbled output. Test at 80 columns.Ramp-up. Low. Developers already know Blade and Tailwind, and the component API (success(), tableRow(), progressBar()->steps()->finish()) maps to familiar patterns. Expect a half-day onboarding for basic components, a day for the rendering engine (render, parse, liveView), and a day plus a review for the async/interactive surfaces — which is where new users will burn time on unfamiliar failure modes. Publish an internal snippet library (a handful of standard command templates) to standardize usage, and document the TTY/CI guardrails so no one accidentally ships a blocking prompt into an automated path.
How can I help you explore Laravel packages today?