The dashboard is fully keyboard-driven. Global keys work from any panel; the rest are scoped to the focused panel. The help overlay (?) shows the same reference in-app.

Global

KeyAction
qQuit
TabCycle to the next panel
Shift+TabCycle to the previous panel
1 2 3 4 5Jump directly to the panel whose title shows [N]
?Toggle help overlay
aArm robot
dDisarm robot
fForce disarm (error state only)

Each panel's title carries a bold-cyan [N] badge that mirrors the number key for that panel: [1] Safety, [2] Commands, [3] Joints, [4] Events, [5] Parameters.

Events panel

KeyAction
j / DownScroll down
k / UpScroll up
EnterShow event details
pPause / resume
cClear events

Commands panel

KeyAction
j / DownSelect next
k / UpSelect previous
EnterExecute (or enter argument edit mode when the command declares arguments)

Command edit mode

Active when the selected command declares arguments and Enter is pressed.

KeyAction
Tab / DownFocus next argument
Shift+Tab / UpFocus previous argument
Printable keyAppend to focused argument
BackspaceDelete last char of focused arg
/ hCycle to previous value (enum args only)
/ lCycle to next value (enum args only)
EnterExecute with current values
EscExit edit mode (keeps values)

Enum-typed args ({:in, [...]} in the Spark schema) render as ‹ value › chevrons and respond to / (or h/l) instead of needing the atom typed literally. For non-enum args, h/l continue to append to the buffer; / are no-ops outside of enum picks. Values are parsed before dispatch: "true"/"false" become booleans, ":foo" an atom, numeric an integer or float, otherwise a string.

Joints panel

KeyAction
j / DownSelect next joint
k / UpSelect previous joint
l / RightIncrease position (1% step)
h / LeftDecrease position (1% step)
LIncrease position (10% step)
HDecrease position (10% step)

Parameters panel

KeyAction
j / DownSelect next parameter
k / UpSelect previous parameter
l / RightIncrease value by one step
h / LeftDecrease value by one step
LIncrease value by ten steps
HDecrease value by ten steps
EnterToggle boolean parameter
tCycle to the next bridge tab (Local → bridges → Local)

Step size is 1% of the declared range when min / max are known — the Spark schema's {:float, min: 0.0, max: 1.0} form on the Local tab, or the bridge's flat :min / :max keys on a bridge tab — and the new value is clamped to the bounds. Parameters without bounds use an absolute step of +1 for integers and +0.1 for floats. The same keys dispatch through BB.Parameter.set on the Local tab and BB.Parameter.set_remote on a bridge tab; a successful remote set refetches that bridge's parameter list so the cached values stay in sync.