npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@volter/supercode-ui

v0.1.120

Published

Composable default UI kit for Volter Harness-powered coding-agent experiences

Readme

@volter/supercode-ui

Repository reference: UI inventory · feature inventory · ideal Storybook first. These repository guides describe current coverage and proposed components; the API below describes this package. Workflow/task and job/run/delivery components are public, with native projections and a host binding at /supervision. Routing and the other remaining families are tracked in the inventory.

supercode-ui is the composable default interface for Volter Harness's glue workflows: inspect a native coding-agent session, continue it safely, switch harnesses, answer requests, hand it to a terminal, and export it back without hiding fidelity or residue.

It is deliberately separate from both the headless supercode-client and any embedding shell. The package does not inject iframes, open sockets, read native session files, persist credentials, or assume Volter Browsers. A host supplies bounded public state and receives typed intents. This lets a browser widget, editor panel, desktop app, or ordinary page share one capability-honest UI.

Compose a host layout with shared behavior

MessengerProvider owns shared navigation and conversation state. Put MessengerSessions in a persistent sidebar and MessengerContent beside it; the content retains the complete messenger's actions, receipts, recovery, settings, and child-session inspector. useMessenger() exposes navigation and isInspecting/isOpening flags to host controls. The responsive composition story demonstrates single-pane mobile navigation and a persistent sidebar in wider containers.

<MessengerProvider state={state} adapter={adapter} initialView="new">
  <aside className="scui-root"><MessengerSessions /></aside>
  <section className="scui-root">
    <MessengerContent showBack={false} starter={{
      variant: 'starter', environmentLabel: 'This workspace',
      suggestions: ['Explain this workspace', 'Fix the failing test'],
      initialDraft: storedNewDraft, onDraftChange: saveNewDraft,
    }} />
  </section>
</MessengerProvider>

Import these from /preact or /react (or their /messenger subpath). The host supplies layout sizing. The optional centered starter uses the same harness readiness, attachments, execution modes, and submission logic as the complete messenger. Its persisted draft is separate from state.savedDraft, which belongs to the attached conversation. An asynchronous start must settle successfully before the starter clears its draft; merely becoming busy or allocating a new runtime is insufficient.

SessionNavigation and SessionSearchDialog are standalone exports from /preact/sessions and /react/sessions (also included in the main visual entry points). They need no provider or router. Bind their callbacks to useMessenger() when composing a messenger, or to your own navigation. The dialog filters the supplied inventory by default; a host may instead supply results, onQueryChange, loading, error, and onRetry for remote search.

<SessionNavigation canStart={canStart} onNew={startConversation} onSearch={() => setSearchOpen(true)} />
<SessionSearchDialog open={searchOpen} state={state}
  onClose={() => setSearchOpen(false)} onOpen={openConversation} />

The dialog owns Escape handling, focus entry/return, empty results, and reuse of SessionRow. See the navigation stories for complete interactions.

Storybook is the component contract

The package's complete development, documentation, and acceptance surface lives in Storybook: Install its locked development dependencies with npm ci --prefix sdk/ui --ignore-scripts. Mailbox integration stories use the public @volter/teams/session-follow export; the package keeps that dependency in its own manifest so clean release installs can compile the stories.

npm run storybook --prefix sdk/ui
npm run build:storybook --prefix sdk/ui

Acceptance stories import the same built public artifacts that consumers install; workflow/orchestration compositions use native-shaped synthetic fixtures with those public exports. They cover every canonical harness identity, loading phase, transcript primitive, native request, tool lifecycle, long plan, session inventory, composer/continuation state, receipt, narrow messenger layout, and modular override seam. The Chromium interaction and axe accessibility configuration covers stories in light and dark consumer themes; the dated UI review records what was actually executed and the remaining device/integration gaps. The static build is available through build:storybook; see the validation guide for current automation.

The older browser fixture remains a low-level embed smoke test; it is not a parallel design system. New component behavior and hard-to-reach states belong in Storybook first.

Use the whole messenger

import { mountSupercodeMessenger } from '@volter/supercode-ui/embed';
import '@volter/supercode-ui/styles.css';

const mounted = mountSupercodeMessenger(document.querySelector('#agent'), {
  state: initialState,
  adapter: {
    onIntent(intent) {
      host.send(intent);
    },
    async pickContext() {
      return host.pickFilesAndImages();
    },
    openKeyboardShortcuts() {
      panel.showKeyboardShortcuts();
    },
    onClose() {
      panel.close();
    },
  },
});

host.onState((state) => mounted.update(state));

Take only the parts you need

import {
  Conversation,
  SessionList,
} from '@volter/supercode-ui/preact';
import { HarnessLogo, harnessLogoDataUrl } from '@volter/supercode-ui/preact/logo';
import { HarnessAdvisory, HarnessPicker, HarnessSettingsPanel } from '@volter/supercode-ui/preact/settings';
import { groupConversation } from '@volter/supercode-ui/core';

