Commands

Register commands that users can discover and trigger from a command palette.

Press Ctrl/Cmd+K to open the palette, then search for commands by name. (Ctrl/Cmd+Shift+P also works on browsers that don’t reserve it, e.g. everything except Firefox.) Commands can also be bound to keyboard hotkeys.

Key methods:

Features demonstrated:

  • Registering commands with labels, descriptions, icons, and hotkeys

  • Fuzzy search filtering in the palette

  • Dynamic command updates (label, description, icon changes)

  • Removing commands at runtime

Source: examples/02_gui/10_commands.py

Commands

Code

  1import time
  2
  3import viser
  4
  5
  6def main() -> None:
  7    server = viser.ViserServer()
  8
  9    # Basic command.
 10    hello_cmd = server.gui.add_command(
 11        "Say Hello",
 12        description="Show a greeting notification",
 13        icon=viser.Icon.MESSAGE,
 14    )
 15
 16    @hello_cmd.on_trigger
 17    def _(event: viser.CommandEvent) -> None:
 18        assert event.client is not None
 19        event.client.add_notification(
 20            title="Hello!",
 21            body="You triggered the Say Hello command.",
 22            color="teal",
 23        )
 24
 25    # Command with a hotkey.
 26    reset_cmd = server.gui.add_command(
 27        "Reset Camera",
 28        description="Move the camera back to the default view",
 29        hotkey="R",
 30        modifier="cmd/ctrl+shift",
 31        icon=viser.Icon.REFRESH,
 32    )
 33
 34    @reset_cmd.on_trigger
 35    def _(event: viser.CommandEvent) -> None:
 36        assert event.client is not None
 37        event.client.camera.position = (3.0, 3.0, 3.0)
 38        event.client.camera.look_at = (0.0, 0.0, 0.0)
 39        event.client.add_notification(
 40            title="Camera Reset",
 41            body="Camera position has been reset.",
 42            color="blue",
 43        )
 44
 45    # Toggle command (changes label/icon on each trigger).
 46    grid_visible = True
 47    grid_handle = server.scene.add_grid("/grid", width=10.0, height=10.0)
 48
 49    toggle_cmd = server.gui.add_command(
 50        "Hide Grid",
 51        description="Toggle grid visibility",
 52        icon=viser.Icon.EYE_OFF,
 53    )
 54
 55    @toggle_cmd.on_trigger
 56    def _(event: viser.CommandEvent) -> None:
 57        nonlocal grid_visible
 58        grid_visible = not grid_visible
 59        grid_handle.visible = grid_visible
 60
 61        if grid_visible:
 62            toggle_cmd.label = "Hide Grid"
 63            toggle_cmd.icon = viser.Icon.EYE_OFF
 64        else:
 65            toggle_cmd.label = "Show Grid"
 66            toggle_cmd.icon = viser.Icon.EYE
 67
 68    # Removable command.
 69    counter = 0
 70    removable_cmd = server.gui.add_command(
 71        "Self-Destruct",
 72        description="This command removes itself after being triggered",
 73        icon=viser.Icon.BOMB,
 74    )
 75
 76    @removable_cmd.on_trigger
 77    def _(event: viser.CommandEvent) -> None:
 78        nonlocal counter
 79        counter += 1
 80        assert event.client is not None
 81        event.client.add_notification(
 82            title="Boom!",
 83            body=f"Triggered {counter} time(s). Removing command...",
 84            color="red",
 85        )
 86        removable_cmd.remove()
 87
 88    server.scene.add_frame("/frame", show_axes=True, axes_length=2.0)
 89    toggle_cmd_disabled = server.gui.add_button("Toggle grid command disabled")
 90
 91    @toggle_cmd_disabled.on_click
 92    def _(_) -> None:
 93        toggle_cmd.disabled = not toggle_cmd.disabled
 94
 95    while True:
 96        time.sleep(1.0)
 97
 98
 99if __name__ == "__main__":
100    main()