PHPackages                             drevops/tui - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. drevops/tui

ActiveLibrary

drevops/tui
===========

Provides terminal UI form-building functionality.

0.1.1(yesterday)05↑2900%GPL-2.0-or-laterPHP &gt;=8.3

Since Jul 22Compare

[ Source](https://github.com/drevops/tui)[ Packagist](https://packagist.org/packages/drevops/tui)[ Docs](https://phptui.dev/)[ RSS](/packages/drevops-tui/feed)WikiDiscussions Synced today

READMEChangelog (2)Dependencies (11)Versions (3)Used By (0)

 [![TUI logo](logo.svg)](logo.svg)

Terminal user interfaces for PHP
================================

[](#terminal-user-interfaces-for-php)

[![GitHub Issues](https://camo.githubusercontent.com/f8ae82f738cb5e62f03616258537fb91e598596d9d38b51c69bf60bd3e35d377/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f647265766f70732f7475692e737667)](https://github.com/drevops/tui/issues)[![GitHub Pull Requests](https://camo.githubusercontent.com/943859846e6f0ab5d6c81eb18e3db92eea72cb38e6a32f938f6ff64339ad390a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d70722f647265766f70732f7475692e737667)](https://github.com/drevops/tui/pulls)[![Test PHP](https://github.com/drevops/tui/actions/workflows/test-php.yml/badge.svg)](https://github.com/drevops/tui/actions/workflows/test-php.yml)[![codecov](https://camo.githubusercontent.com/6c7e8f3e0faf8bf10b5694866988e4aa09dc54500fd44a6f114cc373d8ed2445/68747470733a2f2f636f6465636f762e696f2f67682f647265766f70732f7475692f67726170682f62616467652e7376673f746f6b656e3d37574542314958425954)](https://codecov.io/gh/drevops/tui)[![GitHub release (latest by date)](https://camo.githubusercontent.com/edfc9e731e6794a76c6130d19d3104d555b0cc7323aa78cbd408692664931b5f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f647265766f70732f747569)](https://camo.githubusercontent.com/edfc9e731e6794a76c6130d19d3104d555b0cc7323aa78cbd408692664931b5f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f647265766f70732f747569)[![LICENSE](https://camo.githubusercontent.com/c7eebf69fc587b228405c1322bb97c3e625bb7e5cab6f670e86e83ab737b1d98/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f647265766f70732f747569)](https://camo.githubusercontent.com/c7eebf69fc587b228405c1322bb97c3e625bb7e5cab6f670e86e83ab737b1d98/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f647265766f70732f747569)[![Renovate](https://camo.githubusercontent.com/35389190ce58a3690fe850342c1c3fd4f54e4c10ba8996741c8558ee24bf50dc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f72656e6f766174652d656e61626c65642d677265656e3f6c6f676f3d72656e6f76617465626f74)](https://camo.githubusercontent.com/35389190ce58a3690fe850342c1c3fd4f54e4c10ba8996741c8558ee24bf50dc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f72656e6f766174652d656e61626c65642d677265656e3f6c6f676f3d72656e6f76617465626f74)

---

   ![Terminal form with a rounded border](docs/assets/bordered-panels-light-animated.svg)

`drevops/tui` is a PHP engine for panel-based terminal forms: keyboard-driven questionnaires that collect a set of answers and hand them back to your code as typed values.

- **Declarative form model.** A form is declared with a fluent builder (`Form` / `PanelBuilder` / `FieldBuilder`): panels of typed fields, each field a widget with its own options, conditions, derivation rules and behavior.
- **Two collection modes, one declaration.** The same form runs as a full-screen interactive TUI on a terminal, or resolves non-interactively from a JSON payload, per-field environment variables, discovery rules and defaults.
- **Application-agnostic.** The engine doesn't know (or care) what application it serves; questions and handlers live in your code, and applying the collected answers is your job. It collects; you apply.
- **Dependency-light.** The runtime dependency surface is a single string-transform package.

The padded rounded border above is the default look. The same form explicitly opted out of the frame (`border` `none`, `normal` spacing):

   ![Terminal form without a border](docs/assets/borderless-panels-light-animated.svg)

📖 Documentation
---------------

[](#-documentation)

Full documentation lives at **[phptui.dev](https://phptui.dev)**. The in-development build, rebuilt from `main` ahead of each release, is previewed at **[tui-docs.netlify.app](https://tui-docs.netlify.app/)**.

Features
--------

[](#features)

Every feature has a reference page and a runnable, self-contained example in [`playground/`](playground):

FeatureSummaryDocsExample🧭 Full-screen TUIScrollable panel browser: hubs drill into sub-panels to any depth, contextual key-hint footer, ? help overlay[panels](https://phptui.dev/panels)[`03-panels-*`](playground)🪟 Modal panelsA panel marked `->modal()` opens as a centered dialog over its dimmed parent, with its own submit/cancel buttons[panels](https://phptui.dev/panels#modal-panels)[`03-panels-*`](playground)🧱 Panel layouts`->layout(1, 2)` arranges panels as a grid of side-by-side preview columns - rows of any width, recursively per level, with spatial arrow navigation[panels](https://phptui.dev/panels#panel-layouts)[`03-panels-*`](playground)🖥️ Fullscreen mode`->fullscreen()` stretches the frame to the whole terminal; `halign`/`valign` anchor the content and min/max size options guard small or very wide terminals[panels](https://phptui.dev/panels#fullscreen)[`03-panels-*`](playground)⚡ Inline editingA field's editor opens in place on the panel row; `->standalone()` opts a field out to full-screen[panels](https://phptui.dev/panels#inline-editing)[`04-inline-editing`](playground/04-inline-editing.php)🧩 Widgets13 field types: text, number, calendar, textarea, password, select, reorder, suggest, search, file picker, confirm, toggle, pause[widgets](https://phptui.dev/widgets)[`02-widgets-*`](playground)🏗️ Builder-drivenThe form is declared in PHP with a fluent builder; the common cases need no code[configuration](https://phptui.dev/configuration)[`01-quickstart`](playground/01-quickstart.php)🎛️ Interactive or unattended`run()` picks the mode: keyboard on a terminal, otherwise JSON payload + `TUI_` environment variables[headless collection](https://phptui.dev/headless-collection)[`08-headless-*`](playground)🔗 Derived valuesFields computed from other answers via `{{field}}` templates and str2name transforms, settling to a fixpoint[configuration](https://phptui.dev/configuration#derived-values)[`05-form-logic-*`](playground)🔀 Conditional fields`->when()` conditions (eq/ne/in/contains, composable with all/any/not) drive visibility; form-level fix-ups reconcile answers[configuration](https://phptui.dev/configuration#conditional-fields)[`05-form-logic-*`](playground)⚙️ Declared behaviorDynamic defaults, validation and transforms as field closures, or as per-field handler classes resolved by naming convention[field behavior](https://phptui.dev/field-behaviour)[`06-field-behaviour-*`](playground)🔍 DiscoveryUpdate mode detects defaults from an existing directory: dotenv keys, JSON dot-paths, path checks, directory scans[discovery](https://phptui.dev/field-behaviour#discovery)[`07-discovery`](playground/07-discovery.php)📦 Self-describing answersAnswers carry provenance; `toSummary()` renders a badged, panel-grouped report and `toJson()` the machine result; `schema()`, `validate()` and `agentHelp()` describe the form itself[self-describing answers](https://phptui.dev/headless-collection#self-describing-answers)[`08-headless-*`](playground)🎨 ThemesSix built-ins selected by name; a custom theme is a `DefaultTheme` subclass overriding palette atoms and render methods[themes](https://phptui.dev/themes)[`09-themes-*`](playground)⌨️ Key bindingsPresets (`default`, `vim`, or a class) plus per-binding overrides scoped to navigation or a widget type; conflicts throw at setup[key bindings](https://phptui.dev/key-bindings)[`10-key-bindings-*`](playground)✨ Display modesDark/light follows the terminal background, glyphs follow the locale, color honors `NO_COLOR`; all three can be forced[display modes](https://phptui.dev/display-modes)[`11-display-modes-*`](playground)🧪 Test harness`TuiTester` drives the real panel loop from scripted keystrokes, no TTY; assert on answers, output and rendered frames[testing](https://phptui.dev/testing)[`13-testing`](playground/13-testing.php)🌍 TranslationsBundled chrome catalogs load automatically; a directory, a single catalog file or an inline map layers your own strings and chrome overrides on top, falling back to English[translations](https://phptui.dev/translations)[`12-translations`](playground/12-translations.php)Installation
------------

[](#installation)

```
composer require drevops/tui
```

Quick start
-----------

[](#quick-start)

Declare a form with the `Form` builder, then drive it through the `Tui` facade - the one class that wires up the engine, resolver, schema tools and TUI for you:

```
use DrevOps\Tui\Builder\Form;
use DrevOps\Tui\Builder\PanelBuilder;
use DrevOps\Tui\Tui;

$form = Form::create('Quick start')
  ->panel('order', 'New order', function (PanelBuilder $p): void {
    // A required single-line text field.
    $p->text('name', 'Order name')->required();

    // A single choice, starting on "Banana".
    $p->select('fruit', 'Fruit')->default('banana')->options([
      'apple' => 'Apple',
      'banana' => 'Banana',
      'cherry' => 'Cherry',
    ]);

    // A multi-select, with one option pre-checked.
    $p->select('veg', 'Vegetables')->multiple()->default(['carrot'])->options([
      'carrot' => 'Carrot',
      'tomato' => 'Tomato',
      'spinach' => 'Spinach',
    ]);

    // An integer bounded to a sensible quantity.
    $p->number('quantity', 'Quantity')->min(1)->max(99)->default(6);

    // A yes/no gate.
    $p->confirm('organic', 'Organic only?')->default(FALSE);
  });

$tui = new Tui($form, handler_namespaces: ['App\\Handler']);

$answers = $tui->run();
```

The facade's surface:

CallPurpose`run($prompts, $version, $directory, $interactive)`Collect answers; interactive on a TTY, headless otherwise (or forced via `$interactive`)`collect($prompts, $directory, $update, $version)`Headless collection from JSON + environment; `$update` enables discovery`interact()`The interactive panel TUI, explicitly`schema()` / `validate($answers)` / `agentHelp()`Describe the questions as structured metadata, validate an answer payload, emit the agent-facing answer schema`theme($theme, $options)` / `keys($preset, $overrides)`Select the theme and key bindings`color($bool)` / `unicode($bool)` / `fullscreen($bool)` / `footer($bool)` / `clearOnExit($bool)` / `translator($t)`Display and runtime switches`form()` / `engine()` / `registry()`The internals, for finer controlRead the [full guide at phptui.dev](https://phptui.dev), and browse [`playground/`](playground) for complete, runnable examples - the numbered scripts for each feature in the table above.

Widgets
-------

[](#widgets)

There's a widget for most things you'd want to ask: text entry, numbers and dates, single and multiple choice, fuzzy search, filesystem browsing, and simple gates. Each one links to its full reference on [phptui.dev](https://phptui.dev/widgets), and every card below plays back the real interaction in whichever color scheme - light or dark - your reader is using.

![Calendar widget](docs/assets/widget-calendar-light-animated.svg)**[Calendar](https://phptui.dev/widgets/calendar)**
A month calendar returning a normalized ISO `YYYY-MM-DD`; arrows move by day and week.![Confirm widget](docs/assets/widget-confirm-light-animated.svg)**[Confirm](https://phptui.dev/widgets/confirm)**
Yes/No toggle; arrows or Space switch, y/n set the choice directly, Enter accepts.![File picker widget](docs/assets/widget-filepicker-light-animated.svg)**[File picker](https://phptui.dev/widgets/filepicker)**
Browse the filesystem for a path; arrows move, → enters a directory and ← returns to its parent. Add `->multiple()` for several paths.![Number widget](docs/assets/widget-number-light-animated.svg)**[Number](https://phptui.dev/widgets/number)**
Integer entry (digits with an optional leading minus) accepted as an `int`, with optional min, max and step.![Password widget](docs/assets/widget-password-light-animated.svg)**[Password](https://phptui.dev/widgets/password)**
Text rendered as a mask in the editor, the field row and the summary; the accepted value stays plain for your code, and can be made revealable.![Pause widget](docs/assets/widget-pause-light-animated.svg)**[Pause](https://phptui.dev/widgets/pause)**
An acknowledgment gate; Enter or Space accepts. Unattended runs auto-acknowledge it, so it never blocks automation.![Reorder widget](docs/assets/widget-reorder-light-animated.svg)**[Reorder](https://phptui.dev/widgets/reorder)**
Rank a list by moving items into the order you want; Space picks an item up, arrows carry it through the list, Enter accepts.![Search widget](docs/assets/widget-search-light-animated.svg)**[Search](https://phptui.dev/widgets/search)**
Single choice with a visible filter line; typing fuzzy-matches and ranks the labels, exact and prefix matches leading.![Select widget](docs/assets/widget-select-light-animated.svg)**[Select](https://phptui.dev/widgets/select)**
Single choice from a list; arrows move, Enter accepts the highlighted option, long lists page around the cursor.![Suggest widget](docs/assets/widget-suggest-light-animated.svg)**[Suggest](https://phptui.dev/widgets/suggest)**
Free text with autocomplete over a fixed option set: as you type, suggestions are fuzzy-matched and ranked by relevance.![Text widget](docs/assets/widget-text-light-animated.svg)**[Text](https://phptui.dev/widgets/text)**
Single-line input with a movable caret; type to insert, arrows move, Backspace deletes, Enter accepts.![Textarea widget](docs/assets/widget-textarea-light-animated.svg)**[Textarea](https://phptui.dev/widgets/textarea)**
Multi-line input; Enter inserts a newline, arrows move between lines, Tab accepts, with an external-editor handoff.![Toggle widget](docs/assets/widget-toggle-light-animated.svg)**[Toggle](https://phptui.dev/widgets/toggle)**
An inline switch between two labeled values; arrows or Space flip, the first letter of each label sets it directly.Themes
------

[](#themes)

Six themes ship built-in, selected by name on the `Tui` facade. Dark or light is a separate `mode` display option auto-detected from the terminal background, so every adaptive theme serves both:

```
$tui = (new Tui($form))->theme('midnight');
```

NamePalette`default`Cyan accents on an auto-detected dark or light base - the out-of-the-box look.`midnight`Violet accents, green values, pink highlights.`frost`Arctic frost-blue accents, sage values, sand highlights.`ember`Burnt-orange accents, olive values, gold highlights.`mono`Hue-free - bold weight, gray levels and reverse video for maximum compatibility.`dos`Retro MS-DOS: the bright white/cyan/yellow CGA palette in a double-line window, made for a blue terminal background.Each renders across every widget and degrades to plain text without ANSI. Here the dark palette (left) and the light palette (right); the [themes docs](https://phptui.dev/themes) also show every theme inside the rounded border frame:

**`midnight`**

 [![midnight theme, dark mode](docs/assets/theme-midnight-dark-static.svg)](docs/assets/theme-midnight-dark-static.svg) [![midnight theme, light mode](docs/assets/theme-midnight-light-static.svg)](docs/assets/theme-midnight-light-static.svg)

**`frost`**

 [![frost theme, dark mode](docs/assets/theme-frost-dark-static.svg)](docs/assets/theme-frost-dark-static.svg) [![frost theme, light mode](docs/assets/theme-frost-light-static.svg)](docs/assets/theme-frost-light-static.svg)

**`ember`**

 [![ember theme, dark mode](docs/assets/theme-ember-dark-static.svg)](docs/assets/theme-ember-dark-static.svg) [![ember theme, light mode](docs/assets/theme-ember-light-static.svg)](docs/assets/theme-ember-light-static.svg)

**`mono`**

 [![mono theme, dark mode](docs/assets/theme-mono-dark-static.svg)](docs/assets/theme-mono-dark-static.svg) [![mono theme, light mode](docs/assets/theme-mono-light-static.svg)](docs/assets/theme-mono-light-static.svg)

**`dos`** - the CGA blue screen, painted regardless of the terminal background

 [![dos theme, dark terminal](docs/assets/theme-dos-dark-static.svg)](docs/assets/theme-dos-dark-static.svg) [![dos theme, light terminal](docs/assets/theme-dos-light-static.svg)](docs/assets/theme-dos-light-static.svg)

Write your own by subclassing `DefaultTheme` and overriding just its palette - see the [theming guide](https://phptui.dev/themes) and the playground's [`OceanTheme`](playground/themes/OceanTheme.php).

Contributing
------------

[](#contributing)

See the [Contributing guide](https://tui-docs.netlify.app/contributing) for the development workflow, quality gates and how the documentation and SVG assets are built.

---

*This repository was created using the [Scaffold](https://getscaffold.dev/) project template*

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance100

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

1d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/b57b0fd0b96f77f2efa1a1889af0ae607fa139bcc1256e809ee3ebbb30907364?d=identicon)[alexdrevops](/maintainers/alexdrevops)

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Type Coverage Yes

### Embed Badge

![Health badge](/badges/drevops-tui/health.svg)

```
[![Health](https://phpackages.com/badges/drevops-tui/health.svg)](https://phpackages.com/packages/drevops-tui)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