The UI inventory lists all 58 public components, including complete and composable messenger surfaces, transcript primitives, session inventory, composer/context/images, child inspection, settings/readiness, and identity/activity components. Pure state readers, selectors, formatters, and intent constructors live at supercode-ui/core and have no DOM or Preact imports. For genuine partial delivery, the preact/logo, preact/icon, preact/conversation, preact/sessions, preact/composer, preact/settings, and preact/messenger subpaths are independently tree-shaken artifacts; taking the logo does not pull in Markdown, the messenger, or session-list code. harnessLogoDataUrl(id) gives non-Preact launchers the same canonical mark: a self-contained SVG data URL, or the brand's URL for Volter Harness's own ids (supercode, orchestrator); it returns null for an unknown harness rather than inventing a fallback identity.

React and Preact use the same component sources

React applications import the native React build instead of isolating a Preact root or aliasing their application runtime:

import { SupercodeMessenger } from '@volter/supercode-ui/react/messenger';
import type { MessengerComponents } from '@volter/supercode-ui/react';
import '@volter/supercode-ui/styles.css';

const components: MessengerComponents = { SessionRow: ProductSessionRow };
return <SupercodeMessenger state={state} adapter={adapter} components={components} />;

The react, react/logo, react/icon, react/conversation, react/sessions, react/composer, react/settings, and react/messenger exports are generated from the exact same JSX sources as their preact/* counterparts. Consumers install only the renderer they use; both are optional peers, and a React host never loads Preact through the React entry points.

Compact host launcher

Overlay extensions and host applications can use the canonical activity projection without recreating Volter Harness's attention rules:

import { AgentActivityLauncher } from '@volter/supercode-ui/react/activity';

<AgentActivityLauncher state={snapshot} showSummary onOpen={() => openMessenger()} />

projectAgentActivity() is also available from the renderer-free core entry. It selects the highest-priority session (needs-input → failure → working → unread), reports one aggregate unread count, and exposes the selected opaque session key. The default launcher is themeable and allows its badge to overflow without being clipped.

Host navigation and context

Hosts do not need to fork the messenger to connect their own object model:

<SupercodeMessenger
  state={state}
  adapter={{
    onIntent,
    confirmIntent: (intent) => showTakeoverConfirmation(intent),
  }}
  navigation={{
    id: selectedObject.revision,
    view: 'new',
    harness: 'claude-code',
    draft: 'Inspect this selection',
    context: [selectedObject.asTranscriptContext()],
  }}
  composerCommand={{
    id: browserCapture.revision,
    action: 'attach',
    attachments: browserCapture.asTranscriptAttachment(),
  }}
  contextCandidates={visibleObjects.map(asTranscriptContext)}
  components={{ ContextCandidate: ObjectPreview }}
  slots={{
    listHeader: () => null,
    listToolbarActions: NewConversationButton,
    beforeSessions: ProjectThreads,
  }}
/>

navigation is an event, not duplicated router state: change its id to open a conversation or prefill either an existing or new one, while onViewChange observes user navigation. composerCommand is a separate event-like host seam: focus focuses the active composer and attach appends bounded context without replacing its draft or existing attachments. On New Chat, an attachment selects the compatible headless lane when the remembered terminal lane cannot carry structured context. Context candidates use the exact bounded TranscriptAttachment envelope sent to the harness; a custom candidate component changes presentation without inventing a second context protocol. beforeSessions and afterSessions place host-owned rows inside the same searchable scroller. confirmIntent runs before resume, join, branch, reduction, or export so a host can explain ownership and destination before action.

Harness inventory also retains normalized auth, runtime, protocol, repair, and action-capability evidence. The new-chat view renders unavailable harnesses in a compact HarnessReadiness section; hosts can replace that component while continuing to consume the same readiness contract. For an installed Claude Code or Codex that needs authentication, the default component emits the single authenticateHarness intent. A trusted host constructs the client's HarnessAuthenticationController with a visible terminal/process adapter and supplies it to the controller binding as authentication. The shared controller selects the native method, handles timeout/cancellation/verification, refreshes inventory after success, and exposes only sanitized progress to the default component. The browser-only UI never receives a launch command, spawns a local process, or handles credentials itself. onAuthenticateHarness remains a legacy escape hatch for hosts that have not adopted the shared lifecycle.

When a controlled runtime truthfully advertises native steering, the composer sends a plain-text message into the active turn and keeps a separate secondary action for queueing a follow-up. With attachments—or with a harness that cannot steer—the same input remains queued for the next turn. The distinction is capability-gated from the harness adapter through availableActions.steer; the UI never infers steering support from a generic send method.

Bind directly to the headless controller

Trusted desktop, editor, and Node hosts can avoid rewriting ordinary snapshot and action glue:

import { createControllerBinding } from '@volter/supercode-ui/controller';

const binding = createControllerBinding(controller, {
  authentication,
  authenticationRequest: () => ({
    environment: isRemoteClient ? 'headless' : 'local_browser',
    cwd: projectRoot,
  }),
  onDraft: saveDraft,
  onAcknowledge: clearAttention,
  onArtifact: materializeArtifactInTrustedHost,
});

binding.subscribe((state) => mounted.update(state));
mounted.update(binding.getState());

The binding maps standard controller operations, including verified reduce-and-continue, and projects its durable reduction receipt directly. Host-owned session-list pagination, durable attention, drafts, and artifact materialization remain explicit callbacks. Transcript pagination dispatches to the controller by default. A browser should receive projected state from a trusted host rather than instantiate a local controller or gain filesystem authority.

Bind across a process boundary

Browser-hosted products use the transport-neutral host binding instead of recreating snapshot ordering and intent dispatch around the same controller:

import { createRemoteControllerHost, createRemoteUiBinding } from '@volter/supercode-ui/host';

// Trusted process
const host = createRemoteControllerHost(controller);
events.send(host.getFrame());
host.subscribe((frame) => events.send(frame));
http.onIntent((intent) => host.dispatch(intent));

// Browser
const binding = createRemoteUiBinding({
  initialFrame,
  dispatch: (intent) => http.postIntent(intent),
  attention: {
    state: loadAttention(),
    onChange: saveAttention,
  },
});
events.onFrame((frame) => binding.receive(frame));

Each serializable frame carries a host-process identity, workspace generation, monotonic sequence, controller revision, canonical UI state, and stable opaque reconnect identities. The browser store rejects duplicate and stale frames, including delayed action responses from a retired host process. The optional attention tracker baselines initial inventory without inventing unread dots, persists by stable opaque identity, and marks only newer conversation evidence or a proven runtime completion. HTTP, SSE, WebSocket, authentication, and product shell behavior remain host-owned transports.

A native-store inbox can use createNativeSessionAttentionTracker instead. It consumes projected session rows plus their native descriptors, persists opaque message cursors, ignores tool and heartbeat churn, treats compaction as a new baseline, and returns the delay for one host-owned settlement timer. This keeps unread and finished semantics identical in an editor, extension, desktop app, or mobile companion without moving file persistence into the UI package.

createNativeMessengerState wraps that ledger with bounded per-conversation drafts and per-harness Terminal/Headless preferences. It emits one serializable snapshot, so native hosts do not need to duplicate state parsing or coordinate several independent maps. The host still owns where that snapshot is stored, its debounce and encryption policy, and any multi-device synchronization.

Native continuation exposes one action and a quiet execution-transport selector. A host with a real terminal provider can add terminal to continuationModes and handle onResumeTerminal; Terminal is then the initial choice and Headless remains available from the selector. The UI never infers terminal support from a generic runtime handoff, and never presents a terminal transport when the host cannot create one.

New-session execution is advertised per harness. Set launchModes: ['headless', 'terminal'] and preferredLaunchMode on a HarnessOption; the complete messenger renders the same compact Terminal versus Headless selector in the composer footer and emits that mode on the new intent. Direct controller bindings delegate Terminal only through onStartTerminal, so a terminal selection can never accidentally create a second headless runtime. Hosts may remember the preference per harness; the messenger also retains the current browser draft choice while its New Chat view is open.

The default controller projection is display-bounded: 120 visible transcript rows, at most 480 native entries inspected to fill that tail, 16,000 characters per independent entry field, 100 session rows, 20 fidelity-residue details, and 50 subagents. It filters harness-injected context before counting visible rows, retains native timestamps and typed tool/request lifecycles, and keeps the uncapped residue count truthful. Hosts can narrow those limits with ClientProjectionOptions and can overlay a machine-wide session inventory, pagination state, attention, drafts, attachment errors, and owned/attached identities without reimplementing transcript or capability semantics. projectSessionInventory performs the corresponding title, latest-preview, activity, path, age, sorting, and row projection for raw machine-wide descriptors; the trusted host supplies only its opaque-key callback and retains the reversible locator map. Its isWritable capability callback is fail-closed: unread badges remain neutral until the host proves a real send or terminal-control path. Runtime activity remains independent, so a read-only channel can still truthfully show that its external agent is working or needs input. matchesSessionRef, projectAttachedSession, and formatWorkspacePath complete that trusted-host adapter so products do not need local copies of active-session matching, fallback header identity, or home-relative path formatting.

Modularity contract

  • Every component accepts data and callbacks. No component reaches into a global controller.
  • The complete messenger accepts slots for high-level replacement and components for row-level replacement. Replacements receive the same typed, capability-filtered props as defaults.
  • slots.headerActions adds compact product controls to the default list, chat, and new-chat headers without replacing their navigation, status, or accessibility behavior.
  • slots.listHeader can delegate list chrome to the host, while slots.listToolbarActions adds controls beside the package-owned search field without duplicating search state.
  • Every styled element carries a stable scui-<part> class and states as data-* attributes; CSS custom properties are the theme API and className/style/classNames the styling API (see Styling).
  • styles.css contains both neutral tokens and default component rules. Teams may load it whole, override tokens (see Theme tokens), or omit it and style the stable markup themselves.
  • Component state is local presentation state only (navigation, disclosure, search, drafts and scroll position). Machine/session truth always arrives through state.
  • Unknown harness marks are a contract error. HarnessLogo renders nothing and calls onMissingLogo; it never invents initials that disguise an unsupported harness.
  • Expensive transcript details are mounted only when disclosed. The host remains responsible for bounding and paging transcript/session state.

Styling

The package follows the conventions of modern component libraries, so the usual tools work without fighting it.

Cascade layer. Every rule in styles.css sits in @layer scui (scui.tokens, scui.components). Any unlayered CSS of yours wins over it regardless of specificity. With Tailwind v4 (or any layered setup), declare the order once, before your imports, so utilities beat component defaults:

@layer theme, base, scui, components, utilities;
@import "tailwindcss";
@import "@volter/supercode-ui/styles.css";

Keep global element resets layered or scoped: an unlayered button { color: inherit } would override the package's buttons too.

Anatomy. Every styled element carries one part class, scui-<part>, and its state as data-*/aria-* attributes (.scui-session[data-active="true"], .scui-tool[data-status="error"]). Every package rule is one part class plus state, so one class of yours overrides it. parts.d.ts exports ScuiPart, the generated list of every part name.

