How Omarchy Shell Plugins Function: Quickshell Plugin System Explained
Omarchy shell plugins are self-contained UI extensions that run inside a single long-running Quickshell process, discovered via manifest.json files, loaded dynamically at runtime, and controlled through IPC commands.
The Omarchy desktop environment manages all visual elements—status bars, widgets, panels, overlays, and background services—through a unified plugin architecture. According to the basecamp/omarchy source code, this system enables seamless customization without requiring shell restarts or complex compilation steps.
Plugin Discovery and Validation
The foundation of Omarchy shell plugins lies in shell/services/PluginRegistry.qml, which orchestrates the entire plugin lifecycle.
Scanning Locations
At initialization, the PluginRegistry invokes a Bash script via its rescan() function to scan two distinct directories:
- First-party plugins:
shell/plugins— bundled components shipped with Omarchy - Third-party plugins:
~/.config/omarchy/plugins— user-installed extensions
For each manifest.json (or *.manifest.json) discovered, the registry performs four validation steps:
- Parses the JSON structure
- Validates against schema version 1 with required fields and safe entry-point paths
- Stamps metadata with
__sourceDirand__isFirstPartyflags - Merges manifests into
installedPlugins, reservingomarchy.*namespace for first-party plugins
Manifest Schema and Structure
Every Omarchy shell plugin requires a manifest.json at its root directory. The schema defines capabilities and entry points for the Quickshell runtime.
| Field | Purpose |
|---|---|
id |
Unique identifier; omarchy. prefix reserved for built-ins |
name |
Human-readable display title |
version |
Semantic version string |
kinds |
Plugin types: bar-widget, bar, panel, overlay, menu, service |
entryPoints |
Maps each kind to a relative QML file |
keepLoaded |
Optional; retains plugin in memory after dismissal |
barWidget |
Optional placement metadata and multiplicity rules |
Entry-point paths must be relative and cannot contain .. or traverse outside the plugin directory—enforced by path validation in PluginRegistry.qml.
Enabling and Disabling Omarchy Shell Plugins
Plugin activation is controlled through ~/.config/omarchy/shell.json, interpreted by PluginRegistry.setEnabled(id, true|false, placement?).
Configuration Patterns
- Bar widgets: Enabled by inclusion in
bar.layout.<section>arrays - Bar replacements: Selected via
bar.idfield - General plugins: Listed in top-level
plugins[]array
First-party non-bar plugins are implicitly enabled unless explicitly listed in disabledPlugins[]. The registry handles special logic for widget placement, ensuring cloned plugins correctly supersede their sources.
Runtime IPC Communication
External tools interact with running Omarchy shell plugins through an IPC layer that wraps PluginRegistry methods for atomic configuration changes.
Core IPC Methods
| Command | Function |
|---|---|
listPlugins |
Returns JSON array of all discovered plugins |
enablePlugin <id> <placement> |
Activates plugin with optional bar placement |
putBarWidget <id> <placement> |
Adds widget if absent |
moveBarWidget <id> <placement> |
Relocates existing widget |
call <id> <method> <arg> |
Invokes method on loaded plugin |
These commands enable scripting, automation, and integration with external tools without shell restarts.
Hot-Reload and Plugin Cloning
Omarchy shell plugins support development workflows through automatic reloading and safe customization via cloning.
File System Monitoring
The localPluginWatcher in PluginRegistry.qml uses inotifywait to detect source modifications. Changes emit localPluginChanged(pluginId), triggering hot-reload while preserving state for keepLoaded plugins.
Cloning Mechanism
Cloning creates a personal copy of first-party plugins under ~/.config/omarchy/plugins/<username>.<id>/ with these characteristics:
- Preserved identity: Clone retains original IPC identity—existing shortcuts remain functional
- Automatic mutual exclusion: Enabling clone disables source plugin via
disabledPlugins[]; conversely, enabling source removes clone from disabled list
This design allows users to modify built-in behavior without losing upstream compatibility.
Entry-Point Loading and Injected Properties
When summoned via omarchy-shell shell summon <id>, the registry resolves the entry-point URL through entryPointUrl(manifest, kind). The resulting file:// path loads as a QML Item with injected context:
omarchyPath— Absolute filesystem path to plugin directoryshell— Reference to running shell instancemanifest— Parsed manifest objectpluginRegistry/barWidgetRegistry— Runtime registries for dynamic queries
These properties enable plugins to query system state, emit IPC calls, and self-configure.
Practical Examples
Minimal Bar Widget Manifest
{
"schemaVersion": 1,
"id": "myorg.cool-clock",
"name": "Cool Clock",
"version": "1.0.0",
"kinds": ["bar-widget"],
"entryPoints": { "barWidget": "Widget.qml" },
"barWidget": {
"defaultSection": "center",
"allowMultiple": false
}
}
See shell/services/PluginRegistry.qml for complete schema validation rules.
CLI Plugin Activation
# Enable plugin with left-side bar placement
omarchy enablePlugin myorg.cool-clock '{"section":"left"}'
This internally invokes PluginRegistry.setEnabled("myorg.cool-clock", true, {"section":"left"}).
Panel Summoning with Payload
# Load weather panel and pass location data
omarchy-shell shell summon community.weather '{"location":"Seattle"}'
The summon method loads the plugin if needed and calls its open(payloadJson) entry point.
Basic QML Widget Implementation
// Widget.qml
Item {
width: 80; height: 30
Text {
anchors.centerIn: parent
text: "12:34"
font.pixelSize: Style.font.title
color: Color.foreground
}
}
Automatically receives shell, pluginRegistry, and other context properties on load.
Architecture Files
| Path | Responsibility |
|---|---|
shell/services/PluginRegistry.qml |
Discovery, validation, lifecycle management, hot-reload |
docs/omarchy-shell.md |
Manifest format, IPC reference, configuration schema |
shell/shell.qml |
Shell instantiation, IPC target exposure, config wiring |
shell/plugins/*/*/manifest.json |
Reference first-party plugin implementations |
test/shell.d/plugins-test.sh |
Manifest parsing and safety validation tests |
Summary
- Omarchy shell plugins are Quickshell QML components discovered through
manifest.jsonscanning inshell/pluginsand~/.config/omarchy/plugins shell/services/PluginRegistry.qmlvalidates manifests, manages enabled state, and orchestrates loading- IPC commands (
enablePlugin,summon,call) control runtime behavior without shell restarts - Hot-reload via
inotifywaitand cloning with preserved identity enable safe customization - Injected properties (
shell,omarchyPath,pluginRegistry) provide plugin context
Frequently Asked Questions
What file format defines an Omarchy shell plugin?
A manifest.json file at the plugin root declares metadata including id, version, kinds, and entryPoints. The schema requires schemaVersion: 1 and enforces safe relative paths for entry points.
Can I modify built-in Omarchy plugins without losing updates?
Yes. Use the cloning feature: omarchy enablePlugin with a first-party plugin creates a copy under ~/.config/omarchy/plugins/<user>.<id>/. This preserves the original IPC identity while allowing modifications; the clone automatically supersedes the original when enabled.
How do Omarchy shell plugins receive data when summoned?
The summon IPC method passes a JSON payload to the plugin's open() entry point. For bar widgets and persistent services, injected properties like shell and pluginRegistry enable ongoing runtime interaction.
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 →