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:

  1. Directory walking: Recursively scans both plugin paths for subdirectories containing manifest.json.
  2. Manifest validation: Ensures every plugin declares required fields (schemaVersion, id, name, version, author, description, kinds, entryPoints).
  3. State persistence: Reads ~/.config/omarchy/shell.json to 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, or bar
  • Entry points: entryPoints maps 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 the plugins[] array, or as bar.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.qml service validates manifest.json schemas, 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 plugin CLI provides a complete lifecycle interface: list, enable, disable, add, clone, update, and remove.
  • Hot reloading is available via the rescanPlugins IPC 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:

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 →