Props. Every visual component accepts className and style (applied to its root) and classNames, a map from part name to your classes. A map given to MessengerProvider, SupercodeMessenger or any outer component reaches every part rendered beneath it:

<MessengerProvider state={state} adapter={adapter}
  classNames={{ 'message': 'rounded-3xl', 'tool-head': 'text-sm text-zinc-500', 'send': 'bg-black' }}>

Copy and host regions. Every component also accepts labels and slots, and like classNames a map given to an outer component reaches every part beneath it. Labels given to MessengerProvider also reach the settings and subagent parts inside chat. labels overrides any key of a family's defaults, each exported from that family's entry: SUPERVISION_LABELS and NATIVE_MANAGEMENT_LABELS and INVENTORY_LABELS (/preact/supervision), SETTINGS_LABELS (/preact/settings), TEAM_LABELS (/preact/teams), SUBAGENT_LABELS (/preact/subagents), ACTIVITY_LABELS (/preact/activity), and the messenger's DEFAULT_LABELS (the root entry; typed as MessengerLabels), which covers every string of the chat, transcript, session list, composer, image viewer and code blocks, and the error and untitled-chat fallbacks core supplies (presentError, sessionDisplayName, activitySummary and relativeAge take the same labels). The same paths exist under /react. {name} placeholders are filled in, so a translation is plain JSON. Optional copy (eyebrows, subtitles, notes, footnotes) is not rendered when empty. Prefixed keys rename a native word wherever it appears: status:<word> in workflow, jobs and inventory, runtime:<state> and auth:<state> in settings, activity:<state> in subagents, and in chat toolRunning:, toolDone: and toolFailed:<category>, activityOne: and activityMany:<category>, argument:<name>, language:<fence id>, fidelity:<level>, mode:<terminal|headless>, plus the override-only operation:<name>, action:<text>, toolStatus:<status>, trigger:<kind> and crossSurface:<state>. slots adds host content at named regions. Each region is a component of { value }, where value is that region's model:

