Skip to content

Keybindings

The default virtufin-tui keybindings. Press ? in the TUI for the same table inline.

Global (App level)

Key Action
? Show help overlay
q Quit

Dashboard navigation

Key Action
right Next top-level tab (wraps)
left Previous top-level tab (wraps)
1-9 Switch to the Nth sub-tab of the active top-level tab

The tab layout (which top-level tabs exist, and which panes are under each) comes from pane_order in config.toml, not a fixed list -- see Custom panes. The tables below assume the shipped default layout (Home / Trading / Infra).

Beyond navigation, Dashboard forwards a small set of generic keys to whichever action_* method the currently-mounted pane implements. A key is hidden from the footer entirely if the current pane doesn't implement the matching method.

Key Dispatches to (first match wins)
r action_refresh / action_refresh_data / action_run_script
a action_action / action_add_topic / action_schedule
d action_delete_row / action_disconnect_row / action_delete_topics
enter action_detail / action_switch_context
space action_toggle_pause
/ action_filter
c action_clear
s action_save_script
n action_new_script
w action_toggle_wallclock
t action_toggle_msgtime
Ctrl+L action_clear_chat (AI tab only)
P action_switch_provider (AI tab only)

Home

No pane-specific bindings.

Home

Trading tab

Instruments, Order Book, Portfolio, P&L, and Risk are, as of this writing, mostly placeholders (see Architecture) -- all five currently share the same single binding:

Key Action
r Refresh

The Config sub-tab under Trading is the same page documented under Infra below. The AI sub-tab is documented at AI tab.

AI

A chat assistant that drives the control plane via tool calls. Appears under both Trading and Infra (just before Config).

Key Action
Enter Send the typed message
Ctrl+L Clear the transcript and start a fresh conversation
P Switch the active LLM provider

See AI tab for provider setup (llm_providers.toml, DEEPSEEK_API_KEY / MINIMAX_API_KEY / OPENAI_API_KEY).

World

Key Action
r Refresh
Enter Set the highlighted source as the active world
a Add an untagged connection as an atomic world
n Connect a websocket config (opens WS, sends handshake, starts publish)
c Compose a new world from 2+ existing worlds
p Toggle publish on / off for the selected connection
d Remove a world (sets the world tag to empty)

A World dropdown and a filter checkbox sit above the source table. Pick a world in the dropdown and check the box to show only that world's sources; uncheck to show all. Worlds are derived from the world field of the TOML configs in ~/.config/virtufin/tui/worlds/.

The Publishing column uses a three-state symbol for feed rows: green filled ● (connected + publishing), green hollow ○ (connected but publishing toggled off), grey hollow ○ (not connected).

Instruments

Instruments

Order Book

Order Book

Portfolio

Portfolio

P&L

P&L

Risk

Risk

Infra tab

Workers

Key Action
r Refresh
n New Worker: pick a type from the local registry (~/.config/virtufin/tui/workers.toml), fill in its config, and create it
Enter Open a read-only worker detail popover (Escape to dismiss)
a Open the action modal: set/clear tag, start, stop, delete
d Delete worker (with confirmation)

Workers

Connections

Key Action
r Refresh
Enter Open a read-only connection detail popover (Escape to dismiss)
a Open the action modal: set/clear tag, start/stop publish (by topic), disconnect
d Disconnect (with confirmation; row is removed on success)

Connections

Scripts

Key Action
/ Navigate the script list
r Run the highlighted script (subprocess, isolated)
s Save the edited script (user scripts only)
n New user script (from a template, saved to ~/.config/virtufin/tui/examples/)
e Toggle between the form (if the script has a paired .form.json) and the code editor
f7 Select all in the editor
Ctrl+C / Cmd+C Editor focused: copy selection (Textual native). Output log or script list focused: copy the entire output log to clipboard.
Ctrl+V / Cmd+V Paste in the editor (Textual native, terminal bracketed paste)
Ctrl+X / Cmd+X Cut selection in the editor (Textual native)

Textual's binding chain checks the focused widget first, so Ctrl+C on the editor copies a selection (native TextArea) and on the output log copies the full buffer (ScriptsPage's own binding). q is the global app-quit key -- Ctrl+C never quits, it copies.

Scripts, and any custom pane built the same way, use the same script+form convention: a .py file with an optional sibling .form.json rendered via textual_jsonforms. See Scripts for the full write-up, including the env-var contract and the init_scripts startup mechanism.

Scripts

Triggers

Key Action
r Refresh
a Schedule a new trigger
d Delete the highlighted trigger

Triggers

States

Key Action
r Refresh

Events

Key Action
space Pause / resume the live event stream
c Clear the events buffer
/ Filter events (substring match)
a Add subscription topics
d Remove subscription topics
w Toggle the wallclock timestamp column
t Toggle the message (CloudEvent time) timestamp column

Events

Config

Key Action
Enter Switch to the highlighted context
ctrl+up / ctrl+down Move the highlighted pane up/down within its tab
delete Remove the highlighted pane from its tab
i Insert the highlighted "available custom pane" after the highlighted row in "Tabs & Panes"
x Add a brand-new top-level tab (prompts for id + label)

See Custom panes for the pane_order schema, how the "Tabs & Panes" section works, and how to write a custom pane. See Contexts for the contexts table above it.

Config

Action modal

Opened via a from Workers or Connections.

Key Action
Tab / Shift+Tab Move between fields
Enter Submit
Escape Cancel
Ctrl+Z Undo (tag changes only, 2-second grace period after submit)

Detail popovers / service browser

Key Action
Escape Close (worker/connection detail popovers) or go back a level (service browser)
Enter Drill into the highlighted item (service browser)