Panels

console tui panels

TUI Panels

TUI mode presents a tabbed content area with three tabs, a sidebar of live status panels on the right, a cascade overlay, and a persistent frame of header, status bar, and help bar around them.

Layout

┌─────────────────────────────────────────────────────────────┐
  My Table     Running   v1.0                                 ← Header (F4 to expand)
  /path/to/config.cade                                       
├─────────────────────────────────────────────────────────────┤
   Ball In Play  P1  1,000  Ball 1/3                          ← Status bar (F5 to toggle)
├────────────────────────────────────────────┬────────────────┤
  [Logs]  Events  Console                    Watch          
├────────────────────────────────────────────┤   score  1,000 
                                             Score          
  Log output...                                P1  Ball 1/3   ← Sidebar
                                             Metrics        
                                             Profiler       
├────────────────────────────────────────────┴────────────────┤
  q quit  F1-F3 tabs  F4 header  F5 status                     ← Help bar
└─────────────────────────────────────────────────────────────┘
TabKeyShows
LogsF1Structured log output from the engine and drivers (default on startup)
EventsF2Live hierarchical event tree, grouped by game / ball / mode
ConsoleF3The cade:debug> REPL prompt and its output

The right-hand sidebar stacks four always-visible status panels — Watch, Score, Metrics, and Profiler. It takes about a quarter of the terminal width and hides automatically when the terminal is narrower than 100 columns, giving the active tab the full width.

Tab moves keyboard focus from the active tab into the sidebar panels and around again; Shift+Tab cycles backward. The focused panel is the one that receives panel-specific keys (the Metrics keys, the Profiler sort keys, and so on).

The Cascade viewer is an overlay rather than a tab — press F7 (or Ctrl+E) to open it as a floating panel over the dimmed screen, and F7, Ctrl+E, or Esc to dismiss it. See Cascade Visualization.

Logs Tab

Streams structured log output as a scrollable, color-coded list.

12:13:44.205 DEBUG [audio.mixer] Parsed use block for voice=synth.plunger
  • Timestamp — millisecond precision, from the log record
  • LevelDEBUG, INFO, WARN, ERROR; color-coded by severity
  • Source — the component that emitted the log. Nested components render as dotted paths (e.g. audio.mixer). When a record has no source the bracketed segment is omitted entirely — you never see empty [] brackets
  • Message — the formatted message followed by any structured key/value fields

Filter, Search, and Pause

Three independent modes for working through high-volume output:

Text filter (/) — hides non-matching lines. Press /, type a substring, press Enter. Matching is case-insensitive against the message, source, and structured fields. Press / again or Esc to clear.

Search (Ctrl+F) — highlights matches in place without hiding other lines. Use n / N to jump between matches. Filter and search compose: search highlights within the filtered view.

Source filter (s) — opens a picker listing the sources currently present. Select with Space, commit with Enter, dismiss with Esc or q.

Pause (p) — freezes the visible feed while new entries continue to buffer. Press p again to resume; buffered entries drain in order. Pause is independent of autoscroll.

Logs Tab Shortcuts

ShortcutAction
j / k or / Scroll one line (moves the cursor when autoscroll is off)
PgUp / PgDnHalf page up / down
g / Home, G / EndJump to first / last entry
aToggle autoscroll
pToggle pause
wToggle word wrap
fToggle the filter status bar
d / i / W / eFilter to Debug / Info / Warn / Error level
sOpen the source-filter picker
/Text filter (hides non-matching lines)
Ctrl+FSearch (highlights matches)
n / NNext / previous search match
EscClear the search, then the active filter
?Open the keybinding help overlay

The Logs tab is the one view with a built-in help overlay — press ? for a two-column reference, and any key to dismiss it.

Events Tab

A live, hierarchical tree of game events organized by span — game sessions, balls, and active modes. The tree updates in real time and supports collapsing, filtering, and detail inspection.

Tree Structure

Full Example Table ·  RUNNING · localhost:50052  · v0.1.0
./cade/docs/examples/full-example-table-with-modes
────────────────────────────────────────────────────────────────────────
 Ball in Play  player1  17,000  Ball 1/3
switch.hit ▁▁▁▁█▁▂▁▁▁ 31  flipper.pressed ▁▁▁▁▁█▁▁▁▁ 14
────────────────────────────────────────────────────────────────────────
· [-] Player 1  Ball 1/1  Score: 17K  Events: 59
╰── · [-] Ball 1  Score: 17K  (34s)  Events: 59
    ├── · [-] Active Modes (1)
       ╰── · +23.078s — multiball pri:200
    ├──  ... 43 earlier ...
    ├── · +11.577s     device.Kicker1.activated [switch] +10K
    ├── · +11.577s     mode.multiball.started
    ├── · +11.596s     ball_device.unhit <BallRelease>
    ├── · +11.610s     switch.hit <StartBallControl> held 651ms
    ├── · +12.612s     switch.pressed <launch_ball> held 1.5s
    ├── · +14.662s     device.Gate.activated [switch]
    ├── · +15.111s     system.ball.drain
    ├── · 12:14:03.257 system.game.end
    ╰── · [-] lifecycle
        ╰── · +11.577smode.multiball.started