<WorkflowBoard board={board} layout="board"
  labels={{ searchTasks: 'Filter issues', boardSubtitle: '', 'status:running': 'In progress' }}
  slots={{ laneStart: ({ value }) => <StatusIcon lane={value.lane} />,
           taskEnd: ({ value }) => <Assignee name={value.assignee} /> }} />

Board regions are headerActions, toolbarActions, laneStart and laneEnd. Cards have taskStart and taskEnd, task details have taskDetailsActions and taskDetailsEnd, and each attempt has attemptEnd. Jobs have jobStart, jobEnd, headerActions and toolbarActions. Runs have runStart and runEnd, and run details have runDetailsActions and runDetailsEnd. A host whose slots carry a card's id or status hides the package's rows with --scui-task-meta-display: none and --scui-task-status-display: none.

The other families' regions:

  • Settings: managementHeaderActions (value: the harness list), harnessCardActions and harnessCardEnd (value: a harness), configurationHeaderActions and configurationEnd (value: the report), controlEnd and settingEnd (value: a control), harnessOptionEnd and readinessItemEnd (value: a harness option).
  • Native management forms: formActions and formEnd.
  • Teams: sessionStart and sessionEnd (value: a session), machineStart and machineEnd (value: a machine), machineDetailActions and machineDetailEnd, transcriptHeaderActions, paneActions (value: { machine, pane }), viewHeaderActions (value: { me, team }) and tabsEnd.
  • Source inventory: rowStart and rowEnd on every list, detailActions and detailEnd on every detail view, and approvalActions.
  • Subagents: subagentHeaderActions and subagentEnd.

