How to Add a Custom Bar Widget to the Omarchy Bar Layout: A Complete Guide
You add a custom bar widget to Omarchy by creating a plugin package containing a manifest.json that declares "kinds": ["bar-widget"], implementing a QML component that extends the BarWidget base class, and registering it via the omarchy putBarWidget CLI command or manual configuration in shell.json.
Omarchy is an open-source Qt/QML shell environment that supports extensible top-bar widgets through a modular plugin system. Understanding how to add a custom bar widget requires familiarity with the omacom/omarchy repository architecture, specifically how PluginRegistry detects bar-widget plugins and how BarWidgetRegistry manages their lifecycle.
Understanding the Bar Widget Architecture
The Omarchy top bar is composed of bar-widget plugins managed by three core components from the source code:
- PluginRegistry (
shell/services/PluginRegistry.qml): Scans plugin directories and identifies packages with"kinds": ["bar-widget"]. It determines default placement using thedefaultBarWidgetSection(manifest)logic. - BarWidgetRegistry (
shell/plugins/bar/BarWidgetRegistry.qml): Instantiates live widget instances and tracks their state within the bar layout. - BarWidget Base Class (
shell/Ui/BarWidget.qml): Provides the required interface that all widgets must extend, including standard properties likeid,icon, andtooltip.
When a widget is enabled, the registry loads the QML file specified in the manifest's "barWidget" field and inserts it into the requested section (left, center, or right) of the bar layout.
Step 1: Create the Plugin Package
All custom widgets reside in the user plugins directory at ~/.config/omarchy/plugins/.
Directory Structure
Each widget requires a dedicated folder named after its unique plugin ID:
mkdir -p ~/.config/omarchy/plugins/com.example.mywidget
Configure the Manifest
Create a manifest.json file that declares the widget type and entry point:
{
"id": "com.example.mywidget",
"kinds": ["bar-widget"],
"barWidget": "BarWidget.qml",
"defaultSection": "right"
}
The "defaultSection" field specifies initial placement (left, center, or right) when the widget is first enabled.
Step 2: Implement the Widget Component
Your widget must extend the BarWidget base class defined in shell/Ui/BarWidget.qml. This ensures compatibility with the bar's rendering and IPC systems.
Create BarWidget.qml in your plugin directory:
import QtQuick 2.15
import QtQuick.Layouts 1.15
import "qrc:/shell/Ui" as Ui
Ui.BarWidget {
id: root
// Override base class properties
icon: "qrc:/icons/custom.svg"
tooltip: "My Custom Tool"
// Custom UI implementation
MouseArea {
anchors.fill: parent
onClicked: {
console.log("Widget activated");
// Add custom click handling logic here
}
}
}
The base class handles integration with the bar's click handling and pop-out panels, allowing you to focus on the UI content.
Step 3: Enable and Position the Widget
Once the plugin files are in place, you must register the widget with the bar layout using one of two methods.
Using the CLI Command
The shell/shell.qml file implements the putBarWidget function, which exposes a CLI interface:
omarchy putBarWidget com.example.mywidget '{"section":"right"}'
This command inserts the widget into the specified section of ~/.config/omarchy/shell.json and triggers the BarWidgetRegistry to load the component immediately.
Manual Configuration
Alternatively, edit ~/.config/omarchy/shell.json directly. Add your widget to the desired layout section:
{
"bar": {
"layout": {
"left": [...],
"center": [...],
"right": [
{ "id": "com.example.mywidget" }
]
}
}
}
The PluginRegistry detects the change and instantiates the widget on the next bar refresh.
Complete Working Example
Here is a full setup script that creates a functional custom widget:
# Create plugin structure
PLUGIN_DIR="$HOME/.config/omarchy/plugins/com.example.sysmonitor"
mkdir -p "$PLUGIN_DIR"
# Write manifest
cat > "$PLUGIN_DIR/manifest.json" << 'EOF'
{
"id": "com.example.sysmonitor",
"kinds": ["bar-widget"],
"barWidget": "BarWidget.qml",
"defaultSection": "right"
}
EOF
# Write widget implementation
cat > "$PLUGIN_DIR/BarWidget.qml" << 'EOF'
import QtQuick 2.15
import QtQuick.Layouts 1.15
import "qrc:/shell/Ui" as Ui
Ui.BarWidget {
id: root
icon: "qrc:/icons/cpu.svg"
tooltip: "System Monitor"
Text {
anchors.centerIn: parent
text: "CPU"
color: "white"
font.pointSize: 8
}
MouseArea {
anchors.fill: parent
onClicked: console.log("Opening system monitor...")
}
}
EOF
# Enable via CLI
omarchy putBarWidget com.example.sysmonitor '{"section":"right"}'
Summary
- Plugin Structure: Place manifests and QML files in
~/.config/omarchy/plugins/<id>/. - Manifest Requirements: Declare
"kinds": ["bar-widget"]and specify"barWidget": "YourFile.qml". - Base Class: Extend
BarWidgetfromshell/Ui/BarWidget.qmlto ensure proper integration. - Registration: Use
omarchy putBarWidget <id> '{"section":"position"}'or editshell.jsonto add the widget tobar.layout.left,center, orright. - Registry Flow:
PluginRegistrydetects the plugin,BarWidgetRegistryinstantiates it, andshell.qmlmanages placement viaputBarWidget.
Frequently Asked Questions
What is the base class for omarchy bar widgets?
All bar widgets must extend BarWidget, defined in shell/Ui/BarWidget.qml. This base class provides essential properties like id, icon, and tooltip, and handles integration with the bar's IPC and rendering systems.
How do I specify the default section for my widget?
Include a "defaultSection" field in your manifest.json with a value of "left", "center", or "right". When the PluginRegistry in shell/services/PluginRegistry.qml processes your plugin, it uses this value to determine initial placement via the defaultBarWidgetSection logic.
Can I move a widget after adding it?
Yes. Use the moveBarWidget function available in shell/shell.qml via the CLI, or manually edit the bar.layout sections in ~/.config/omarchy/shell.json. Moving a widget updates its position in the layout array without requiring a plugin reload.
Where is the bar layout configuration stored?
The active bar layout is stored in ~/.config/omarchy/shell.json under the bar.layout object. This JSON file contains three arrays (left, center, right) listing the widget IDs currently displayed in each section.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →