How Omarchy Discovers and Manages Plugins: Complete Guide to the Quickshell Architecture
Omarchy discovers plugins by scanning two filesystem locations at startup—$OMARCHY_PATH/shell/plugins/ for first-party code and ~/.config/omarchy/plugins/ for user additions—then validates each manifest.json via PluginRegistry.qml before registering them with the long-lived Quickshell process.
The basecamp/omarchy repository implements a modular desktop environment where every UI component and background service is a plugin loaded into a single Quickshell instance. Understanding how Omarchy handles plugin discovery and management is essential for customizing the shell without breaking the core runtime.
Plugin Discovery Architecture
Omarchy’s discovery mechanism relies on a centralized registry service that walks specific directories and enforces a strict manifest schema.
Plugin Directory Structure
The shell searches two distinct paths during initialization:
- First-party plugins: Located at
$OMARCHY_PATH/shell/plugins/inside the repository. These ship with Omarchy and include the top bar, panels, and default widgets. - Third-party plugins: Located at
~/.config/omarchy/plugins/. Users install custom extensions here, and the shell treats them identically to built-ins after validation.
Both directories are scanned recursively at startup by the services/PluginRegistry.qml component.
The PluginRegistry.qml Service
Found at shell/services/PluginRegistry.qml, this service performs three critical operations:
- Directory walking: Recursively scans both plugin paths for subdirectories containing
manifest.json. - Manifest validation: Ensures every plugin declares required fields (
schemaVersion,id,name,version,author,description,kinds,entryPoints). - State persistence: Reads
~/.config/omarchy/shell.jsonto determine which plugins are enabled before registering them with the Quickshell engine.
The registry also maintains the enabled state map in memory, syncing changes back to shell.json when users toggle plugins via CLI.
Manifest.json Schema Requirements
Every plugin must contain a valid manifest.json at its root. The schema requires:
- Identity fields:
schemaVersion,id,name,version,author,description - Kinds array: Defines the plugin type—
bar-widget,panel,overlay,menu,service, orbar - Entry points:
entryPointsmaps each kind to its corresponding QML file path - Optional UI metadata: Bar widgets may include additional display hints
PluginRegistry.qml rejects any plugin with an invalid or missing manifest, preventing corrupted code from crashing the shell.
Plugin Management and CLI Commands
Omarchy provides a unified CLI interface—omarchy plugin <command>—that wraps IPC calls to the running Quickshell process.
Enabling and Disabling Plugins
The enabled state logic differs between first-party and third-party plugins:
- Third-party plugins: Enabled when their ID appears anywhere in
shell.json(as a bar widget entry, in theplugins[]array, or asbar.id). - First-party plugins: Enabled by default unless explicitly listed in the
disabledPlugins[]array.
Use the following commands to toggle state:
# Enable a third-party widget
omarchy plugin enable myorg.weather
# Disable a built-in first-party plugin
omarchy plugin disable omarchy.network
These commands invoke the setPluginEnabled IPC method, which atomically updates shell.json and triggers a registry refresh.
Installing Third-Party Plugins
Users can extend Omarchy by adding plugins from Git repositories or cloning built-ins for local modification:
# Add a plugin from a public repository and enable immediately
omarchy plugin add https://github.com/acme/omarchy-weather.git --enable --yes
# Clone a built-in plugin to customize it locally
omarchy plugin clone omarchy.clock --edit
The add command validates the remote manifest.json, clones to ~/.config/omarchy/plugins/<id>/, and optionally sets the enabled flag. The clone command copies first-party code to the user directory with a renamed ID, routing future calls from the original ID to the clone.
Updating and Removing Plugins
For git-managed plugins, Omarchy supports fast-forward updates with diff preview:
# Update a specific plugin
omarchy plugin update myorg.weather
# Update all git-managed plugins
omarchy plugin update --yes
Removal disables the plugin first, then either deletes the directory or backs it up depending on whether it is a git checkout:
omarchy plugin remove myorg.weather
IPC Contract and Hot Reloading
The omarchy-shell binary exposes an IPC interface that CLI commands use to manipulate the running Quickshell process without restarts.
Shell IPC Methods
The three primary methods implemented in services/PluginRegistry.qml are:
listPlugins: Returns JSON describing every discovered plugin, its enabled state, and its kinds.setPluginEnabled <id> <enabled>: Persists the enabled flag and updates the registry.rescanPlugins: Forces a complete re-walk of plugin directories and reloads changed code.
CLI wrappers in bin/omarchy-plugin-*.sh translate user commands into these IPC calls.
Hot Reloading During Development
Developers can force the shell to rescan directories after editing plugin code:
omarchy-shell shell rescanPlugins
This command triggers the rescanPlugins IPC method, which re-validates all manifests and hot-reloads QML changes without terminating the session. In practice, Quickshell’s file watchers often trigger this automatically, but manual rescans are useful when moving files or debugging manifest.json syntax.
Summary
- Omarchy uses two filesystem paths—
$OMARCHY_PATH/shell/plugins/and~/.config/omarchy/plugins/—to discover first-party and third-party plugins at startup. - The
services/PluginRegistry.qmlservice validatesmanifest.jsonschemas, manages the enabled state, and registers plugins with the Quickshell engine. - Plugin kinds (
bar-widget,panel,service, etc.) defined in the manifest determine how the shell instantiates each plugin. - Persistent state is stored in
~/.config/omarchy/shell.json, with first-party plugins enabled by default and third-party plugins enabled by explicit inclusion. - The
omarchy pluginCLI provides a complete lifecycle interface:list,enable,disable,add,clone,update, andremove. - Hot reloading is available via the
rescanPluginsIPC method, allowing developers to iterate without restarting the shell.
Frequently Asked Questions
Where does Omarchy store third-party plugins?
Third-party plugins live in ~/.config/omarchy/plugins/, with each plugin residing in its own subdirectory containing a manifest.json file and its associated QML code. This separates user customizations from the core first-party plugins shipped in $OMARCHY_PATH/shell/plugins/.
What happens if a plugin has an invalid manifest.json?
The PluginRegistry.qml service rejects the plugin during the discovery phase, and it will not appear in omarchy plugin list or be loaded by the shell. The shell continues initializing other plugins, ensuring that one malformed extension cannot crash the entire desktop environment.
How do I override a built-in Omarchy plugin with my own version?
Use the omarchy plugin clone <id> command, which copies the built-in plugin to your user config directory, automatically renames it with your user prefix, and enables the clone. The shell then routes calls from the original ID to your local copy, allowing safe modification of first-party code.
Can I manage plugins while Omarchy is running?
Yes. All omarchy plugin commands communicate with the running Quickshell process via IPC, so enabling, disabling, adding, or updating plugins takes effect immediately without requiring a session restart. The rescanPlugins IPC method ensures the registry reflects filesystem changes in real time.
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 →