The messenger's own regions are its slots (including sessionStart and sessionEnd inside each session row) and components.

Tokens. Colors, type, radii, shadows, controls and per-component values are custom properties; see Theme tokens. --scui-scaling multiplies all spacing and control sizes (0.85 is IDE-dense, 1 the default, 1.15 roomy).

Containers. Each .scui-root is the named container scui: components adapt to the width they are given, not the viewport, and your CSS can do the same with @container scui (...). A size container takes its width from its parent, never its content: the root's width is --scui-width (420px by default) capped at 100%; set --scui-width: 100% to fill a pane, and give a shrink-to-fit parent (a centered flex item, width: fit-content) a width of its own.

Unstyled. Omit styles.css and style the part classes yourself; markup and behavior do not depend on it.

examples/web restyles one shell as Claude, ChatGPT and VS Code's Chat view, and frames every family as GitHub, Linear, Jira and Vercel, with token files only; Storybook's Look toolbar renders every story in each.

Upgrading a host to the styling anatomy

  • Element resets. Package rules are now layered, so an unlayered button { … } or .shell button { … } in your CSS overrides package controls. Move element-level defaults into a layer declared before the package: @layer app-base, scui; then @layer app-base { button { … } }. Your class rules can stay unlayered.
  • Modifier classes became attributes: scui-starter → .scui-chat[data-variant="starter"], scui-new-starter → .scui-new[data-variant="starter"], scui-drop-target → .scui-envelope[data-dropping="true"], scui-pending → .scui-message[data-pending="true"], scui-loading-compact → .scui-loading[data-compact], scui-domain-positive|danger|warning → .scui-domain-badge[data-tone], scui-domain-has-detail → .scui-domain-workspace[data-detail].
  • Palette. Tokens inherit from any ancestor; setting them on each .scui-root still works but is no longer needed.
  • Root width. .scui-root is a size container with width --scui-width (420px) capped at 100%; set --scui-width: 100% to fill a pane.
  • Header actions. Buttons you pass through slots.headerActions take the package look with className="scui-icon-button".

Theme tokens

A theme is a set of custom-property assignments on any ancestor of the components (or on the .scui-root itself). No token is re-declared inside the package, so a value set anywhere up the tree reaches every component, and one theme can restyle a whole product without a selector override. examples/web restyles the same shell as Claude (/claude) and ChatGPT (/chatgpt) with token files only.

