Textual TUI

ooai-llm tui launches an optional interactive terminal app for model exploration. It does not replace the CLI; it gives you a faster way to inspect the same catalog, cost, suite, and profile concepts.

Install

The TUI is optional so base installs stay small:

pip install "ooai-llm[tui]"

Launch it:

ooai-llm tui

From a source checkout, prefer the project environment so you do not accidentally launch an older globally installed command:

pdm run ooai-llm tui

Pick a theme explicitly if the default is not what you want:

pdm run ooai-llm tui --theme paper
pdm run ooai-llm tui --theme slate
pdm run ooai-llm tui --theme mono --refresh-cooldown 0

Available themes:

  • paper: default warm light theme for high-contrast scanning.

  • slate: dark neutral theme.

  • mono: minimal-color theme for quieter terminals.

  • forest: earlier earthy green/gold theme.

Start with provider and token-shape defaults:

ooai-llm tui \
  --source litellm \
  --providers openai,anthropic,mistral \
  --input-tokens 10000 \
  --output-tokens 2000 \
  --budget-usd 10 \
  --theme slate \
  --views cheapest,coding,catalog

Limit the data that is fetched when you only want a subset:

pdm run ooai-llm tui --providers mistral --views cheapest,catalog --limit 10
pdm run ooai-llm tui --view catalog --view suites --no-benchmarks

Available load views are cheapest, coding, catalog, suites, and benchmarks. Skipped views remain visible in the TUI, but they render a clear “not loaded” message instead of triggering provider/catalog work.

If the catalog looks too small, you are probably looking at the supported ooai provider catalog. That is the right catalog for factory defaults and profiles, but it intentionally covers only first-class supported providers. Use the raw LiteLLM registry scope when you want broad discovery across every provider label included in your installed LiteLLM package:

pdm run ooai-llm tui --catalog-all
pdm run ooai-llm tui --catalog-scope litellm-registry --include-non-chat --limit 0 --views catalog

--catalog-all is shorthand for catalog-only loading, raw LiteLLM registry scope, non-chat rows included, and no row limit.

Control refresh throttling when you know you are using only local LiteLLM metadata:

ooai-llm tui --source litellm --refresh-cooldown 0

If Textual is not installed, the command prints an actionable install message.

Screens

The TUI is a visual layer over tested package functions:

  • Home shows the selected source, providers, token shape, budget, and key map.

  • Cheapest shows cost-ranked model comparisons for the configured token shape.

  • Coding shows coding-oriented model comparisons.

  • Catalog shows raw model metadata: release, price, token limits, capabilities.

  • Suites shows catalog-derived suite candidates for runtime experiments.

  • Profiles shows ChatModelProfile and LLM runtime reminders.

  • Benchmarks shows known LiveCodeBench Pro endpoint surfaces when enabled.

The main screen includes a dashboard, persistent view-navigation buttons, provider filter, free-text search, view selector, refresh button, table, and row detail pane. Free-text search matches model names, providers, capabilities, endpoint paths, and other visible row metadata.

Views are switched with an explicit Textual ContentSwitcher, not a secondary tab strip, so the top buttons, view selector, command palette, and key bindings all update the same active view.

Data Path

The app gets its data from ooai_llm.tui.data.build_tui_snapshot(...). That function is independent of Textual and can be tested or reused by future exporters.

from ooai_llm.tui.data import TUIConfig, build_tui_snapshot

snapshot = build_tui_snapshot(
    TUIConfig(
        providers=["mistral"],
        source="litellm",
        input_tokens=10_000,
        output_tokens=2_000,
        budget_usd=10,
    )
)

print(snapshot.cheapest[0].model)
print(snapshot.cheapest[0].call_cost)
print(snapshot.catalog[0].capabilities)

Use raw LiteLLM registry scope from Python when you want the same broad catalog that powers --catalog-all:

from ooai_llm.tui.data import TUIConfig, build_tui_snapshot

snapshot = build_tui_snapshot(
    TUIConfig(
        catalog_scope="litellm_registry",
        include_non_chat=True,
        load_views=["catalog"],
        limit=0,
    )
)

print(len(snapshot.catalog))

The same data helpers support non-terminal tests and exporters:

from ooai_llm.tui.data import filter_tui_rows, rows_for_view

rows = filter_tui_rows(
    rows_for_view(snapshot, "coding"),
    query="tool_calling",
    provider="mistral",
)

Manual refreshes are rate-limited by TUIRefreshGate so repeated key presses do not hammer provider catalogs. The default cooldown is two seconds and can be changed with --refresh-cooldown.

Extension Points

The TUI is now a package, not a standalone module:

ooai_llm.tui.app       Textual app construction and event wiring
ooai_llm.tui.data      reusable snapshot, filtering, and refresh-gate helpers
ooai_llm.tui.themes    selectable CSS palettes
ooai_llm.tui.commands  command-palette command specs

The app uses Textual’s built-in command palette (Ctrl+P) for view switching, search, clearing search, and refresh commands. That is the first extension point for future actions because new commands can be added declaratively in ooai_llm.tui.commands without making the app class larger.

Textual also has official APIs we should use before adding heavier third-party dependencies: DataTable and Markdown widgets for the current explorer, workers for slow catalog/provider refreshes, screens/modals for profile editors or save dialogs, CSS for theming, and notify(...) for transient status messages. Potential optional add-ons later are textual-fspicker for import/export file dialogs and textual-serve for browser-served demos, but neither should be a base dependency yet.

Key Bindings

  • Click the top navigation buttons to switch views.

  • tab, n, or ] switches to the next view.

  • shift+tab, p, or [ switches to the previous view.

  • 1 through 7 jump to major views.

  • / focuses free-text search.

  • escape clears search.

  • r refreshes catalog/comparison/suite data, subject to the refresh cooldown.

  • q quits.

Scope

The first TUI is an explorer, not a model router. Use it to answer:

  • Which models are cheapest for this call shape?

  • Which coding models have tool calling or structured output?

  • Which providers have the best calls-per-budget tradeoff?

  • Which shortlist should become a model suite or profile map?

  • Which known benchmark endpoint surfaces are available for optional CLI checks?

Use the CLI or Python API for automation and checked-in configuration.