Quickshell Desktop Configuration (shell.json) Structure in Omarchy: Complete Guide

The shell.json file in Omarchy is a versioned JSON configuration that defines the status bar layout, enabled plugins, and global desktop settings for the Quickshell-based environment.

The Omarchy repository uses Quickshell as its lightweight QML-based shell. Understanding the shell.json structure is essential for customizing your desktop or developing new plugins. This guide breaks down every field, loading mechanism, and validation test based on the actual source code implementation.


Location and Loading Priority

The Quickshell host resolves configuration through a two-tier system:

  1. Default configuration — config/omarchy/shell.json bundled with the repository
  2. User override — ~/.config/omarchy/shell.json (complete replacement, no deep-merge)

In shell/shell.qml at line 73, the runtime implements file watching for hot-reload. When the user edits their config, the shell updates bar layout and enabled plugins without restart.

The test suite at test/shell.d/config-test.sh line 16 verifies this override behavior: if the user file exists and parses as valid JSON, it replaces defaults entirely.


Top-Level Structure Overview

Every shell.json file must contain three core keys:

Key Type Required Description
version integer Yes Schema version; current default is 1
bar object Yes Status bar configuration with layout arrays
plugins array of strings Yes List of plugin IDs to load

Optional top-level keys include theme (string) and settings (object) for plugin-specific global configuration.


Bar Configuration (bar)

The bar object controls the status bar appearance and widget arrangement.

Core Fields

  • id (string, optional): Identifier for the bar instance, used by migration scripts
  • transparent (boolean): Controls background transparency; defaults to false per runtime-smoke-test.sh line 298
  • layout (object): Contains three arrays defining widget placement

Layout Structure

The layout object requires exactly three keys:

{
  "bar": {
    "id": "main-bar",
    "transparent": false,
    "layout": {
      "left": [],
      "center": [],
      "right": []
    }
  }
}

Each array holds widget entries in display order. The config-test.sh suite validates that all three arrays exist and are parseable.

Widget Entry Format

Individual widgets are objects with this structure:

Field Type Required Description
id string Yes Widget module name (e.g., omarchy.clock, omarchy.battery)
settings object No Inline configuration overriding plugin defaults

Example entry with settings:

{
  "id": "omarchy.battery",
  "settings": {
    "showPercentage": true
  }
}

The runtime-smoke-test.sh line 293 verifies that default widget IDs like omarchy.clock are present in valid configurations.


Plugins Array

The top-level plugins field lists enabled plugin IDs as strings:

"plugins": [
  "omarchy.workspaces",
  "omarchy.clock",
  "omarchy.tray",
  "omarchy.battery"
]

Plugin activation follows two paths per PluginRegistry.qml at line 110:

  • Explicit: ID appears in the plugins array
  • Implicit: Widget entry in bar layout references the plugin ID

The registry resolves these IDs to QML module paths and instantiates corresponding plugin components.


Complete Configuration Example

Putting it together, a production-ready shell.json:

{
  "version": 1,
  "bar": {
    "id": "main-bar",
    "transparent": false,
    "layout": {
      "left": [
        { "id": "omarchy.workspaces" }
      ],
      "center": [
        { "id": "omarchy.clock" }
      ],
      "right": [
        { "id": "omarchy.tray" },
        { 
          "id": "omarchy.battery",
          "settings": { "showPercentage": true }
        }
      ]
    }
  },
  "plugins": [
    "omarchy.workspaces",
    "omarchy.clock",
    "omarchy.tray",
    "omarchy.battery"
  ],
  "theme": "default"
}

Hot-Reload and Runtime Behavior

The Quickshell host monitors configuration files using Qt's file system watcher. When shell.json changes:

  1. JSON validity is checked
  2. If valid, the entire configuration replaces the current state
  3. Bar layout rebuilds with new widget arrangement
  4. Plugin registry updates enabled set
  5. Theme re-applies if changed

This implementation in shell/shell.qml enables rapid iteration without session restart.


Key Source Files

Path Purpose
config/omarchy/shell.json Default configuration template
shell/shell.qml QML host, config loading and hot-reload
shell/services/PluginRegistry.qml Plugin resolution from JSON IDs
test/shell.d/config-test.sh Schema validation tests
test/shell.d/runtime-smoke-test.sh Runtime behavior verification
shell/plugins/bar/README.md Widget ID documentation

Summary

  • shell.json is versioned via the version field (currently 1)
  • bar.layout uses three arrays (left, center, right) of widget entries
  • Widget entries require id and optionally include settings
  • plugins array lists explicitly enabled plugins; implicit activation occurs through widget references
  • User override at ~/.config/omarchy/shell.json replaces defaults completely
  • Hot-reload watches file changes and updates runtime without restart
  • PluginRegistry.qml resolves IDs to QML modules at line 110

Frequently Asked Questions

What happens if shell.json has invalid JSON syntax?

The shell rejects the configuration and falls back to the default bundled in config/omarchy/shell.json. The runtime logs the parse error but continues operation with known-good defaults.

Can I use multiple bars with different configurations?

The current schema supports a single bar object. Multiple bar instances would require distinct configuration files and separate Quickshell process launches, which Omarchy does not implement by default.

Do I need to list a plugin in both plugins and bar.layout?

No. Per PluginRegistry.qml, plugins activate through either mechanism. However, listing in plugins ensures initialization even if no widget currently uses the plugin, which matters for background services like notifications.

How do I find available widget IDs for my layout?

Consult shell/plugins/bar/README.md in the repository for documented widget identifiers, or examine the plugin directories under shell/plugins/—each valid widget exports its ID through the plugin manifest.

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 →