Defaults are the Volter brand's roles. Every colour, shadow and font default is one of the Volter brand's roles, read as var(--volter-<role>, <brand value>): --scui-bg is var(--volter-surface-page, light-dark(…)), --scui-accent is --volter-action-default, --scui-font is --volter-font-ui. A host that sets --volter-* (a Volter product loading the brand's tokens.css) governs every default at once, a host that sets --scui-* overrides the one it sets, and a page that sets neither gets the brand's own values. The brand values are resolved when the package is built; the stylesheet fetches nothing.

| Primitive | Brand role | |---|---| | --scui-bg, -bg-raised, -fill | surface.page, surface.raised, surface.subtle | | --scui-fg, -muted | text.primary, text.muted | | --scui-border, -border-strong | border.default, border.strong | | --scui-accent, -accent-fg | action.default, text.onStrong | | --scui-positive, -warning, -danger | status.healthy.base, status.attention.base, status.danger.base | | --scui-shadow-sm, -md, -lg | shadow.floating, shadow.floating, shadow.dialog | | --scui-font, -font-mono | font.ui, font.data |

Harness logos for third-party agents keep their vendors' colours.

Primitives (declared on :root, override any of them):

  • Palette: --scui-bg, --scui-bg-raised, --scui-fill, --scui-fg, --scui-muted, --scui-border, --scui-border-strong, --scui-accent, --scui-accent-fg, --scui-positive, --scui-warning, --scui-danger. Defaults use light-dark(), so one declaration covers both schemes.
  • Scheme: components use color-scheme: var(--scui-color-scheme, light dark), following the OS by default. Set --scui-color-scheme: dark (or light) to force one, or inherit to follow the host's own color-scheme.
  • Type: --scui-font, --scui-font-mono, --scui-line-height, and the scale --scui-text-2xs, -xs, -sm, -md, -lg, -base (the root size), -xl, -2xl, -3xl, -4xl, -5xl.
  • Shape: --scui-radius-xs, -sm, -md, -lg, -xl, -2xl, -pill; --scui-shadow-sm, -md, -lg.
  • Spacing: --scui-scaling multiplies every padding, gap and control size (default 1).
  • Frame: --scui-width, --scui-height, --scui-radius, --scui-root-border, --scui-head-height, --scui-intrinsic-width (the width a root measures inside a shrink-to-fit parent).

Component tokens are never declared; each is read with its default as a fallback where it is used, so an unset one tracks the primitives wherever those are overridden:

| Surface | Tokens | |---|---| | Controls | --scui-button-bg, -fg, -border, -radius; --scui-icon-button-radius; --scui-press-transform (buttons, icon buttons and session rows while pressed, e.g. translateY(1px)); --scui-input-bg, -border, -radius; --scui-primary-bg, -fg (shared parts scui-button[data-variant], scui-icon-button, scui-input) | | Page titles | --scui-heading-font, --scui-heading-weight (workflow, orchestration, source, agent and harness views) | | Surfaces | --scui-card-radius (cards, request, tool detail, plan, domain panels); --scui-popover-radius, -shadow (menus, pickers, image viewer) | | Header | --scui-head-bg, -border, -padding, -title-size, -title-weight, -logo-display, -subtitle-display, --scui-head-display (none hides a header, e.g. a session list set inside a host panel) | | Conversation | --scui-conversation-width (column max width), --scui-conversation-padding, --scui-turn-gap | | Assistant prose | --scui-prose-font, -size, -line-height, -gap, -fg, -heading-font, -heading-weight | | User message | --scui-user-bg, -fg, -border, -radius, -padding, -max-width, -align, -font, -size, -line-height | | Timeline | --scui-message-display (grid lays each message out as columns), --scui-message-columns, -column-gap; --scui-message-actor-display (shows the time-and-speaker cell, worded by the actor:user and actor:assistant labels), -actor-columns, -actor-dot, -actor-dot-bg, -actor-user-dot-bg; --scui-entry-inset (tool groups, reasoning and plans line up under the content column) | | Tool rows | --scui-tool-head-padding, --scui-tool-actor-width, -actor-gap (the tool's timeline cell, shown with --scui-message-actor-display and worded by the actor:tool label), --scui-message-actor-tool-dot-bg; --scui-tool-icon-display, -status-display, -chevron-display; --scui-tool-detail-inset, -detail-border, -detail-max-height; --scui-tool-metrics-display, -fields-display, -actions-display, -technical-display (each none hides that part of an opened tool); --scui-tool-output-bg, -output-padding, -output-max-height; --scui-terminal-bg, -gap, -head-bg, -head-border, -head-padding, -lights-display, -command-fg. With groupTools={false} on the messenger each tool call is its own row, and expandTools opens their details. | | Code | --scui-inline-code-bg, -fg, -border, -radius, -padding; --scui-code-bg, -fg, -border, -radius, -size, -head-bg, -head-border | | Requests | --scui-request-bg, -border, -padding, -shadow, -allow-bg, -allow-fg (options carry data-kind) | | Reply actions | --scui-reply-actions-position (static puts copy/time as a row under each assistant reply), -top, -opacity, -pointer-events, -bg, -border, -shadow, -padding, -gap, -justify, -width; --scui-message-time-display, --scui-message-action-size, --scui-message-action-icon-size | | Tools | --scui-tool-size, -weight, -fg; --scui-tool-target-size, -bg, -fg, -padding, -radius (the command or path chip) | | Composer | --scui-compose-bg, -border, -padding, -width; --scui-composer-size; --scui-envelope-bg, -border, -radius, -padding, -shadow; --scui-send-bg, -fg, -radius, -size; --scui-stop-bg | | Starter | --scui-starter-flow (row wrap puts the mark beside the title), --scui-starter-mark-gap, --scui-starter-hint-basis, --scui-starter-bg, -title-font, -title-size, -title-weight, -title-tracking, -mark-display, -mark-color, -mark-size, -hint-display | | Session rows | --scui-list-toolbar-display (none hides the search bar), -gap, -padding; --scui-search-height, -padding, -gap, --scui-search-flex (0 0 34px collapses search to its icon until focused), --scui-session-radius, -bg, -border, -spacing (the gap below each row), -shadow (e.g. an inset rule between rows), -padding, -align, -title-size, -title-weight, -active-bg, -hover-bg, -list-padding, -logo-display, -logo-size, -path-display, -preview-display, -rail-display | | Workflow and jobs | --scui-domain-bg, -border, -radius, -title-size, -header-display, -header-padding, -schedule-padding (a job's schedule strip), -toolbar-display, -toolbar-padding, -toolbar-border, -toolbar-align, -search-columns (auto minmax(0,1fr) sets the search label beside its field), -search-size (search and filter labels), -control-height (buttons, selects and search fields), -meta-size (subtitles, card meta and footnotes), -heading-size (task, job and run titles in their details), --scui-focus-target-outline (the ring on a heading, list or panel focused as it opens), -switch-display, -collection-padding, -detail-border, -detail-border-top, -detail-bg, -detail-columns (minmax(0,1fr) puts task and run details below the list); --scui-eyebrow-transform, -tracking; --scui-board-gap; --scui-lane-bg, -border, -radius, -padding, -min-height, -title-font, -title-size, -title-weight, -title-fg, -title-transform, -title-tracking, -title-justify, -title-gap, -title-padding; --scui-lane-count-bg, -fg, -radius, -padding, -size, -weight; --scui-task-bg, -border, -radius, -shadow, -padding, -gap, -spacing, -hover-bg, -flow (column lays a card out as one row), -columns, -align, -title-order (-1 puts the title first), -title-size, -title-weight, -title-fg, -meta-display, -status-display; --scui-badge-bg, -border, -radius, -padding, -size, -weight, -transform, -dot-display; --scui-run-padding, -border | | Settings panels | --scui-panel-width (100% stretches them in a flex host), -padding, -max-width, -margin; --scui-harness-card-bg, -border, -radius, -padding, -gap; --scui-harness-management-title-size; --scui-configuration-form-bg, -form-border, -form-radius, -form-padding, -title-size, -label-font, -label-size, -label-weight, -label-tracking, -label-transform; --scui-settings-header-bg, -header-border | | Subagents | --scui-subagent-bg, -row-bg, -row-radius, -row-hover-bg, -history-border | | Source inventory | --scui-inventory-row-bg, -border, -radius, -padding, -gap, -title-size; --scui-inventory-nav-gap, -padding, -border, -bg, -active-bg, -active-weight | | Teams | --scui-team-* for every surface of the team view: bar (-bar-height, -bar-bg, -bar-border, -title-size, -bar-copy-display: none hides the team name and role for a host that shows them), tabs (-tab-height, -tab-radius, -tab-active-bg, -tab-active-color), rows (-session-padding, -machine-padding, -row-radius, -row-hover-bg, -row-active-bg), presence dots (-dot-size, -dot-online-bg), transcript badges (-live-bg, -coverage-bg), detail panels (-panel-bg, -panel-border, -panel-radius), sign-in (-sign-in-width, -sign-in-radius) and the pane terminal (-terminal-bg, -terminal-border, -terminal-radius); the full list is in src/styles/teams.css |

Starter copy is a label: labels.starterMark (the glyph; '' shows none), labels.starterTitle, labels.starterHint and labels.startPlaceholder join askAgent and the other MessengerLabels.

Host boundary

SupercodeUiState is a transport-safe view model, not a duplicate controller. A trusted host maps SupercodeController snapshots and persisted inventory into it, then handles SupercodeUiIntent. An iframe or extension host can pass unknown payloads through parseSupercodeUiIntent before using dispatchControllerIntent; transport-specific operations can be intercepted with handleIntent while ordinary controller semantics continue through the shared dispatcher. The browser cannot supply locators, credentials, policy, environment variables, or arbitrary materialization paths. Session keys and target harnesses must be revalidated by the host. Harness configuration is similarly narrow: the UI can only submit a choice from the revisioned interoperability-control report it received. The headless controller rejects configuration unless the trusted embedding host explicitly opts into allowHarnessConfiguration, revalidates the active harness, control key, declared choice, reset capability, and revision, then asks the local service to update the native file atomically. The UI shows the scope, precedence uncertainty, and security consequence before it emits that intent; it is not a generic preferences editor. pickContext is optional and host-owned: the default composer shows one attachment control when this callback exists and accepts either typed text context (detail) or native image inputs (url). Images can also be pasted or dropped directly, and an image-only turn is sent without inventing fallback prompt text. The composer bounds images to four supported browser formats at 5 MB each, previews them locally, and keeps both attachment kinds associated with queued messages, retry, edit, and new-chat recovery. The host still chooses how explicit file selection is exposed and must revalidate every returned item.

openKeyboardShortcuts is also optional and host-owned. When present, the default conversation overflow includes a Keyboard shortcuts item without consuming permanent header width.

Transcript images with a browser-safe URL open in a keyboard-accessible, viewport-bounded viewer; remote images expose copy-link and open-original actions, while local data images can be downloaded. createClientProjection keeps large historical data URLs in a projection-scoped host registry and puts only stable metadata plus an opaque reference in SupercodeUiState. RemoteControllerHost uses that same projection and exposes host.resolveImage(reference) for the current frame; a new projection or closing the host retires the previous registry. An embedding host may implement adapter.resolveImage to fetch that reference only after a click and return a bounded Blob; the viewer owns and revokes the resulting object URL and presents loading, failure, and retry states. Without that adapter—or when native data is incomplete—the attachment remains an honest unavailable-preview state rather than a broken thumbnail or deceptive action.

An embedding product such as Vibewaiting should therefore be small: Volter Browsers owns its iframe and launcher lifecycle, Volter Harness owns this UI and the controller semantics, and Vibewaiting only bridges state/intents plus host-specific theme and persistence policy.

Native supervision (0.1.72)

Independent workflow, job/run, configuration inventory and approval compositions are available from ./preact/supervision and ./react/supervision. Their bounded projections and native host adapters live in ./supervision. These do not need a conversation controller. A host supplies source scopes and native SDK clients.

createSupervisionHost binds job discovery, profile-scoped run history and confirmed pause, resume, run requests and deletion for Hermes, OpenClaw and the orchestrator. createSourceInventoryHost reads profiles, channels, routes, triggers, skills and memory; it does not turn instance-wide native readers into per-profile readers. createApprovalHost requires the existing native connection and session, re-reads a pending choice, and requires a matching decision receipt. Configuration inventories are read-only. JobControls requires explicit host capabilities and keeps run-request receipts distinct from completed runs.

The public parts include JobList, OrchestrationJobs, SourceInspector and ApprovalInbox; see the source inventory and supervision parts stories. Native unknowns, discovery failures and delivery failures remain distinct states.

Validation: package build, TypeScript checks and 49 headless tests pass, including colliding job IDs across orchestrator profiles and confirmation of a paused job. Volter Desktop separately exercised these components in normal Chrome and native job creation/history/pause against a disposable orchestrator home. This does not claim full scheduling migration, write editors, or live permission round-trip coverage.

Standalone agent configuration

AgentConfigurationPanel from /react/settings or /preact/settings renders reports from the SDK's Node-only /configuration host. Supply report, loading, saving, error, onRefresh and onChange({ key, value }). The host owns paths, revision checks and native commands; the component owns field types, read-only states, per-control Save/Reset, scope and verified-save feedback. It needs no chat controller or open conversation. Its Storybook stories cover shared settings, unavailable adapters and failed saves.

Harness readiness and native sign-in

HarnessManagement from /react/settings or /preact/settings renders the existing picker sign-in controls as a standalone view. Pass the shared controller UI state, redacted native authentication reports, optional selected-harness label, and host callbacks for refresh, cancellation and opening the sign-in terminal. Sign-in emits the existing authenticateHarness intent. Native reports control availability; unsupported adapters never receive an invented sign-in flow. The host runs HarnessAuthenticationController with its own terminal execution adapter. Neither native launch plans nor terminal output belong in browser state.

Native management components

The Preact and React supervision entries export NativeSetupControls, SkillInstall, MemoryEditor and JobScheduleForm. Hosts pass trusted scoped callbacks; the components render native receipts, failures and conflicts. AgentConfigurationPanel accepts guarded profile deletion, SkillDetails accepts confirmed removal, and MemoryBrowser can open a full native document. createSourceInventoryHost supplies native skill install/remove and full memory access; writable memory is an explicit host adapter. Skill operations allow up to two minutes for native fetch/scan/readback and retain errors when not confirmed.

Schedule forms emit native cron/time-zone, interval or one-time definitions. Run models can include a separate completion receipt so callback execution and agent turn completion remain distinct. The messenger header reports connection or error state before presenting a ready label. Unsupported native capabilities remain explicit; these components do not implement a harness or scheduler.

Workflow, orchestration and the example app

Import WorkflowBoard, TaskDetails, OrchestrationJobs, JobList, RunDetails and their standalone parts from /react/supervision or /preact/supervision. The renderer-free /supervision entry exports projectWorkflow, projectJobs, projectRuns and createSupervisionHost. Projections preserve native status words, separate execution from delivery, omit absent session links, and bound data. The trusted host owns native homes and ids; components receive opaque keys and callbacks. The workflow read door supplies no mutation API. A pause result must include the matching, authoritatively disabled job; consumers update their job state from that receipt.

WorkflowBoard starts in initialLayout (list by default). A host whose own view tabs choose board or list passes layout and hears onLayoutChange, and usually hides the board's header and switch with --scui-domain-header-display: none and --scui-domain-switch-display: none.

The example webapp imports these public components and the session messenger. Its shell supplies routing, responsive pane placement, browser history, themes and connection adapters. Demo data is explicitly labeled. Connected mode observes native sessions and supports opt-in job pause; it is not a runtime-control or remote-hosting product.

SourceInspector composes ProfileList/ProfileDetails, ChannelList, RouteList, TriggerList, SkillList/SkillDetails and MemoryBrowser. createSourceInventoryHost binds configured native sources to independent read outcomes and literal memory search. A failed section does not become an empty success. Counts and previews are bounded; native filesystem locations stay on the host. Use section, selectedKey and onNavigate to connect an app router, or let the component own selection.

ApprovalInbox/ApprovalDetails accept native request options. createApprovalHost requires a caller-owned client plus an explicit harness/session, rereads the request before resolving, and validates the returned native decision. Resolution is opt-in. This does not edit an access policy. OrchestrationOverview and AdapterStatus render projectRuntimeState output from a supplied orchestrator state observation. They neither start a runtime nor infer live health from config. All these exports are available through the same React/Preact supervision entry points.