Skip to content

ctx.workspaces

Read and drive workspace state through WorkspaceService — create/rename/close workspaces, manage their folders, and subscribe to a frozen snapshot. (Opening editor tabs lives on ctx.editors, not here.)

ts
ctx.workspaces: WorkspaceService

Example

tsx
import { useServiceState } from "@silo-code/sdk";

// read workspace state reactively in a component
function OpenCount() {
  const state = useServiceState(ctx.workspaces);
  return <span>{state.open.length} open</span>;
}

// or observe changes imperatively
const sub = ctx.workspaces.subscribe((state) => {
  console.log(state.open.length, "open workspaces");
});

Methods

On ctx.workspaces. Method names link to the full signature.

MethodWhat it does
getState()Current frozen WorkspaceState.
subscribe(listener)Observe changes; returns a Disposable.
get(id)One-shot lookup of a workspace by id (for reactive reads, prefer the state).
create(input)Create a workspace from a folder + name.
createFromFolderPicker()Show a folder picker, then create.
rename(id, name)Rename a workspace.
reorder(from, to, position)Reorder workspaces.
activate(id)Activate (and reopen if closed).
close(id)Soft close — hidden but still saved.
reopen(id)Reverse of close.
delete(id)Hard delete — permanent removal (also reaps the workspace's terminals).
addFolder(id, folder)Add an extra folder to a workspace.
removeFolder(id, folder)Remove an extra folder.

State

The readable state — a frozen WorkspaceState from getState(), subscribe, or useServiceState:

PropertyTypeWhat it is
allreadonly Workspace[]every workspace, in user order
openreadonly Workspace[]open workspaces (not closed)
closedreadonly Workspace[]closed workspaces, most-recent first
activeIdstring | nullid of the active workspace
hydratedbooleantrue once persisted state has loaded

Workspace status

Ephemeral status rows below each workspace's path line (adorn verbs — see ADR 0029 / ADR 0030). bindStatus returns an array of rows per workspace (unlike tab bindActivity, which returns a single adornment or null).

Each row may include an Activity (working | ready | warn | error). Omit activity for the neutral gray fallback.

ts
ctx.subscriptions.push(
  ctx.workspaces.bindStatus({
    id: "my-ext.status",
    provide(workspaceId) {
      return getRunningTasks(workspaceId).map((t) => ({
        id: t.id,
        activity: "working",
        label: t.name,
        startedAt: t.startedAt,
      }));
    },
  }),
);

// Or imperatively:
ctx.workspaces.setStatus(workspaceId, {
  id: "one-shot",
  activity: "ready",
  label: "Ready",
});
ctx.workspaces.clearStatus(workspaceId, "one-shot");
MethodWhat it does
setStatus / clearStatusImperative rows
bindStatusKeep a projection in sync (provide → array)
registerStatusDeprecated shim → bindStatus
getStatusImperative + binder rows
invalidateStatusRe-query binders
subscribeStatusListen for changes

Each row is a WorkspaceStatusRow.

Workspace sections

Extensions can mount an arbitrary React component inside each workspace row — below the path line and any status rows. Sections are useful for richer surfaces: interactive cards, agent-status summaries, call indicators, etc.

Return null from your component for workspaces where the section should not appear. This produces no DOM node and no visual gap.

tsx
ctx.subscriptions.push(
  ctx.workspaces.registerSection({
    id: "my-ext.section",
    component: ({ workspaceId }) => {
      const ws = ctx.workspaces.get(workspaceId);
      if (!ws?.terminals.length) return null;
      return <MyCard terminals={ws.terminals} />;
    },
    order: 0, // lower = higher in the stack, default 0
  }),
);

Multiple providers from different extensions stack vertically in ascending order. Each component is responsible for its own top margin/padding and must use only --silo-* design tokens.

MethodWhat it does
registerSection(provider)Register a React component to mount in workspace rows. Returns a Disposable.
subscribeSection(listener)Subscribe to provider registration changes. Returns a Disposable.

The provider shape is WorkspaceSectionProvider; component props are WorkspaceSectionProps.

Workspace badges

Inline badges next to the workspace name (same adorn verbs as status).

ts
ctx.subscriptions.push(
  ctx.workspaces.bindBadge({
    id: "my-ext.badges",
    provide(workspaceId) {
      const env = getEnv(workspaceId);
      if (!env) return [];
      return [{ id: "env", text: env.label, color: env.color }];
    },
  }),
);

ctx.workspaces.setBadge(workspaceId, {
  id: "ci",
  text: "fail",
  color: "#f87171",
});
ctx.workspaces.clearBadge(workspaceId, "ci");
MethodWhat it does
setBadge / clearBadgeImperative badges
bindBadgeKeep a projection in sync
registerBadgeDeprecated shim → bindBadge
getBadgesImperative + binder badges
invalidateBadgesRe-query binders
subscribeBadgesListen for changes

Each badge is a WorkspaceBadge.

Workspace property pages

Extensions can contribute a tab to the workspace properties modal — the right place for per-workspace configuration (persistent settings the user adjusts through forms). The modal always shows a tab bar: the built-in General tab (name, folders) first, then registered pages in ascending order.

Persist the page's settings via ctx.storage.workspace, immediately on change — the modal has no Save button. For one-shot actions (refresh, clear) prefer a workspace context-menu item instead; property pages are for configuration.

tsx
ctx.subscriptions.push(
  ctx.workspaces.registerPropertyPage({
    id: "my-ext.properties",
    title: "My Extension",
    component: ({ ws }) => (
      <MySettingsForm
        value={readSettings(ws.id)}
        onChange={(next) => writeSettings(ws.id, next)}
      />
    ),
    visible: (ws) => isRelevant(ws), // hide the tab where it doesn't apply
  }),
);
MethodWhat it does
registerPropertyPage(page)Register a tab in the workspace properties modal. Returns a Disposable.

The page shape is WorkspacePropertyPage; component props are WorkspacePropertyPageProps.

Types

Pass WorkspaceService.

Related: WorkspaceState · WorkspaceStatusRow · WorkspaceStatusProvider · WorkspaceSectionProvider · WorkspaceSectionProps · WorkspaceBadge · WorkspaceBadgeProvider · WorkspacePropertyPage · WorkspacePropertyPageProps · CreateWorkspaceInput · OpenFileOptions.

See also

Other State members on ctx.