Skip to content

The TUI

bash
rta

Bare rta on a terminal opens the interactive shell. In a pipe it prints help instead, so a script never hangs on an interface nobody can see.

It is the same capabilities as the CLI — the same declarations, the same safety classes, the same results. What changes is that you can browse them, fill inputs in a form, and see a table you can walk through.

The landing dashboard

A search bar across the top, and one tile per plugin that has something to show at a glance. Typing filters every capability in the catalogue on the fly.

KeyWhat it does
/Search
enterOpen
escBack
q or ctrl+cQuit
[ ]Move a tile
HHide a tile
pPlugin inventory — where a hidden tile comes back
tTheme
cConfigure

Tiles are yours to arrange. H hides one you never look at; p opens the inventory where any of them comes back.

Stating the dashboard yourself

With no dashboard: block, rta builds one: a tile per plugin that has a capability which is Read, needs no input, and is cheap enough to run unasked. Plugins installed later appear on their own.

There are two ways to change that, and the difference is whether tomorrow's plugin still shows up.

Adjust the automatic set. hidden: and order: bend it without freezing it:

yaml
dashboard:
  hidden:
  - git.overview
  order:
  - sys.overview
  - todo.list
  columns: 3

Or state it exactly. tiles: replaces the automatic set outright — hidden: and order: are not consulted, because the list is already both:

yaml
dashboard:
  tiles:
  - id: kube.overview
  - id: todo.list
    span: 2
  - id: pg.overview
    with:
      profile: prod

with: fills the capability's inputs. span: widens a tile past what its own declared width works out to — for the one you actually read.

Naming a tile is the only way to get a capability the automatic dashboard leaves out. Anything that reaches off the box — every kube, pg, s3 and vault capability — is kept off it deliberately, however cheap it looks: a dashboard runs its tiles on load and again on a timer, and nobody expects opening a TUI to spend an API quota or disclose anything to a third party. Writing one into tiles: is you asking for it, which is a decision the automatic path can't make for you.

Worth knowing what that costs before you do: a tile refreshes on a timer for as long as the TUI is open, so a cluster-wide kube.overview tile is that many kubectl calls an hour, every hour. rta explain kube.overview prints what a capability actually reads, which is not always only what its name suggests.

Two things the block will not do, whatever you write in it:

  • A tile that is not Read is dropped. Otherwise {id: kv.rm, with: {key: old-token}} would delete that key on startup and keep deleting it — on a timer, with no form and no confirmation, since the destructive gate lives on the CLI and the browse path and a tile goes through neither.
  • The whole block is ignored unless the config is one you named — your user config directory, or RTA_CONFIG. rta falls back to ./.rta.yaml when there is no user config directory (ordinary under env -i, in a container, in CI), and a cloned repository does not get to arrange your screen: {id: http.get, with: {url: …}} there would be a beacon that starts the moment you open the TUI in that directory. hidden: is the same hazard pointed the other way — it can take the agent tile off the screen, and that tile is where you notice a parked consent request before its clock runs out.

The catalogue

Every capability as a table grouped by plugin — one row each, with its ID, its safety class and its summary. The filter stays live, every pane is bounded by the terminal and scrolls inside it, and the mouse wheel works.

Running something

A capability with inputs opens a form built from its declaration:

  • Fields that declare Options become a picker.
  • Fields that declare Suggest complete from what exists on your machine — your tags, your keys, your hosts file.
  • Path fields complete directory by directory as you type.
  • ctrl+e opens $EDITOR on a long body.
  • shift+enter accepts every remaining field at its current value, for a form whose defaults are already right.

Tab means one thing on every field

Take me forward. What that is depends only on what the box under the cursor can still be completed to, never on which field it is:

What the box holdsWhat tab does
something an offer extendstakes the offer, and stays — so a path, a cluster coordinate or a comma list is walked a segment at a time, exactly as in a shell
nothing yetsays what is on offer, because there is no ghost to accept until something is typed
everything there was to completemoves to the next field

shift+tab is the previous field and enter is the next one, whatever the box holds. A field that completes says so under itself, because the footer speaks for the screen rather than for the box under the cursor.

Destructive capabilities confirm before acting, the same as on the CLI.

The plugin inventory

p opens what is installed, what each plugin puts on the dashboard, and — the part worth having a pane for — any artifact rta found on $PATH and refused to run. A trust gate's failure mode is silence: a plugin that is installed and doing nothing looks exactly like one that was never installed.

KeyWhat it does
pOpen the inventory (and close it)
spaceShow or hide its dashboard tile
tApprove an artifact, or take an approval back
aChoose which credential locations it may read
cConfigure it
enterIts capabilities, in the search bar

t is the decision made where the evidence is: the digest and the path are on the screen while you take it, which the command line shows you only afterwards. Neither direction takes effect on the process you are in — trust is read once, before anything is launched — so approving says it loads when rta restarts, and withdrawing says the plugin already running stays running until rta exits.

a is the permission after that one. Approving says these bytes may run; allowing says what they may read — a kubeconfig, an SSH directory, whatever the plugin declares it needs. The row shows both sides: what it has been allowed, and what it is still asking for.

a opens a form where t is a keypress, and the difference is deliberate. Approving is one yes/no about one thing already named on the row. Allowing is plural — a plugin can declare several locations, and a bare key would hand over every one of them from a cursor position. The form is also what makes taking access back expressible: the list you submit is the whole grant, so clearing a box withdraws that location and there is no second command to learn. A plugin you have not approved yet cannot be allowed anything — running at all is the decision that comes first, and the pane says so rather than opening a form that could not succeed.

Working with results

KeyWhat it does
enterOpen the row
eEdit inputs and run again
rRe-run
yCopy as JSON
dDelete
escLeave a slow run

Views are actionable rather than static. In a task list, d marks done and x removes — from the list and from a record's own page, refreshing as it goes. Detail pages are composed from other capabilities' views rather than rebuilt, so a record page shows metadata, prose and relations as separate sections.

Profiles

f opens the profiles pane — your configured environments, which one is on, and what each covers. n creates one and c edits it, which is the shortest way to define a profile: the form is generated from each plugin's declared inputs, and it knows which of them are secrets, so a credential lands in secrets: as a reference instead of in set: as a value.

KeyWhat it does
fOpen profiles
uUse this one
enterThe plugins inside it
nNew
dDelete
sSet a credential
yCopy export lines for the credentials nothing has set — shown only when there are some

Adding a plugin to an environment is one form. Press n in the pane and the editor opens on the plugin under your cursor, already pinned to its artifact, with that plugin's own configuration keys under it — tab completes the name, and naming a different one swaps the keys below. The form asks three things and says where each starts:

── how to reach it — one of these, or neither to connect directly ────
── what staging changes about it ────

If the plugin you added needs a credential and nothing supplies one, the credential editor is the next screen rather than somewhere to navigate back to. esc declines; the entry is already saved.

Switching a profile on here does the same thing rta use does, including the part worth remembering: while a profile is on, rta mcp serve refuses every other one. See Profiles.

Charts

Some capabilities render as charts when there is a terminal to draw in:

bash
rta sys cpu --cores
rta net ping example.com --graph

Markdown bodies — notes, audit findings, anything returning prose — are rendered rather than dumped.

Untrusted plugins

If rta found an rta-plugin-* binary it has not been told to run, the TUI says so in a pane rather than a startup line. The line would be written to the primary buffer, and the TUI opens on the alternate one — so it would be covered before anyone could read it. The pane is the only place a person inside the TUI can learn a decision is pending.

See Using plugins.

Next

  • The CLI — the same capabilities, scriptable
  • Profiles — what the f pane manages