Each span can be collapsed ([+]) or expanded ([-]) independently. Active modes are grouped into an Active Modes subtree below their ball span. Events carry a leading time column, either +11.577s relative to ball start or a wall-clock stamp (see Time Display), and are annotated with points (+10K), device context (<BallRelease>), and held duration for merged pairs (held 651ms). Cascade durations under 0.05 ms are hidden to reduce noise; under 1 ms renders dim, 1 ms and above renders in a warning color to flag slow cascades.

A mode that just ended lingers in Active Modes for a couple of seconds, greyed out with its score frozen, before rolling off. If the same mode restarts while the prior activation is still fading, both appear as separate rows; only the live one keeps accumulating.

Collapse state resets when a new game starts.

Time Display

The leading time column has three modes. Press Alt+T on the Events tab to cycle between them; the hint bar at the bottom names the mode you will land on next.

ModeShows
Hybrid (default)Ball-relative offsets (+11.577s) for gameplay events, and wall-clock time (12:14:03.257) for the infrastructure and operator events: game start and end, coin insert, pause
RelativeBall-relative offsets on every row
Wall clockWall-clock time on every row

Hybrid is the default because it answers both questions at once: how far into the ball a shot landed, and what time of day the game itself started and ended. Switch to wall clock when you are lining the tree up against an external log or a screen recording, and to relative when you want every row measured from the same ball start.

The column is padded to the widest value on screen, so switching modes shifts the event names left or right but keeps them aligned.

Archived Games

Finished games are retained in a bounded ring above the live game so you can scroll back without leaving the TUI.

· [+] Game started +01:23:45  Player 1: 42K  Player 2: 18K
· [+] Game started +01:41:07  Player 1: 12K
· [-] Game  (live)
╰── · [-] Player 1  Ball 2/3  Score: 6000  Events: 18
    ╰── ...
  • Up to three archived games are retained; a fourth evicts the oldest.
  • Collapsed by default — expand with l or Space.
  • Summaries only. Archived entries keep the player leaderboard, per-ball summaries, completed-mode history, and lifecycle entries. Raw per-event leaves are dropped, so the ball node shows an aggregate count (Events: N) but has no event children — a large memory saving in exchange for losing per-event inspection after the game ends.

The active game is never archived while in progress.

Event Compression

Related event pairs are automatically merged into single entries:

  • Hit/unhit pairs — a switch or ball device firing both hit and unhit in the same span becomes one entry showing held duration (left_inlane held 234ms). Cross-span pairs are not merged.
  • Switch press/release pairs — merged the same way.
  • Flipper pairs — a full press sequence (flipper press + staged press + both releases) compresses from four events into one, dramatically reducing flipper noise.

Press p to toggle expand mode, which injects synthetic rows for the closing half of each merged pair. This is display-only; the underlying data is unchanged.

Overflow Expansion

When a span exceeds the per-span display limit, older events hide behind an overflow node (▸ ... N earlier ...). Press Enter or l on it to reveal the next 16, repeatedly to page through. Collapse and re-expand the span to reset.

Sibling-Lock Mode

Sibling-lock constrains j/k to one depth level — useful for scanning all completed modes without diving into their children. Press s to lock to the current node’s parent:

[LOCK] j/k:siblings  g/G:first/last  esc:unlock

While locked, j/k move between siblings, g/G jump to first/last, and h/l/Space/Enter still collapse, expand, and open details. Esc unlocks. The lock releases automatically if the locked parent stops being visible.

Memory Management

The event tree caps retained entries (default 10,000). At the cap, the oldest completed game span and its events are evicted. At least two game spans must exist before eviction, and the active game is never removed.

Events Tab Shortcuts

ShortcutAction
j / k or / Move cursor down / up
g / Home, G / EndJump to first / last
l / Expand node, or descend into first child
h / Collapse node, or ascend to parent
[ / ]Previous / next sibling
SpaceToggle collapse of the selected node
EnterReveal the next 16 hidden events on an overflow node; open the detail view on any other node
sToggle sibling-lock mode
pToggle paired-event expand mode
Alt+TCycle the time column (hybrid → relative → wall clock)
cOpen the cascade viewer for the selected event
aToggle autoscroll
/Enter filter mode (press again to clear)
EscRelease sibling lock, then clear the filter

The filter bar accepts structured clauses — see Filtering Events for the syntax.

Console Tab

The REPL. Contains the cade:debug> prompt and a scrollback view of command results and scoring output.

The input line offers ghost-text completion suggestions, history navigation, and readline-style editing:

ShortcutAction
EnterSubmit the command (accepts the history-search result when searching)
TabAccept the offered completion; with no completion showing, move focus to the sidebar
/ Navigate command history
Ctrl+RReverse history search
Ctrl+SStep forward through history-search results
Ctrl+UClear the line and return the cursor to the start
Ctrl+/Toggle the search bar
EscCancel history search

Note: q quits the console from the Logs and Events tabs, but not from the Console tab — there it types the letter q into your command. Use Ctrl+C to quit from anywhere.

Sidebar

The sidebar’s four panels update live while you work in any tab. They render top to bottom in this order and are cycled through with Tab / Shift+Tab.

Watch Panel

The watch list — every variable and expression you have added with watch, updated in real time, plus the active player’s score and ball while a game is in progress. Open it when you want scoring state visible at all times without re-running inspect.

The header shows the current display mode:

ModeShows
CompactNames and current values only
PersistentAdds a sparkline trend per numeric variable
AuditAdds a “Recent Changes” log of the latest value changes

With the Watch panel focused:

ShortcutAction
mCycle display mode (Compact → Persistent → Audit)
cClear all watched variables and expressions

Launch with --watch=false to leave the Watch panel out of the sidebar entirely.

Score Panel

Current game state at a glance: the game phase, each player’s score with the active player highlighted, the ball number, and the credit balance (or free play). Display-only — it has no keys of its own. It mirrors what the game status bar shows, but stays visible even when the status bar is toggled off.

Metrics Panel

Runtime health, grouped into categories:

CategoryShows
SystemCPU, memory, goroutine count, heap objects, GC pause time
gRPCEvents sent/received, active and total streams, uptime
PerformanceFPS, frame time, update rate (populated while an engine is running)
ScoringEvents/sec, average latency, cache hit rate, committed and pending counts (populated when a scoring engine is loaded)

With the Metrics panel focused:

ShortcutAction
EnterDrill into category selection — Tab / Shift+Tab then cycle categories, Esc exits
hToggle the history view
eExport current metrics and history to a JSON file
rReset collected metrics
+ / -Speed up / slow down the update rate

Profiler Panel

Live per-event timing from the scoring profiler: one row per event with Count, Avg, P50, P95, P99, and Max in microseconds, sorted by P95 by default. The panel shows No profiling data yet until you start the profiler with profile start.

With the Profiler panel focused:

ShortcutAction
sCycle the sort column (Event, Count, Avg, P50, P95, P99, Max)
rReverse the sort direction
/ or k / jMove the row selection

Chrome

Header

Shows table identity and engine status. F4 toggles between two modes:

  • Compact (default, 2 lines) — table name, engine status, platform health, and Cade version on line 1; config path on line 2.
  • Regular (4 lines) — table name and engine status; config path; platform address and connection status; Cade version.

Game Status Bar

Toggled with F5. When visible it shows:

  • Game phase — ● Ball In Play, ○ Starting, ■ Game Over, or idle
  • Player, Score (comma-separated), and Ball (e.g. Ball 1/3)
  • Event sparklines — event activity over the last 60 seconds

The status bar drops lower-priority fields when the terminal is narrow.

Tab Bar

A single line showing the three tabs. The active tab is bold and bracketed; inactive tabs are dimmed. Press the matching F-key to switch instantly.

Help Bar

A single line at the bottom showing the global key hints: q quit, F1-F3 tabs, F4 header, F5 status.

Global Shortcuts

ShortcutAction
Ctrl+CQuit the console
qQuit (Logs and Events tabs only — see the note above)
Tab / Shift+TabCycle focus forward / backward through the active tab and the sidebar panels
F1 / F2 / F3Switch to the Logs / Events / Console tab
F4Toggle header between compact and regular
F5Toggle the game status bar
F7 or Ctrl+EToggle the cascade overlay
Alt+CCopy the active panel’s content to the clipboard
Alt+Shift+CCopy the focused log entry (Logs tab)
Alt+LCycle to the next layout preset
EscClose an open overlay, otherwise pass through to the active tab

Copied log text uses the same format as the display, including the source bracket only when a source is present — you never get stray [] in copied output.

Themes

The TUI ships these built-in themes:

ThemeDescription
defaultBalanced scheme suitable for most terminals
darkMuted dark palette
lightBright, readable light mode
high-contrastMaximum contrast for accessibility
monochromeNo colors, minimal distraction
solarized-darkSolarized Dark palette
solarized-lightSolarized Light palette

Pick one at launch:

cade console --theme dark

Or switch live from the prompt — every panel and the chrome repaint immediately:

cade:debug> theme                # show the current theme and the full list
cade:debug> theme solarized-dark # switch, with a color preview

An unknown name is rejected with the list of valid ones.

The theme system adapts to terminal color capability — TrueColor (24-bit), 256-color, 16-color, and 8-color — degrading gracefully.

Separately, the console’s own output colors (prompt, values, errors) are set by the colors block in the console config file, which offers default, solarized, monokai, and custom. See Configuration.