TUI

The TUI (text user interface) is Lolly's interactive terminal shell - the whole app driven by the keyboard, inside your terminal. Where the CLI is a one-shot command for scripts and pipelines, the TUI is a full-screen, keyboard-first surface for browsing tools, filling in inputs, saving projects, editing your profile and exporting - without leaving the terminal or opening a browser.

It runs the same engine and the same render path as the web shell and the CLI, so its output can never drift from the GUI.

lolly tui        # from the installed CLI (npm i -g @lolly-tools/cli)
npm run tui      # from a checkout

lolly tui and lolly-tui start the same thing: the CLI hands the terminal straight to it, so one install gives you both doors. See Install for the three ways to get the command.

It takes over the whole screen (like vim or htop) and restores your terminal on exit. It needs a real interactive terminal (a TTY); with output piped it says so and stops.

How it relates to the CLI

The TUI is the CLI bridge under an interactive transport. Its host bridge reuses the CLI's implementation verbatim - same headless DOM (jsdom), same filesystem asset access, same export path. The one difference is that the TUI owns the screen, so log output goes to an in-app buffer instead of stdout.

CLITUI
ShapeOne-shot commandInteractive full-screen app
Best forScripts, CI, pipelines, batch fan-outExploring tools, hand-tuning inputs, quick one-offs
Input--flag=value argvKeyboard, in place
Engine / outputSame engine, same bytesSame engine, same bytes
StateIn-memory, ephemeral per runPersisted on disk (~/.lolly)

If you can express a job as a URL, prefer the CLI - it's reproducible and pipeable. Reach for the TUI when you want to see and adjust a tool the way you would in the web shell, but from a terminal.

Provenance defaults

The C2PA and Imprint rows both open ON, the same default as the app and the CLI, and the same tool declarations opt them out: a tool that sets render.c2pa:false, and any on-device privacy utility, opens with both rows off and keeps them off. All three surfaces read one policy in the engine, so they cannot drift apart. The Imprint row reads no pixels to mark on a vector or data format, since there are no pixels to carry it. Durable stays off, since it is a neural encode and a model download.

Cycle either row to off for a barer render, or set both off for byte-reproducible output. The CLI page has the measured cost of that choice, and it applies here too, because the terminal exports through the same engine path: the credential is about 2 KB and no measurable time, while the Imprint on a raster costs time that scales with pixel count and grows the file, because the mark adds detail that lossless compression cannot squeeze away. A PNG carries its Imprint browser-free, so turning it on does not pull the export into the browser tier. What you get for leaving them on is a file that can prove where it came from, plus a mark that survives a re-encode or a screenshot, which a metadata credential alone does not.

Views

The TUI mirrors the web shell's layout, distilled to the terminal. Switch top-level views with the number keys; every view is keyboard-navigable (hjkl / arrows, Enter to open, Esc to go back).

Batch (the "TUI way", no /pro grid)

Three sources, one zip: a Projects folder subtree (e), a ticked multiselection of saved sessions across folders (Space to tick, b to run) or a CSV/TSV file (c) - the same row format the CLI batch subcommand reads (a toolId column, optional per-row format/width/height/unit/dpi and a column per input). The result is one .zip on your Desktop, optionally password-locked.

Preview priority

For a designer tool the preview is low-priority and opt-in (p). For a utility - where the output is the whole point - it's the primary pane, shown automatically (even on a narrow terminal):

No wasted space on a form that barely exists.

The layout is responsive: narrow terminals collapse the two-pane tool view into a single stacked column, the same way the web shell reflows on mobile.

Inputs it can edit

Every input type the engine models is editable from the keyboard - text, numbers, booleans, selects and repeating blocks (drill into a block → its rows → its fields; add, delete, reorder and nest). It also edits file inputs (give it a path - the bytes are read locally and handed to on-device utilities like strip-data) and asset inputs (a catalog id like suse/logo/hor-pos-green, or a pasted lolly.tools tool link, resolved to an embedded render).

Inline preview

Preview is opt-in (p) and secondary - seeing inputs, files, projects and export settings matters more than pixels in a terminal. When enabled, the TUI rasterises the tool's SVG and renders it as a truecolor half-block image directly in the terminal cells (no external image protocol required).

What it can render

Two tiers, picked automatically per format:

Set the browser tier up once:

npm run install:browser   # downloads Chromium into .browsers at the repo root
                          # (an existing services/mcp/.browsers install, or PLAYWRIGHT_BROWSERS_PATH, is reused instead;
                          #  LOLLY_BROWSER_CHANNEL=chrome uses an installed Chrome and downloads nothing)
npm run build:web         # a built web shell for full-fidelity raster/pdf/video

If Chromium (or the built shell) isn't present, those formats fail with a one-line "run npm run install:browser / npm run build:web" message, and the TUI falls back to writing HTML so every tool still exports something. SVG and data formats never need either.

Exports are written to your desktop (~/Desktop) by default, with the folder editable per export.

URL Screenshot (url-shot)

url-shot - capture any live web page - runs fully in the TUI on the browser tier. It drives Chromium straight at the URL, so you get more than a plain shot:

The crop and recolor controls are ordinary tool inputs, so they're editable from the keyboard like any other. (Recolor also applies in the web/desktop shells; crop and vector PDF/SVG are the terminal capture's own.)

Persistence

Unlike the ephemeral CLI, the TUI keeps state on disk: saved sessions, project folders and your profile. It uses the same directory the desktop app and the CLI use, picked in this order:

  1. $LOLLY_STATE_DIR, when you name one.
  2. $LOLLY_TUI_DIR, the old name for the same thing. It still works and prints a one-line note saying which name replaced it.
  3. The desktop app's own data directory, when the app is installed here: ~/Library/Application Support/tools.lolly.Desktop on macOS, $XDG_DATA_HOME/tools.lolly.Desktop (or ~/.local/share/...) on Linux, %APPDATA%\tools.lolly.Desktop on Windows.
  4. ~/.lolly.

Saved projects live in saved-state/<slot>.json, in the record the desktop app writes. So a project you saved in the app is in the terminal's Projects list, and a project you save here opens in the app. Each record keeps both halves of its state: the tool's serialised URL-state, which reopens through the same parser the web shell and CLI use, and the resolved input values, which is what a session saved in the app carries.

Projects the TUI saved before this move sat in sessions/<slot>.json. They are copied into the shared layout the first time you open Projects, with their names and dates intact. The old files are left where they were, and a marker beside the new ones stops the copy running twice.

Project folders and your profile stay terminal-only files beside them, folders.json and profile.json. The app keeps both of those in its browser database, so there is nothing on disk to share yet.