Skip to content

Repository files navigation

tuibot icon: a terminal-faced rover with three exploration nodes

tuibot

Let a curious bot loose in your terminal UI—then replay every move.

Status: alpha Python 3.11+ Docker required arXiv: 2608.03743 License: MIT

A friendly terminal robot exploring random, guided, and scripted paths inside a container while recording a replay timeline

tuibot is an automated testing tool for terminal user interface applications. It launches a target inside a Docker container, gives it a real headless PTY, explores the interface like a user, and brings back screens, actions, crashes, generated tests, and optional line + widget coverage.

The short version: point tuibot at source code, choose an explorer, set a budget, and get a browser-replayable testing expedition instead of a pile of terminal logs.

✨ Pick your explorer

Strategy Personality Best for
🎲 random Fast, deterministic chaos Fuzzing key paths, mouse handling, resize behavior, and crash recovery
🧭 llm_guided Looks, thinks, acts, repeats Goal-oriented exploration when the next useful action depends on the screen
🧪 llm_script Reads the source and writes tests Reusable, assertion-driven shell-use scenarios generated from the real app

Every explorer runs under a time or action budget. If the app exits early, tuibot can relaunch it without resetting the session log or accumulated coverage.

🚀 Launch your first expedition

Requirements

  • Python 3.11 or newer, managed with uv
  • Docker with a reachable daemon
  • An Anthropic-compatible API key only for LLM-backed strategies or generation features

Microsoft shell-use and tuicov live inside the test container; neither needs to be installed on the host.

Install from the checkout

uv sync
uv run tuibot --help

Go

uv run tuibot init             # create config.toml
$EDITOR config.toml            # point it at the app and choose a strategy
uv run tuibot doctor           # check Docker, screenshots, coverage, and credentials
uv run tuibot run              # start exploring
uv run tuibot replay runs/<session-id>

config.toml.example is the complete configuration reference. A small random smoke run looks like this:

[run]
name = "first expedition"
strategy = "random"
seed = 4242

[target]
source_path = "../my-tui"

[budget]
type = "actions"
actions = 50

[entrypoint]
mode = "config"
command = ["python", "-m", "my_tui"]

[docker]
mode = "image"
image = "python:3.13-slim"

[logging]
formats = ["raw", "svg"]

See config.toml.example for input files, generated entry points, Dockerfile generation, strategy tuning, relaunches, screenshots, LLM gateways, and coverage.

🎒 What comes home

Each run gets one timestamped directory that can be copied, archived, or replayed on another machine:

runs/20260731-164500-a1b2c3/
├── config.resolved.toml   frozen configuration for this run
├── session.jsonl          actions, launches, captures, exits, and errors
├── session.json           final outcome, budget, launches, and coverage totals
├── screens/               timestamped raw, SVG, and/or PNG captures
├── entrypoint.json        configured or generated launch recipe
├── inputs/                configured or generated input files
├── coverage/              cumulative tuicov work directory
└── scripts/               generated tests for the llm_script strategy

The replay server turns that directory into a browsable timeline:

uv run tuibot replay runs/<session-id> --port 8080

🧠 How the expedition works

flowchart LR
    S["Target source"] --> D["Docker image"]
    D --> P["shell-use PTY"]

    R["🎲 Random"] --> P
    G["🧭 LLM guided"] --> P
    T["🧪 LLM scripts"] --> P

    P --> A["Screens + actions"]
    P --> C["tuicov coverage"]
    A --> O["One run directory"]
    C --> O
    O --> W["Browser replay"]
Loading

tuibot talks to the shell-use CLI through docker exec. The PTY, target process, and coverage runtime stay together inside the container, while the bind-mounted run directory makes captures and reports appear immediately on the host.

The session budget is the single clock. A crash, clean exit, generated-script failure, or relaunch is recorded as part of the same expedition rather than becoming a separate run.

📈 Turn on coverage

Coverage is powered by public companion project tuicov, which uses the target language's native coverage mechanism and normalizes the results.

tuibot instruments once, runs with --no-build on every launch, and reuses one work directory. Snapshots are cumulative, so relaunches add evidence instead of erasing it.

Install tuicov from a pinned GitHub archive inside the runtime image:

[coverage]
enabled = true
types = ["line", "widget"]

[docker]
tuicov_source = "tuicov @ https://github.com/tui-testing/tuicov/archive/<commit>.zip"

During tuicov development, point at a checkout instead:

[docker]
tuicov_source = "/path/to/tuicov"

A local checkout is mounted read-only at /opt/tuicov and run from source, so edits apply to the next session without rebuilding the image. A package requirement or URL is installed and cached in the generated runtime layer.

Pin a release tag or commit for reproducible runs. Use the main archive only when intentionally following development.

🖼️ Screenshot modes

Format Host dependency Notes
raw None Compact terminal text, ideal for LLM-guided exploration
svg None Native shell-use output with sharp, selectable text
png Rasterizer + font Convenient for image models and portable previews

For PNG support:

uv sync --extra png
uv run tuibot doctor

The optional extra installs resvg as a self-contained wheel. resvg, rsvg-convert, inkscape, or a custom logging.png_command also work.

A rasterizer without fonts can produce a perfectly valid PNG with no visible text. tuibot probes for that failure before the run begins. On fontless systems, set logging.png_font to a monospace .ttf, .otf, or .ttc file.

⌨️ Command deck

Command What it does
tuibot init [path] Write a documented starter configuration
tuibot doctor [-c config.toml] Validate config, Docker, screenshots, credentials, and coverage wiring
tuibot run [-c config.toml] Run one testing expedition
tuibot replay <run-dir> [--port N] Open the standalone browser replay tool

🛠️ Build with us

uv sync
uv run pytest
uv run tuibot --help

Start with AGENTS.md for repository architecture and contributor rules. The companion coverage engine lives at tui-testing/tuicov.

📄 License

tuibot is available under the MIT License.

📚 Cite this project

If you use tuibot in your research, please cite:

@misc{peng2026llmstestterminaluser,
  title         = {Can LLMs Test Terminal User Interfaces?},
  author        = {Chao Peng and Ruida Hu and Ajitha Rajan and Tegawendé F Bissyandé and Jacques Klein and Cuiyun Gao},
  year          = {2026},
  eprint        = {2608.03743},
  archivePrefix = {arXiv},
  primaryClass  = {cs.SE},
  url           = {https://arxiv.org/abs/2608.03743},
}

About

Automated testing for terminal UIs with random, LLM-guided, and scripted exploration, replayable sessions, and optional code coverage.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages