Skip to content

Browser component API

The Smithers workbench is a Pattern A composition: every visual surface is its own custom element. This page is the flat list. The narrative version is in Workbench (browser UI).

Tag registration

projects/matrix-3/packages/smithers/src/browser/index.ts:7-49 is the authoritative list:

mx-split                  → MxSplit                (from @open-matrix/core)
smithers-app              → SmithersApp
smithers-topology-rail    → TopologyRail
smithers-source-graph     → SourceGraph
smithers-inspector        → Inspector
smithers-control-palette  → ControlPalette
smithers-runner-panel     → RunnerPanel
smithers-agent-chat       → AgentChat
smithers-constraint-collector → ConstraintCollector
smithers-status-bar       → SmithersStatusBar

All registrations are idempotent (if (!customElements.get(...))).

API summary

<smithers-app>

The root shell. Pattern A — SmithersApp extends MatrixActorHtmlElement directly (SmithersApp.ts:143).

Acceptsapp.refresh
Emitsdeclared at SmithersApp.ts:150-... (force-poll, theme-changed, layout-changed)
Childrenevery other workbench tag, composed via nested <mx-split>

Polls graph.topology-rail and graph.issue-inspector on a user-selectable interval (5s/10s/15s/30s/60s). Subscribes to $activity frames and routes them to AgentChat or RunnerPanel.

<smithers-topology-rail>

The left rail. Reads a TopologyRailProjection from graph.topology-rail. Renders queue counts (ready / blocked / active / escalated), critical-path issues, blocker badges, ratchet count.

<smithers-source-graph>

The center graph. Switches between forest, neighborhood, critical-path, blast-radius, dependency-delta modes via WorkspaceActor.workspace.set-graph-mode. Pulls projections from ConstraintGraph.

<smithers-inspector>

Right-of-graph panel. Six tabs (InspectorTab from src/types/index.ts:43):

overview, constraints, prompts, reviews, diff, session

Each tab is a typed projection from a daemon op:

TabOp
overviewgraph.issue-inspector(N)
constraintsgraph.constraints-for(N)
promptssmithers.workspace.workspace.tree(N) + the gathered prompt
reviewssmithers.review-queue filtered by issue
diffsession trace + applyPatch results
sessionsession transcript from system.agents

<smithers-control-palette>

The action surface. Buttons map directly to supervisor ops:

ButtonOp
Startsmithers.start { issueNumber }
Stopsmithers.stop { issueNumber }
Steersmithers.steer { issueNumber, prompt }
Sign-Offsmithers.sign-off { issueNumber, signOffReport }
Autosmithers.auto { enabled }

<smithers-runner-panel>

Per-runtime status — which workers are online, last heartbeat, container ID. Reads from smithers.containers and smithers.active-agents.

<smithers-agent-chat>

The live $activity stream from the agent's session. Renders text/tool-call/tool-result frames as a chat-like timeline. Re-uses ActivityFrame from @open-matrix/core.

<smithers-constraint-collector>

Approve / dispatch chat constraints. The user types a constraint; it goes through smithers.constraint-approved to add to the projection for a target issue.

<smithers-status-bar>

Top bar. Renders SmithersStatusBarState:

  • Theme toggle (dark/light from SMITHERS_THEME_TOKENS).
  • Poll-interval picker (5/10/15/30/60s).
  • Workstream-request indicator (count of pending requests).
  • Supervisor health pill (from smithers.health).

Layout primitive

<mx-split> from @open-matrix/core/framework/components/MxSplit. Used to compose the four splits:

ts
// SmithersApp.ts:29-34
[
  { childName: 'main-split',   defaultPosition: 22, min: 12, max: 40 },
  { childName: 'source-split', defaultPosition: 70, min: 30, max: 90 },
  { childName: 'work-split',   defaultPosition: 50, min: 20, max: 80 },
  { childName: 'chat-split',   defaultPosition: 60, min: 20, max: 85 },
]

Positions are persisted via WorkspaceActor so they restore on reload.

Theme tokens

SMITHERS_THEME_TOKENS (SmithersApp.ts:44-117) defines dark and light — exhaustive token sets covering surface, text, info/success/warning/danger surfaces, code background, and dividers. Selected via the status bar.

Pattern A reminder

Smithers uses Pattern A, not Pattern B. The shell IS the actor. There is no separated "headless" actor for SmithersApp itself; it owns DOM and logic together. Compare with FlowPad which uses Pattern B (separated FlowpadAppShell + FlowpadApp).

The choice is justified in .claude/rules/webapp-compliance.md: the workbench's logic is mostly plumbing (subscriptions, splits, theme), so separating it would create more boilerplate than it saves.

See also

Source: projects/matrix-3/packages/smithers/src/browser/index.ts:7-49, projects/matrix-3/packages/smithers/src/browser/SmithersApp.ts:1-200, projects/matrix-3/packages/smithers/src/browser/workbench/.