# How Omarchy Discovers and Manages Plugins: Complete Guide to the Quickshell Architecture

> Learn how Omarchy discovers and manages plugins using its Quickshell architecture. Explore filesystem scanning, manifest validation, and the plugin registry for seamless integration.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: architecture
- Published: 2026-08-24

---

**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`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/shell.json) when users toggle plugins via CLI.

### Manifest.json Schema Requirements

Every plugin must contain a valid [`manifest.json`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/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:

```bash

# 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`](https://github.com/basecamp/omarchy/blob/main/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:

```bash

# 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`](https://github.com/basecamp/omarchy/blob/main/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:

```bash

# 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:

```bash
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:

```bash
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`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/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.