How to Add a Custom Bar Widget to the Omarchy Top Bar

To add a custom bar widget to the Omarchy top bar, create a QML component that extends BarWidget, place it in the shell/plugins/bar/widgets/ directory with a manifest.jsonc file, and the BarWidgetRegistry service will automatically discover and instantiate it at startup.

Omarchy is the open-source desktop shell developed by Basecamp (37signals), built with Qt Quick and QML. Its modular top bar system uses a declarative BarWidget architecture that requires no C++ or JavaScript—only QML and a minimal configuration file—to extend with custom functionality.

Creating the Bar Widget Component

Omarchy widgets are fully declarative QML components. To create one, you extend the base BarWidget component and define your UI logic.

Implementing the BarWidget Interface

Create a new .qml file in shell/plugins/bar/widgets/ that imports Omarchy.Ui 1.0 and extends BarWidget. The base component, defined in shell/Ui/BarWidget.qml, provides required properties including anchor (positioning as "left", "center", or "right"), width, height, and visible.

import QtQuick 2.15
import QtQuick.Layouts 1.15
import Omarchy.Ui 1.0

BarWidget {
    id: root
    width: 48
    height: 48
    anchor: "right"

    MouseArea {
        anchors.fill: parent
        onClicked: root.toggle()
    }

    Image {
        anchors.centerIn: parent
        source: root.active ? "qrc:/icons/check.svg" : "qrc:/icons/close.svg"
    }
}

Widget Properties and Anchoring

The anchor property determines the widget's position in the top bar flow. Use "left" for the leading edge (near the app menu), "center" for the middle section, or "right" for the trailing edge (near system trays). The BarWidget base class handles layout insertion automatically based on this property, while built-in examples like shell/plugins/bar/widgets/Workspaces.qml demonstrate complex state interactions.

Registering with BarWidgetRegistry

The BarWidgetRegistry service located at shell/services/BarWidgetRegistry.qml manages widget lifecycle and discovery. It scans plugin directories at startup and instantiates any valid BarWidget components it discovers.

Automatic Discovery via Manifest

Create a manifest.jsonc file alongside your QML component to register the widget:

{
  "name": "my-widget",
  "description": "A tiny custom widget for the top bar",
  "type": "bar-widget",
  "entry": "MyWidget.qml"
}

The registry recognizes the bar-widget type and loads the entry point automatically. No manual registration code is required for files placed in shell/plugins/bar/widgets/.

Explicit Registration (Optional)

For external plugins or development overrides, explicitly list widgets in the registry's pluginList property within shell/services/BarWidgetRegistry.qml:

property var pluginList: [
    // …existing entries…
    "plugins/bar/widgets/MyWidget.qml"
]

Adding Inline Modules to Panels

Inline modules differ from bar widgets—they render inside existing panels (such as the Menu or Weather panels) rather than the top bar row itself. These typically reside in shell/plugins/bar/inline/ or within specific panel directories.

Creating an Inline Module

Inline modules use standard QML components rather than the BarWidget base class. They are inserted into Row or Column layouts within panel definitions. Reference shell/plugins/menu/BarWidget.qml for an example of inline usage within the Omarchy menu panel.

import Omarchy.Ui 1.0

Panel {
    // …panel boilerplate…
    Row {
        MyInlineWidget { }
    }
}

Inline Module Manifest

Use type: "inline-module" in your manifest to distinguish these from top bar widgets:

{
  "name": "my-inline",
  "description": "Inline module for the Omarchy menu",
  "type": "inline-module",
  "entry": "MyInline.qml"
}

Study shell/plugins/panels/weather/Panel.qml for panel layout patterns and shell/plugins/panels/weather/BarWidget.qml for a complete reference implementation combining both widget types.

Summary

  • Extend BarWidget: Create a QML file that inherits from shell/Ui/BarWidget.qml and set the anchor property to "left", "center", or "right" to control positioning in the top bar.
  • Register via manifest.jsonc: Use type: "bar-widget" for top bar items or type: "inline-module" for panel-embedded components to enable automatic discovery by the registry service.
  • Leverage BarWidgetRegistry: The shell/services/BarWidgetRegistry.qml service handles instantiation automatically—no C++ compilation or manual JavaScript registration is required.
  • Place files correctly: Bar widgets belong in shell/plugins/bar/widgets/; inline modules belong in shell/plugins/bar/inline/ or within specific panel plugin directories.
  • Reference existing implementations: Study shell/plugins/panels/weather/BarWidget.qml and shell/plugins/menu/BarWidget.qml for complex interaction patterns and state management.

Frequently Asked Questions

What is the BarWidget base component?

BarWidget is a QML component defined in shell/Ui/BarWidget.qml that provides the required interface for all top bar widgets. It exposes properties like anchor (for positioning), width, height, and visible, and handles lifecycle management with the BarWidgetRegistry service. All custom widgets must extend this component to be recognized by the system.

Where do I place custom bar widget files?

Place custom bar widget QML files and their manifest.jsonc configurations in shell/plugins/bar/widgets/. The BarWidgetRegistry service scans this directory at startup. For inline modules intended for specific panels, use shell/plugins/bar/inline/ or the individual panel's plugin directory (e.g., shell/plugins/panels/weather/).

Can I add widgets to existing panels like the Menu?

Yes. Create an inline module with type: "inline-module" in your manifest instead of bar-widget. These modules render inside panel layouts rather than the top bar row. Reference shell/plugins/menu/BarWidget.qml for an example of a widget that lives inside the Omarchy menu panel, or examine shell/plugins/panels/weather/Panel.qml for panel layout patterns.

Do I need to write C++ or JavaScript to create widgets?

No. The Omarchy BarWidget system is fully declarative. You only need QML for the UI component and a manifest.jsonc file for registration. The BarWidgetRegistry handles all instantiation and lifecycle management automatically without requiring compiled C++ code or imperative JavaScript registration logic.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →