Skip to content

Service row

ui.ServiceRow is a component for one thing an AI agent uses (an MCP server, an external agent, a skill) on a settings page: an icon, the name with its version and a status dot, the detail (its command or URL, in a monospace font) and a summary; then a spinner while busy, a main button (primary, such as Update or Install), an on/off switch (enabled; None hides it) and a ⋯ menu with the actions (ui.MenuItem). status colors the dot: running and installed green, starting yellow, update in the accent color, error red, off and missing gray. status_text is the dot’s tooltip, and it shows under the name for error, missing and update.

ui.ServiceRow · Category: AI agents · Full reference →

Service rowService row
  • In the settings of an app with AI agents: one row per MCP server, agent or skill.
  • For any list of services that can be turned on and off, updated or removed.
import pyzed as pz
from pyzed import ui
class Settings(pz.App):
def __init__(self):
self.on = True
def view(self):
return ui.ServiceRow(name="github", detail="npx -y @modelcontextprotocol/server-github",
status="running" if self.on else "off", enabled=self.on,
on_toggle=lambda e: setattr(self, "on", e.value),
actions=[ui.MenuItem("Remove", self.remove, icon="trash-2", danger=True)])

enabled=False also dims the name and the icon.

Service row: status="running"Service row: status="running"
status="running"
Code
pz.container(ui.ServiceRow(name="github", detail="npx -y server-github", status="running",
enabled=True), width=420)
Service row: status="starting"Service row: status="starting"
status="starting"
Code
pz.container(ui.ServiceRow(name="github", detail="npx -y server-github", status="starting",
enabled=True), width=420)
Service row: status="error"Service row: status="error"
status="error"
Code
pz.container(ui.ServiceRow(name="github", detail="npx -y server-github", status="error",
status_text="Exited with code 1", enabled=True), width=420)
Service row: status="off"Service row: status="off"
status="off"
Code
pz.container(ui.ServiceRow(name="github", detail="npx -y server-github", status="off",
enabled=False), width=420)
Service row: status="installed"Service row: status="installed"
status="installed"
Code
pz.container(ui.ServiceRow(name="Gemini CLI", version="0.64.0", icon_name="bot",
status="installed"), width=420)
Service row: status="missing"Service row: status="missing"
status="missing"
Code
pz.container(ui.ServiceRow(name="Codex CLI", icon_name="bot", status="missing",
status_text="Not installed yet", primary="Install"), width=420)
Service row: status="update"Service row: status="update"
status="update"
Code
pz.container(ui.ServiceRow(name="Gemini CLI", version="0.64.0", icon_name="bot", status="update",
status_text="0.65.0 is available", primary="Update"), width=420)

The ⋯ menu is drawn open, as after a click on it.

Service row: summary=Service row: summary=
summary=
Code
pz.container(ui.ServiceRow(name="notes", icon_name="book-open", status="running",
summary="Reads and writes the notes folder."), width=420)
Service row: busy=TrueService row: busy=True
busy=True
Code
pz.container(ui.ServiceRow(name="Gemini CLI", version="0.64.0", icon_name="bot", busy=True,
primary="Update"), width=420)
Service row: actions=[...]Service row: actions=[...]
actions=[...]
Code
pz.container(ui.ServiceRow(name="github", detail="npx -y server-github", status="running", enabled=True,
actions=[ui.MenuItem("Edit", on_edit, icon="pencil"),
ui.MenuItem("Remove", on_remove, icon="trash-2", danger=True)]),
width=420)

Service row has 2 events of its own, listed below. Like every widget it also has the 18 common events (click, double_click, right_click, mouse_enter, drag, key_down, resize…), attached with .on(...): see Events and Events of every component.

It is a pz.Component, so it also raises on_mount and on_unmount, and its handlers get a pz.Event whose value holds the data.

Event Handler gets When
on_toggle (event) The switch was flipped.
on_primary (event) The main button was pressed.

Handler gets is what Pyzed passes to your callable: () means nothing. Any handler can also be a message (a value that is not callable), which goes to update().

The same events written three ways. Imperative: methods of the app change self. Declarative: the handlers produce messages and one update() decides. Functional: a pure function draws an immutable state and asks for changes with set_state(...). See Imperative, declarative and functional.

class Settings(pz.App):
def __init__(self):
self.on = True
self.updates = 0
def view(self):
return ui.ServiceRow(name="github", status="running" if self.on else "off", enabled=self.on,
primary="Update",
on_toggle=lambda e: setattr(self, "on", e.value), # the switch
on_primary=lambda e: setattr(self, "updates", self.updates + 1))
class ServiceRow

A component for one thing an agent uses (an MCP server, an external agent, a skill), like the rows of Zed’s agent settings: a status dot, the name and command, an on/off switch, a main button and a ⋯ menu.

Property Default Description
name "" Name.
detail "" The command or URL, in a monospace font.
summary "" A line about it.
icon_name "plug" The icon.
status "" running, starting, error, off, installed, missing or update (the dot’s color).
status_text "" The dot’s tooltip; shown under the name for errors and updates.
version "" A version or a source.
enabled None The switch (None hides it).
busy False Shows a spinner.
primary "" Text of the main button (Update, Install…).
actions None ui.MenuItem entries of the ⋯ menu.
theme None Theme.

Events: on_toggle, on_primary (events).

Full reference →