# How Bar Widgets Are Implemented and Configured in Omarchy's shell.json

> Discover how to implement and configure bar widgets in Omarchy using shell.json. Learn about the manifest-driven registry system and declarative configuration for widget placement and options.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: how-to-guide
- Published: 2026-08-19

---

**Omarchy's top-bar uses a manifest-driven registry system where `shell/services/BarWidgetRegistry.qml` manages widget state and [`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json) declares the default layout, allowing declarative configuration of widget placement and options.**

Omarchy organizes its desktop interface through a flexible plugin architecture centered on bar widgets. The system separates concerns between a runtime registry that tracks widget state and a JSON configuration file that defines initial placement and visual properties. This design enables both static configuration through [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json) and dynamic manipulation via the registry's QML API.

## The Bar Widget Registry

The `BarWidgetRegistry.qml` service located at `shell/services/BarWidgetRegistry.qml` serves as the central authority for bar widget management. This registry maintains a map of all installed bar-widget manifests and exposes methods for runtime manipulation.

The registry provides three core functions for widget manipulation:

- **`putBarWidget(id, placement)`** – Adds a widget to the specified section
- **`moveBarWidget(id, placement)`** – Relocates an existing widget
- **`setBarWidget(id, key, value, selector)`** – Updates widget-specific configuration options

When a widget is first added, the registry determines its default section through `defaultBarWidgetSection(manifest)`, which returns `left`, `center`, or `right` based on the widget's manifest declaration. The registry mirrors its state to the UI layer through `Bar.qml`, which provides `summonBarWidget`, `hideBarWidget`, and `isBarWidgetOpen` functions to control visibility.

## Configuring Bar Widgets via shell.json

The [`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json) file declares the static bar configuration under the top-level `bar` object. This file controls both global bar properties and the specific widget layout.

### Layout Structure

The `layout` sub-object within the `bar` configuration defines three ordered arrays: `left`, `center`, and `right`. These arrays determine widget positioning from left to right in each section:

```json
{
  "bar": {
    "position": "top",
    "transparent": false,
    "centerAnchor": "omarchy.clock",
    "layout": {
      "left": [
        { "id": "omarchy.menu" },
        { "id": "omarchy.workspaces" }
      ],
      "center": [
        { "id": "omarchy.indicators" },
        { "id": "omarchy.clock" },
        { "id": "omarchy.keyboard-layout" }
      ],
      "right": [
        { "id": "omarchy.tray" },
        { "id": "omarchy.network" },
        { "id": "omarchy.power" }
      ]
    }
  }
}

```

### Widget-Specific Configuration Options

Individual widgets accept optional configuration fields passed directly to their QML components. The clock widget (`omarchy.clock`) demonstrates the most common pattern, supporting `format`, `formatAlt`, and `verticalFormat` strings:

```json
{
  "id": "omarchy.clock",
  "format": "dddd HH:mm",
  "formatAlt": "d MMMM 'W'ww yyyy",
  "verticalFormat": "HH\n—\nmm"
}

```

Each widget entry requires at minimum an `id` field matching the plugin's manifest ID.

## Widget Implementation Architecture

Concrete widget implementations reside in `shell/plugins/bar/widgets/` as QML files extending the base `BarWidget` component. Files such as `Workspaces.qml`, `Tray.qml`, and `SystemUpdate.qml` implement the specific UI and logic for their respective functions.

The `Bar.qml` component at `shell/plugins/bar/Bar.qml` renders the actual bar interface. It queries the registry to determine which widgets to instantiate and handles the visual arrangement according to the `left`, `center`, and `right` sections defined in the configuration.

## Managing Widgets Programmatically

While [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json) provides the initial state, the registry API enables runtime modifications through QML JavaScript calls.

To add a new widget to the left section:

```qml
shell.pluginRegistry.putBarWidget("omarchy.new-widget", { section: "left" })

```

To move an existing widget to a different section:

```qml
shell.pluginRegistry.moveBarWidget("omarchy.clock", { section: "right" })

```

To update a widget's configuration option, such as changing the clock format:

```qml
shell.pluginRegistry.setBarWidget(
    "omarchy.clock",
    "format",
    JSON.stringify("HH:mm:ss"),
    "{}"
)

```

To enable or disable widgets entirely:

```qml
// Enable a third-party widget
shell.pluginRegistry.setEnabled("third-party.widget", true)

// Disable the built-in bar (reverts to built-in fallback)
shell.pluginRegistry.setEnabled("omarchy.bar", false)

```

## Summary

- **`shell/services/BarWidgetRegistry.qml`** manages the runtime state of all bar widgets, providing methods to add, move, and configure widgets programmatically.
- **[`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json)** declares the default layout through a `bar.layout` object with `left`, `center`, and `right` arrays, plus widget-specific options like `format` and `formatAlt`.
- **Widget implementations** live in `shell/plugins/bar/widgets/` and extend the `BarWidget` base component, with the `Bar.qml` view handling visual rendering.
- The registry determines default widget sections via `defaultBarWidgetSection()` and exposes API functions including `putBarWidget()`, `moveBarWidget()`, and `setBarWidget()`.

## Frequently Asked Questions

### How do I add a custom widget to the left side of the bar?

Call `shell.pluginRegistry.putBarWidget("your.widget.id", { section: "left" })` from QML JavaScript, or add an entry with `"id": "your.widget.id"` to the `layout.left` array in [`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json). The widget must be installed in `shell/plugins/bar/widgets/` and registered in the plugin manifest.

### What configuration options are available for the clock widget?

According to the source configuration in [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json), the `omarchy.clock` widget accepts `format` (primary display), `formatAlt` (alternative display), and `verticalFormat` (vertical bar layout) strings using Qt time format patterns. These values pass directly to the widget's QML implementation.

### Can I disable the built-in bar entirely using the registry?

Yes. Call `shell.pluginRegistry.setEnabled("omarchy.bar", false)` to disable the built-in bar component. This reverts the shell to a fallback state without the top-bar interface. You can re-enable it by passing `true` to the same function.

### Where are widget implementations stored in the source code?

Individual widget QML files reside in `shell/plugins/bar/widgets/` within the repository. For example, `Workspaces.qml` implements `omarchy.workspaces`, `Tray.qml` implements `omarchy.tray`, and `SystemUpdate.qml` implements `omarchy.system-update`. Each extends the `BarWidget` base component defined in the shell framework.