How to Define a Custom Plugin manifest.json for Omarchy: Complete Developer Guide
Omarchy discovers and loads plugins through a manifest.json file placed in the plugin's root directory, which supplies metadata and entry-point mappings required by the Quickshell runtime.
Omarchy is a desktop environment built on the Quickshell runtime that extends functionality through a dynamic plugin system. When the shell starts, it scans specific directories for valid plugin manifests. Understanding how to define a custom plugin manifest.json for Omarchy is essential for extending the desktop with custom bar widgets, panels, or background services.
How Omarchy Discovers Plugins
The plugin discovery mechanism is implemented in shell/PluginManager.qml. When Quickshell initializes, the manager searches the shell/plugins/ directory for subdirectories containing a manifest.json file. The loadPluginManifest function parses this JSON to register the plugin under its unique identifier and create the appropriate QML components.
Each manifest must reside in the plugin's root directory. For reference, see the Weather panel implementation at shell/plugins/panels/weather/manifest.json. The runtime uses the manifest to determine which kinds the plugin implements and which QML files to load for each entry point.
Required Manifest Schema Fields
A valid manifest.json must include specific metadata fields that tell Omarchy how to handle the plugin:
- schemaVersion: Currently must be set to
1 - id: A unique dotted identifier (e.g.,
"omarchy.weather") used to reference the plugin globally - name: Human-readable title displayed in the UI
- kinds: Array of plugin types implemented (e.g.,
["bar-widget"],["panel"], or["service"]) - entryPoints: Object mapping each kind to its corresponding QML file path relative to the plugin directory
Optional fields include version, author, and description, which appear in the plugin picker interface.
Configuring Plugin Entry Points and Kinds
The entryPoints object defines which QML files the runtime loads for each kind. For example, a bar widget declares "barWidget": "BarWidget.qml" to specify that BarWidget.qml contains the implementation extending the base component found in shell/components/BarWidget.qml.
Kind-specific metadata blocks (e.g., barWidget, panel) configure UI presentation:
- displayName: The title shown in selection menus
- category: The grouping for organization (e.g.,
"Utility","System") - allowMultiple: Boolean indicating whether users can instantiate multiple copies
- settingsForm: String referencing a QML file (relative path) that extends
shell/components/SettingsForm.qmlfor configuration UI
Creating a Custom Plugin Step-by-Step
Follow this workflow to register a new plugin with Omarchy:
- Create a directory under
shell/plugins/(e.g.,shell/plugins/panels/my-awesome-panel/) - Add a
manifest.jsonwith required fields and appropriate kinds - Create the QML files referenced in
entryPointsrelative to the plugin directory - Optionally create a settings form QML and reference it in the kind-specific block
- Restart Omarchy to trigger plugin scanning
Minimal Bar-Widget Plugin Example
This complete example demonstrates a functional custom widget.
The manifest.json file:
{
"schemaVersion": 1,
"id": "omarchy.mywidget",
"name": "My Widget",
"version": "0.1.0",
"author": "Your Name",
"description": "A simple custom bar widget",
"kinds": ["bar-widget"],
"entryPoints": {
"barWidget": "MyBarWidget.qml"
},
"barWidget": {
"displayName": "My Widget",
"description": "Shows a static label",
"category": "Utility",
"allowMultiple": false,
"settingsForm": "myWidgetSettings"
}
}
The corresponding MyBarWidget.qml implementation:
import QtQuick 2.15
import Omarchy 1.0
BarWidget {
Text {
text: "Hello Omarchy"
color: Theme.foreground
}
}
Optional settings form (myWidgetSettings.qml):
import QtQuick 2.15
import Omarchy 1.0
SettingsForm {
property string greeting: "Hello Omarchy"
}
Place all three files in the same plugin directory. After restarting Omarchy, the new widget appears under Utility → My Widget in the bar-widget picker.
Summary
- Omarchy scans
shell/plugins/directories formanifest.jsonfiles during startup viashell/PluginManager.qml - The manifest requires
schemaVersion,id,name,kinds, andentryPointsat minimum - Kind-specific blocks configure UI metadata like
displayName,category, andallowMultiple - Entry points reference QML files that extend base components such as
BarWidgetorSettingsForm - Plugins must be placed in the correct directory structure and require a shell restart to appear in the interface
Frequently Asked Questions
What kinds of plugins can I create in Omarchy?
Omarchy supports several plugin kinds including bar-widget for the top bar, panel for full-screen overlays, and service for background processes. Each kind expects specific entry point names in the manifest and extends corresponding base components in shell/components/.
Where does Omarchy scan for plugin manifests?
The runtime scans subdirectories within shell/plugins/ looking for manifest.json files. The discovery logic resides in shell/PluginManager.qml. You can organize plugins into subdirectories like shell/plugins/panels/ or shell/plugins/services/ without affecting detection.
Can I instantiate multiple copies of the same widget?
Set allowMultiple: true in the kind-specific configuration block (e.g., barWidget.allowMultiple). When enabled, users can add multiple instances of your plugin to the bar or panel. If set to false, the system restricts instantiation to a single copy.
How do I debug a plugin that isn't loading?
Verify that manifest.json contains valid JSON with all required fields (schemaVersion, id, name, kinds, entryPoints). Check that QML file paths in entryPoints are correct relative to the plugin directory. Omarchy's startup logs often indicate parse errors in shell/PluginManager.qml if the manifest fails validation.
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 →