TUI screens and shortcuts

The Cantrip TUI layers modal screens on top of the chat panel so you can inspect Juju state, tail logs, and open files without breaking the session. This page catalogues them.

Overview

The main TUI view is a chat panel for talking to the agent, flanked by status panes and a file tree. Function keys open modal screens over the chat; Esc always closes the current modal. Every modal shares a common chrome: a title bar, a scrollable body, and a footer listing its screen-specific shortcuts.

Function-key screens

Key Screen What it shows
F1 Help Keyboard shortcuts and slash-command reference.
F2 Status toggle Show or hide the Dev / COS status panes on the right.
F3 Logs Tail juju debug-log for the dev model — see Logs for filters.
F4 Debug / Traces COS endpoint URLs with Grafana deep-links — see Traces and COS endpoints.
F5 Watcher reactions Pause/resume the watcher's autonomous reactions. The watcher always keeps observing — the model panes and [Watcher] chat notices stay current — but while paused, detected events don't queue tasks for the agent.
F6 Files toggle Show or hide the charm file pane (tree plus repo-stats sidebar — see Charm file pane). Click a file to open the File detail modal.
F7 Model info Current primary and light model, cost, and token usage.
F8 Integration graph Deployed apps and their relations — see Integration graph.
F9 Transcript Browse the persisted conversation history.

Charm file pane

The right side of the TUI carries a Charm files pane, toggled with F6. Two surfaces sit side by side:

The sidebar is hidden automatically when the pane is too narrow to host both columns; widen the terminal (or close the side panels with F2) to bring it back. Test-pass and lint state are deliberately not in the slate today — they need a bus event from the runner to avoid showing stale data and will land alongside that work.

File detail

Clicking a file in the F6 file pane opens the File detail modal. It shows the path, size, modification time, a best-effort summary of the file’s purpose derived from its contents, the five most recent git log entries that touched the file, and a syntax- highlighted preview rendered via Rich’s Syntax.

Shortcut: R refreshes the modal against the current working tree so you can re-open after a subagent writes to the file. Esc closes.

Tool failure detail

When a tool call fails, the chat shows a one-line block with a brief caption and a dim (details) hint. Clicking that block opens the Tool failure modal, which shows the captured error summary and the tool’s full output — stderr, test logs, tracebacks — so you can see what actually went wrong without opening the transcript viewer. Esc closes. (The block is only clickable when the agent captured detail for that failure; successful calls are never clickable.)

Logs

The F3 Logs screen tails juju debug-log for the dev model. Three shortcuts re-scope the view without leaving the modal:

Integration graph

The F8 Integration graph lays out the deployed apps and their relations as a selectable list — apps first, then one row per relation. The relation rows are the point of the screen:

F cycles a status filter through four states (all apps, only blocked, only waiting, or both — useful for zeroing in on apps that need attention); R refreshes against the live status. When a COS model is connected, both models appear in the one list: a ── Dev model ── section followed by a ── COS model ── section.

Traces and COS endpoints

The F4 Debug screen lists the URLs the agent uses to inspect the COS stack — Prometheus, Loki, Tempo, and Grafana — and builds Grafana deep-links pre-populated with the dev model and time range so one click opens the right dashboard. Each endpoint shows a reachability indicator derived from a live probe so an unreachable endpoint isn’t hidden behind a broken link.

Dev and COS status panes

The right-hand side of the TUI shows two always-on panes, toggled together with F2:

Both panes refresh from the event watcher, so they stay current without polling, and scroll rather than clip when the content grows past the pane height.

Confirmation prompts

Work that affects the outside world — pushing a branch, creating a GitHub repo, working on a triaged issue, spending a Best-of-N racing budget — is never done silently. Instead, Cantrip emits a CONFIRM task that appears in the task panel as a blocked row and prints a framed “… confirmation” prompt in the chat log. The task stays blocked until the user replies approve or skip, so the prompt never disappears off-screen.

The most common confirmation is the repo bootstrap offer, which fires when Cantrip finishes a build inside a directory that has no GitHub remote and gh is available. The default repository name follows the Canonical upstream convention — if the charm is foo, the suggested name is foo-operator. Names that already end in -operator, -charm, -k8s, or -machine are kept as-is.

Reply tokens for the bootstrap prompt:

Tokens can be combined: approve public org=canonical name=my-charm-operator desc=Runs my charm.

Shell mode

Ctrl+X on the chat input toggles shell mode. The input border tints with the warning colour and the placeholder changes to $ shell command (Ctrl-X to leave shell mode) so the state is visible at a glance. Pressing Enter in shell mode runs the command as a subprocess and prints the output as a $ cmd block in the chat — the agent never sees it, no tokens are spent, and Ctrl+X again returns to the normal agent input.

Shell mode is a convenience pass-through to subprocess, not a full shell. Commands are tokenised with shlex and executed under the same Phase 49 sandbox the agent's run_command tool uses, so shell features that the underlying subprocess call cannot handle on its own are not supported:

For interactive shell needs, drop to a real terminal in another window.

Prefix the command with $$ for incognito shell mode. The input still runs as a subprocess and the output still renders into the chat for the user to read, but the persisted row is marked hidden_from_agent: true so any future context-assembly path that would otherwise include shell history skips it. Useful for commands whose output you want visible to you but never to the LLM: