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

> Explore the Quickshell desktop configuration shell.json structure in Omarchy. Understand status bar layout, plugins, and global settings for your Quickshell environment. Get the complete guide.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: how-to-guide
- Published: 2026-09-03

---

**The [`shell.json`](https://github.com/omacom/omarchy/blob/main/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`](https://github.com/omacom/omarchy/blob/main/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`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/shell/shell.qml#L73), 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](https://github.com/omacom/omarchy/blob/quattro/test/shell.d/config-test.sh#L16) 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`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/test/shell.d/runtime-smoke-test.sh#L298)
- **layout** (object): Contains three arrays defining widget placement

### Layout Structure

The `layout` object requires exactly three keys:

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

```

Each array holds **widget entries** in display order. The [config-test.sh](https://github.com/omacom/omarchy/blob/quattro/test/shell.d/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:

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

```

The [runtime-smoke-test.sh line 293](https://github.com/omacom/omarchy/blob/quattro/test/shell.d/runtime-smoke-test.sh#L293) 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:

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

```

Plugin activation follows two paths per `PluginRegistry.qml` at [line 110](https://github.com/omacom/omarchy/blob/quattro/shell/services/PluginRegistry.qml#L110):

- **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`](https://github.com/omacom/omarchy/blob/main/shell.json):

```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`](https://github.com/omacom/omarchy/blob/main/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`](https://github.com/omacom/omarchy/blob/main/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`](https://github.com/omacom/omarchy/blob/main/test/shell.d/config-test.sh) | Schema validation tests |
| [`test/shell.d/runtime-smoke-test.sh`](https://github.com/omacom/omarchy/blob/main/test/shell.d/runtime-smoke-test.sh) | Runtime behavior verification |
| [`shell/plugins/bar/README.md`](https://github.com/omacom/omarchy/blob/main/shell/plugins/bar/README.md) | Widget ID documentation |

---

## Summary

- **[`shell.json`](https://github.com/omacom/omarchy/blob/main/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](https://github.com/omacom/omarchy/blob/quattro/shell/services/PluginRegistry.qml#L110)

---

## Frequently Asked Questions

### What happens if [`shell.json`](https://github.com/omacom/omarchy/blob/main/shell.json) has invalid JSON syntax?

The shell rejects the configuration and falls back to the default bundled in [`config/omarchy/shell.json`](https://github.com/omacom/omarchy/blob/main/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`](https://github.com/omacom/omarchy/blob/main/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.