Omniscio documentation
Browse all documentation
  1. Getting Started13
  2. Sessions & Agents115
  3. Inbox & Notifications59
  4. Projects & Tasks95
  5. Automation & Scheduling75
  6. Knowledge & Memory26
  7. AI Features60
  8. Integrations100
  9. Plugins & Marketplace33
  10. Cloud & Teams56
  11. Settings & Customization58
  12. Account & Billing28
  13. Troubleshooting84
  14. CLI & API Reference22
  15. Legal & Policies4
  16. Uncategorised22

Header widgets

The named controls in Omniscio's titlebar: clicking one either acts directly or opens a small popover. Which widgets ship, how to rearrange them by dragging, and how a plugin contributes one of its own.

What it is

Header widgets are the named controls in Omniscio's top titlebar. Clicking a widget either triggers an action directly or opens an inline popover panel.

The header's right side is a drag-to-reorder row of blocks. The Shortcuts block is the rounded pill of pinned toolbar icons (which still reorder inside the pill). The account (Balancer) and hardcore widgets are pulled out of the pill and render as standalone bare blocks (no pill background) alongside it. The user drags blocks left/right to arrange them; the arrangement persists in headerBlockOrder.

Header widgets are not hardcoded — they live in the toolbar registry and render through the same pinned-item path (ToolbarPinnedItem) as every other toolbar control, so users own their header layout completely.

Where to find it

The named widgets

Widget Label What it does
account Account Opens the account-switcher popover — shows usage, lets the user switch or add accounts, and links to Settings → Accounts. Always visible.
hardcore Hardcore Mode Shows the skull icon and look count while hardcore mode is both revealed and switched on. Hidden automatically when the mode is off.
cpu-burst CPU Burst Performance mode toggle. Visible only in dev builds (import.meta.env.DEV).
helpdesk Get Help Help desk console. In-development, visible only when the helpdesk unreleased feature is enabled.
land-queue Land Queue Two counts: branches waiting on the auto-lander, and worktrees the ledger is holding open. Opt-in — it is not pinned by default, so it sits in the overflow until you add it.

How it behaves

How users manage widgets

There are two levels of arrangement:

  • In the header (drag) — drag a whole block to reorder the blocks (the Shortcut bar via its hover grip, or a widget block directly — a tap still opens the widget's panel; a drag reorders). The block order saves to headerBlockOrder. Inside the Shortcut bar, drag individual icons to reorder them within the pill (unchanged).
  • In Settings → Widgets (formerly "Toolbar") — show/hide any of the named widgets and reorder the icons within the Shortcut bar. Note: reordering a widget here no longer moves its header block position — the header drag does that.

Hiding a widget removes its block from the header (it stays in the registry — re-add it any time from the removed-items section). The only widget that can never be hidden is the Settings gear (settings).

Existing users

When the account and hardcore widgets shipped, a one-time startup migration (runToolbarPinMigration, flag headerWidgetsPinMigrationCompleted) back-filled both IDs into the pinnedToolbarItems setting for users whose stored list predates these registry IDs. New installs see them in the default pinned set from the start.

For agents

The WidgetShell building block

Interactive widgets (those that open an inline popover) use the shared WidgetShell component (src/renderer/src/components/ui/WidgetShell.tsx). It handles all the common plumbing:

  • Uncontrolled or controlled open/close state
  • Click-outside and Escape key dismissal
  • Focus trap inside the panel
  • Opaque elevated panel container (correct surface and shadow via ToolbarPopoverPanel)
  • Optional viewport flip (panel opens upward when it would clip the bottom of the viewport)
  • Optional lazy panel (content is not mounted until the first open, avoiding unnecessary IPC calls)
  • Full ARIA wiring (aria-haspopup, aria-expanded on the trigger; aria-label on the panel)

A widget author provides the trigger visuals (a default icon button, or a custom renderTrigger) and the panel content. All interaction logic lives in WidgetShell.

Example:

<WidgetShell
  ariaLabel="Notifications"
  panelAriaLabel="Notification panel"
  tooltip="Notifications"
  icon={Bell}
  dataUiAnchor="app-notification-bell"
  panelClassName="w-80"
>
  {({ close }) => <NotificationList onDismiss={close} />}
</WidgetShell>

How plugins contribute a header widget

Plugins contribute header buttons via the existing, already-shipped toolbar.setItems() API (part of the plugin UI contributions surface). This API:

  • Requires the chrome plugin permission (gated in Main via requirePluginUiAccess()).
  • Is desktop-only — the phone/web bridge blocks it.
  • Uses replace-semantics per plugin (a new setItems call replaces the plugin's previous set).
  • Routes click events back to the plugin's own webview as command:<id> messages.
  • Accepts an icon by name (a registered icon identifier), not a URL or arbitrary component.

No new permission or plugin capability was introduced for header widgets. Plugins cannot inject arbitrary React components into the header — all rendering stays within Omniscio's own ToolbarPinnedItem render path.

Full details: plugin-ui-contributions-contract.md.

Persisted keys

The setting keys pinnedToolbarItems and hiddenToolbarItems and the individual widget IDs (account, hardcore, cpu-burst, helpdesk) are byte-stable. The headerBlockOrder setting (added for the block row — entries are widget ids plus the 'shortcuts' sentinel; default ['account','hardcore','shortcuts']) is additive and defaults cleanly for existing users, so no data migration was needed.

Where to look in the code

  • Registry — TOOLBAR_ITEMS, DEFAULT_PINNED_TOOLBAR_ITEMS, NON_REMOVABLE_TOOLBAR_IDS, HEADER_WIDGET_BLOCK_IDS (the {account, hardcore} single source of truth for which ids become bare blocks): src/renderer/src/features/toolbar/toolbar-catalog.ts
  • Types and helpers — ToolbarItemDef, getPinnedItems, getVisibleItems, getPinnedEntries(…, excludeWidgetBlocks), getHeaderBlocks (resolves the ordered block row), SHORTCUTS_BLOCK_ID: src/renderer/src/features/toolbar/toolbar-items.ts
  • Block render + drag — the outer block row (useDragReorder, horizontal) with the Shortcut pill + bare widget blocks: src/renderer/src/features/toolbar/AppToolbar.tsx
  • Render path — pinned items rendered via renderPinnedItem; block reorder writes headerBlockOrder: src/renderer/src/app/AppTitlebar.tsx
  • Widget renderer — ToolbarPinnedItem (where AccountIndicator, HardcoreIndicator, etc. live): src/renderer/src/features/toolbar/ToolbarPinnedItem.tsx
  • WidgetShell building block: src/renderer/src/components/ui/WidgetShell.tsx
  • Pin migration — startup task Header widgets pin migration: src/main/startup/registry.ts
  • Settings pane — the "Widgets" manager: src/renderer/src/features/toolbar/ToolbarSettings.tsx
  • Guard test: tests/unit/lint/header-widget-contract.test.ts
  • Contract: .claude/memory/contracts/header-widget-contract.md

Related

Hub jumper covers the keyboard-first route to the same destinations the toolbar's icons open.

Last verified 2026-09-27