# Understanding the Omarchy shell.json Structure: State Management Schema Explained

> Explore the Omarchy shell.json structure. Understand the state management schema including version, bar layouts, and plugins for your desktop.

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

---

**The Omarchy [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json) file is a versioned JSON configuration located at `~/.config/omarchy/shell.json` that serves as the single source of truth for desktop state, containing a mandatory version field, a bar object with widget layouts, and a plugins array for enabled services.**

The `basecamp/omarchy` repository uses this file to persist and hot-reload the desktop environment's configuration without restarting the shell. Understanding the Omarchy shell.json structure is essential for customizing the bar layout, enabling plugins, and managing widget-specific settings across sessions.

## Top-Level Schema Overview

The root object in [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json) follows a strict schema validated at load time. According to the loading logic in [`shell/shell.qml`](https://github.com/basecamp/omarchy/blob/quattro/shell/shell.qml), the file must contain these primary keys:

- **`version`**: An integer specifying the schema version. The current default is `1`.
- **`bar`**: An object describing the panel configuration and widget arrangement.
- **`plugins`**: An array of strings listing enabled plugin identifiers.

Additional top-level keys may appear for plugin-specific configuration, but the three fields above form the required foundation.

## The Bar Configuration Object

The `bar` object controls the on-screen panel's appearance and widget placement. As defined in the bundled default at [[`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json)](https://github.com/basecamp/omarchy/blob/quattro/config/omarchy/shell.json), this object supports the following structure:

```json
{
  "bar": {
    "id": "local.main-bar",
    "transparent": false,
    "layout": {
      "left": [],
      "center": [
        {"id": "omarchy.clock", "type": "qml", "settings": {}}
      ],
      "right": []
    }
  }
}

```

### Bar Properties

- **`id`**: Optional string identifier for the bar instance. Used for debugging and multi-monitor scenarios.
- **`transparent`**: Boolean flag. When set to `true`, the bar background becomes transparent.
- **`layout`**: Required object containing three arrays: `left`, `center`, and `right`. These arrays determine widget positioning across the horizontal axis.

### Widget Entry Structure

Each element within the layout arrays represents a widget entry with a standardized schema enforced by [[`shell/plugins/bar/BarModel.js`](https://github.com/basecamp/omarchy/blob/main/shell/plugins/bar/BarModel.js)](https://github.com/basecamp/omarchy/blob/quattro/shell/plugins/bar/BarModel.js):

- **`id`**: Required string matching the plugin module name (e.g., `"omarchy.clock"`).
- **`type`**: Required string set to either `"command"` for executable-based widgets or `"qml"` for native Qt Quick components.
- **`settings`**: Optional object containing widget-specific configuration overrides.

The shell watches [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json) for filesystem changes and rebuilds the bar layout immediately when these arrays are modified.

## Plugin Management and Arbitrary Keys

Beyond the `bar` object, the Omarchy shell.json structure supports dynamic plugin configuration through two mechanisms:

**The Plugins Array**
The `plugins` field contains an array of enabled service identifiers:

```json
{
  "plugins": ["omarchy.nightlight", "omarchy.media", "omarchy.battery"]
}

```

The [`shell/services/PluginRegistry.qml`](https://github.com/basecamp/omarchy/blob/quattro/shell/services/PluginRegistry.qml) reads this array to determine which services to activate during initialization. A plugin is considered enabled when its ID appears in this list or elsewhere in the configuration.

**Module-Specific Configuration**
Any top-level key matching a plugin ID can store arbitrary configuration for that module. For example:

```json
{
  "omarchy.weather": {
    "location": "Paris",
    "units": "metric"
  }
}

```

These entries merge with default settings at runtime, allowing per-plugin state persistence without modifying the plugin's source code.

## Validation and Fallback Behavior

The shell implements robust validation logic in [`shell/shell.qml`](https://github.com/basecamp/omarchy/blob/quattro/shell/shell.qml) to handle malformed or missing configurations:

1. **Primary Load**: Attempts to read `~/.config/omarchy/shell.json` from the user's home directory.
2. **Fallback**: If the user file is missing, unreadable, or contains invalid JSON, the shell falls back to the bundled [[`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json)](https://github.com/basecamp/omarchy/blob/quattro/config/omarchy/shell.json).
3. **Version Check**: The shell validates the `version` field. If absent, it defaults to `1` and logs a warning to the console.
4. **Schema Enforcement**: The test suite in [[`test/shell.d/config-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/config-test.sh)](https://github.com/basecamp/omarchy/blob/quattro/test/shell.d/config-test.sh) asserts that `layout.left`, `layout.center`, and `layout.right` must be arrays, preventing runtime crashes from malformed widget definitions.

## Practical Configuration Examples

**Reading the current center widgets**

```bash
jq '.bar.layout.center[].id' ~/.config/omarchy/shell.json

```

**Adding a volume widget to the right side**

```bash
jq '.bar.layout.right += [{"id":"omarchy.volume","type":"qml","settings":{"step":5}}]' \
  ~/.config/omarchy/shell.json > tmp.json && mv tmp.json ~/.config/omarchy/shell.json

```

**Enabling the nightlight plugin**

```bash
jq '.plugins += ["omarchy.nightlight"]' \
  ~/.config/omarchy/shell.json > tmp.json && mv tmp.json ~/.config/omarchy/shell.json

```

**Toggling bar transparency**

```bash
jq '.bar.transparent = true' \
  ~/.config/omarchy/shell.json > tmp.json && mv tmp.json ~/.config/omarchy/shell.json

```

Changes take effect immediately without restarting the desktop environment because the file watcher detects modifications and triggers a layout refresh through [[`shell/plugins/bar/BarModel.js`](https://github.com/basecamp/omarchy/blob/main/shell/plugins/bar/BarModel.js)](https://github.com/basecamp/omarchy/blob/quattro/shell/plugins/bar/BarModel.js).

## Summary

- The Omarchy shell.json structure consists of a versioned root object with three mandatory sections: `version`, `bar`, and `plugins`.
- The `bar` object contains layout arrays (`left`, `center`, `right`) that define widget positioning using entries with `id`, `type`, and optional `settings` fields.
- The `plugins` array controls which services load at runtime, while arbitrary top-level keys enable plugin-specific configuration storage.
- The shell validates the file on load and falls back to default configurations located in [`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json) if the user file is corrupted or missing.
- All changes are hot-reloaded, allowing real-time customization of the desktop environment.

## Frequently Asked Questions

### Where does Omarchy store the shell.json file by default?

Omarchy searches for [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json) at `~/.config/omarchy/shell.json` in the user's home directory. If this file does not exist or contains invalid JSON, the shell automatically falls back to the bundled default located at [`config/omarchy/shell.json`](https://github.com/basecamp/omarchy/blob/main/config/omarchy/shell.json) within the installation directory. This fallback mechanism ensures the desktop remains functional even when user configuration is corrupted.

### What happens if I omit the version field in shell.json?

If the `version` field is missing, the shell assumes version `1` and logs a console warning. While the desktop will continue to function using default schema assumptions, omitting this field may cause unexpected behavior if future Omarchy releases introduce breaking schema changes. The version field acts as a migration marker for configuration updates.

### Can I add custom settings for plugins directly in shell.json?

Yes, you can add arbitrary configuration keys at the top level of [`shell.json`](https://github.com/basecamp/omarchy/blob/main/shell.json) using the plugin's ID as the key name. These settings automatically merge with the plugin's defaults at runtime. For example, adding an `"omarchy.clock"` object with a `format` setting overrides the default time display format without modifying the plugin source code.

### How does Omarchy detect changes to shell.json?

The shell initializes a filesystem watcher on `~/.config/omarchy/shell.json` during startup. When the file is modified, the watcher triggers a reload sequence in [`shell/shell.qml`](https://github.com/basecamp/omarchy/blob/quattro/shell/shell.qml) that re-parses the JSON and updates the bar layout, plugin states, and widget configurations in real-time without requiring a session restart.