Quickshell Plugin Kinds Explained: The Complete Architecture Guide for Omarchy

Quickshell recognizes fourteen distinct plugin kinds—including service, panel, bar, bar-widget, indicator, menu, app, action, dmenu, reminder, polkit, lock, background, and agents—that determine how components are loaded, rendered, and integrated into the Omarchy shell.

Quickshell, the core shell framework in the Omarchy project, treats every extendable component as a plugin that declares its functionality through a kinds array in its manifest.json file. These Quickshell plugin kinds act as type identifiers that tell the shell whether a component should run as a background daemon, render as a floating window, or embed as a widget in the system bar. The registry logic in shell/services/PluginRegistry.qml validates these declarations and routes each plugin to its appropriate loader based on its declared kind.

Core Quickshell Plugin Kinds

The shell distinguishes between UI components, background services, and specialized agents. Each kind follows specific conventions for file placement and entry-point naming.

Service Plugins

The service kind represents long-running background processes that operate without direct user interfaces. These daemons typically handle system monitoring, media control, or hardware management.

According to the Omarchy source code, service implementations reside in shell/plugins/services/*/Service.qml. The shell creates dedicated loaders for these plugins that remain active during the entire session.

// shell.qml – generic loader for service-kind plugins
Loader {
    id: pluginServiceLoader
    active: !shell.pluginReloading && !!registry.entryPointUrl(manifest, "service")
    source: registry.entryPointUrl(manifest, "service")
}

Panel Plugins

panel plugins render as top-level UI windows that appear as separate floating interfaces, such as weather displays or VPN status panels. These components typically implement shell/plugins/panels/*/Panel.qml as their entry point.

To declare a panel plugin, the manifest must specify "kinds": ["panel"] and provide a corresponding entry point:

{
  "id": "example.weather",
  "name": "Weather Panel",
  "version": "1.0",
  "kinds": ["panel"],
  "entryPoints": {
    "panel": "Panel.qml"
  }
}

Bar and Bar-Widget Plugins

The bar kind defines the central system bar that hosts widgets and indicators, implemented in shell/plugins/bar/Bar.qml. Within this container, bar-widget plugins provide individual functional blocks such as workspace switchers or system trays.

Bar widgets declare their kind and preferred position using readonly properties:

// Workspaces.qml
readonly property string kind: "bar-widget"
readonly property string defaultSection: "left"

Widget implementations are located in shell/plugins/bar/widgets/*/*.qml.

Indicator Plugins

indicator plugins are compact status icons that live inside the bar, distinct from full widgets. These typically display binary states such as screen-recording activity or night-light status. The source tree places these in shell/plugins/bar/indicators/*/*.qml, such as shell/plugins/bar/indicators/ScreenRecording.qml.

The menu architecture uses multiple sub-kinds defined within shell/plugins/menu/Menu.qml:

  • menu: The container kind that defines the application launcher structure
  • app: Simple launchers that execute applications
  • action: Commands that invoke specific shell functions
  • dmenu: Dynamic menu entries that generate content at runtime (e.g., "Run command…")

Each entry specifies its kind explicitly:

// Menu.qml – a simple app launcher entry
{
    kind: "app",
    label: "Terminal",
    command: "omarchy launch terminal"
}

Reminder Plugins

The reminder kind creates time-based overlays that prompt the user, such as break reminders or notification flows. The implementation in shell/plugins/reminders/ReminderFlow.qml demonstrates how these transient UI components integrate with the shell's timing systems.

Polkit Plugins

polkit plugins implement PolicyKit agents that request elevated privileges when applications need authentication. The reference implementation in shell/plugins/polkit/PolkitAgent.qml shows how these plugins handle secure privilege escalation dialogs.

Lock Plugins

The lock kind manages screen-lock UI components and related helper services. The core implementation in shell/plugins/lock/Service.qml coordinates the lock screen's visual and security aspects.

Background Plugins

background plugins provide wallpaper or video backgrounds for the desktop environment. These are implemented in shell/plugins/background/Background.qml and are loaded early in the shell initialization sequence.

Agent Plugins

The agents kind represents generic plugins that expose custom APIs to other shell components. Located in shell/plugins/agents/*/*.qml, these plugins act as bridges between the shell and external services without providing direct UI elements.

How Quickshell Validates Plugin Kinds

The PluginRegistry in shell/services/PluginRegistry.qml serves as the authority for plugin kind validation. Every plugin manifest must contain a non-empty kinds array, verified by the validateManifest function in lines 64-68 of the registry file.

The registry distinguishes special handling for certain kinds when locating configuration entries. Specifically, it treats "bar", "bar-option", and "plugin" as reserved identifiers during the resolution process (lines 215-244). This logic ensures that core shell components receive proper configuration context while generic plugins follow standard loading paths.

Summary

  • Quickshell plugin kinds are declared in the kinds array of each plugin's manifest.json file.
  • The fourteen recognized kinds include: service, panel, bar, bar-widget, indicator, menu, app, action, dmenu, reminder, polkit, lock, background, and agents.
  • Service plugins run as background daemons in shell/plugins/services/*/Service.qml.
  • Panel plugins render as independent windows using entry points in shell/plugins/panels/*/Panel.qml.
  • Bar-widget and indicator plugins embed in the system bar through shell/plugins/bar/widgets/ and shell/plugins/bar/indicators/.
  • Menu plugins use sub-kinds (app, action, dmenu) defined in shell/plugins/menu/Menu.qml.
  • The PluginRegistry at shell/services/PluginRegistry.qml validates manifests and resolves entry-point URLs using the validateManifest function.

Frequently Asked Questions

What is the difference between a bar-widget and an indicator in Quickshell?

Bar-widgets are functional UI components that provide interactive controls like workspace switching or volume adjustment, while indicators are simple status displays that show binary states like recording activity or connectivity status. Bar-widgets typically occupy more space and accept user input, whereas indicators appear as compact icons within the bar's indicator area.

How do I create a new service plugin in Quickshell?

Create a new directory under shell/plugins/services/ containing a Service.qml file and a manifest.json that declares "kinds": ["service"]. The shell automatically detects enabled service plugins and loads them through the pluginServiceLoader in shell.qml, which activates when registry.entryPointUrl(manifest, "service") returns a valid path.

Can a single Quickshell plugin declare multiple kinds?

Yes, a plugin can declare multiple kinds in its manifest's kinds array. The PluginRegistry handles multi-kind plugins by resolving separate entry points for each declared kind. For example, a plugin might provide both a service for background logic and a panel for configuration UI, with each component loaded through its respective entry point URL.

Where does Quickshell validate that a plugin has a valid kind?

Validation occurs in shell/services/PluginRegistry.qml within the validateManifest function (lines 64-68), which checks that the manifest contains a non-empty kinds array. Additionally, the registry's entry-point resolution logic (lines 215-244) handles special cases for core kinds like "bar" and "plugin" when matching plugins to their configuration contexts.

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 →