A dependency-light PHP engine for building terminal user interfaces: interactive, keyboard-driven forms that collect answers and hand them to your code. Describe the questions in PHP with a fluent builder, add a handler class wherever a question needs real behaviour, and the engine renders a scrollable, themeable TUI - or collects the answers non-interactively from a JSON payload.
The engine knows nothing about the application it serves: it stays generic, the application-specific questions and handlers live in the consumer, and applying the collected answers is the consumer's job, not the TUI's.
The border is optional - here is the same form without one, at normal spacing:
Full documentation - every widget, configuration, theming, key bindings and the engine architecture - lives at phptui.dev.
- 🧭 Full-screen TUI - a scrollable, keyboard-driven form with a contextual key-hint footer and a
?help overlay - 🧩 Widgets - field types for text, numbers, dates, choices, file browsing, fuzzy search and gates
- 🏗️ Builder-driven - the form is declared in PHP with a fluent builder
- 🎛️ Interactive or unattended - answer the form by keyboard, or supply the answers up front as a JSON payload and environment variables so it runs without prompting
- 🔗 Derived values and 🔀 conditional fields that settle to a fixpoint
- 🔍 Discovery, ⚙️ declared behaviour and 📦 self-describing answers
- 🎨 Themes, ⌨️ key bindings and ✨ Unicode and ASCII display modes
- 🧪 Test harness - drive a form from scripted keystrokes and assert on the answers and rendered output
- 🌍 Translations - present chrome and questions in another language, falling back to English
composer require drevops/tuiDeclare a form with the fluent Form builder, then drive it with the Tui facade - one class that wires 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('My form')
->panel('general', 'General', fn(PanelBuilder $p) => $p->text('name', 'Your name')->required());
$tui = new Tui($form, ['App\\Handler']);
// Interactive on a terminal, non-interactive otherwise.
$answers = $tui->run();
// Or call a mode directly:
echo $tui->collect('{"name":"Ada"}')->toJson(); // non-interactive: JSON + environment
$answers = $tui->interact(); // interactive TUIRead the full guide at phptui.dev and browse playground/ for complete, runnable examples.
The widgets cover text entry, choices, filesystem browsing and gates. Each links to its full reference on phptui.dev. Every image below follows your colour scheme - light or dark.
| Calendar A month calendar returning a normalized ISO YYYY-MM-DD; arrows move by day and week. |
|
| Confirm Yes/No toggle; arrows or Space switch, y/n set the choice directly, Enter accepts. |
|
| File picker Browse the filesystem for a single path; arrows move, → enters a directory and ← returns to its parent. |
|
| Multi file picker Like the file picker, but several paths accumulate as you browse; Space toggles the highlighted entry. |
|
| MultiSearch A multi-select whose filter query shows as a search line; typing fuzzy-matches and ranks, Space toggles matches. |
|
| MultiSelect Multiple choice from a checkbox list; Space toggles, typing narrows the list, select-all and deselect-all in one key. |
|
| Number Integer entry (digits with an optional leading minus) accepted as an int, with optional min, max and step. |
|
| Password Text rendered as a mask in the editor, the field row and the summary; the accepted value stays plain for the consumer, and can be made revealable. |
|
| Pause An acknowledgement gate; Enter or Space accepts. Unattended runs auto-acknowledge it, so it never blocks automation. |
|
| 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 Single choice with a visible filter line; typing fuzzy-matches and ranks the labels, exact and prefix matches leading. |
|
| Select Single choice from a list; arrows move, Enter accepts the highlighted option, long lists page around the cursor. |
|
| Suggest Free text with autocomplete over a fixed option set: as you type, suggestions are fuzzy-matched and ranked by relevance. |
|
| Text Single-line input with a movable caret; type to insert, arrows move, Backspace deletes, Enter accepts. |
|
| Textarea Multi-line input; Enter inserts a newline, arrows move between lines, Tab accepts, with an external-editor handoff. |
|
| Toggle An inline switch between two labelled values; arrows or Space flip, the first letter of each label sets it directly. |
composer install
composer lint
composer testSee the Contributing guide for the full development workflow.
This repository was created using the Scaffold project template