# How to Configure Omarchy Shell Plugin Settings: JSON Persistence and QML Integration

> Configure omarchy shell plugin settings using JSON files in $HOME/.local/state/omarchy/settings. Learn how settings are injected into QML components and persisted automatically.

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

---

**Omarchy shell plugin settings are configured through individual JSON files stored in `$HOME/.local/state/omarchy/settings/`, which the shell automatically injects into QML components via a `settings` property and persists through a built-in file-watching mechanism.**

The Omarchy desktop environment utilizes a modular plugin architecture where each extension manages its own persistent configuration without explicit file I/O code. Understanding how Omarchy shell plugin settings are configured requires examining the interplay between JSON storage, QML property injection, and manifest declarations that define user interfaces.

## Where Plugin Settings Are Stored

Omarchy stores each plugin’s configuration as a separate JSON file under the user’s local state directory. When the shell instantiates a plugin from the `shell/plugins/` directory, it creates a settings object populated from:

```bash
$HOME/.local/state/omarchy/settings/<plugin-id>.json

```

For example, the weather panel loads its configuration from [`weather.json`](https://github.com/omacom/omarchy/blob/main/weather.json) (referenced in `shell/plugins/panels/weather/Panel.qml`), while the notifications service uses [`notifications.json`](https://github.com/omacom/omarchy/blob/main/notifications.json) (handled in `shell/plugins/notifications/Service.qml`).

If the JSON file does not exist, the shell supplies an empty object `{}` to the plugin, which may then write default values on first run.

## Injecting Settings into QML Components

The shell injects the loaded JSON object into each plugin’s QML component through a standardized property binding. Every plugin QML file that requires configuration exposes a property declaration:

```qml
// shell/plugins/panels/tailscale/Service.qml
property var settings: ({})  // Injected by omarchy-shell at load time

// Accessing values
var value = settings ? settings[name] : undefined

```

This pattern appears across the codebase, including in `shell/plugins/bar/widgets/Tray.qml` and `shell/plugins/notifications/Service.qml`. The shell binds the JSON representation to this `settings` property, enabling automatic synchronization between the file system and the QML runtime.

## Persistence and Auto-Save Mechanism

Changes to the `settings` object are automatically persisted through a helper mechanism that watches the `settingsFile`. According to the `shell/plugins/notifications/Service.qml` implementation, the system uses a `FileView` component combined with a save timer:

```qml
// shell/plugins/notifications/Service.qml
readonly property string settingsPath: stateDir + "notifications.json"

FileView {
    id: settingsFile
    path: service.settingsPath          // Monitored for external changes
    onReloaded: {
        // Parse JSON → service.settings object
    }
}

```

When QML code modifies the `settings` property, a `settingsSaveTimer` schedules a debounced write operation that serializes the object back to the JSON file. This design allows plugins to treat settings as reactive variables while the shell handles serialization, file watching, and hot-reload when external edits occur.

## Declaring Settings UIs in Plugin Manifests

Plugins expose configuration interfaces to users through manifest declarations. The [`manifest.json`](https://github.com/omacom/omarchy/blob/main/manifest.json) file can specify a `"settingsForm"` field that tells the shell which UI form to instantiate:

```json
// shell/plugins/panels/weather/manifest.json
{
  "id": "omarchy.weather",
  "kinds": ["panel"],
  "entryPoints": { "Panel": "Panel.qml" },
  "settingsForm": "weatherSettings"
}

```

When this field is present, the shell creates a form dialog bound to the same `settings` object, allowing users to edit the underlying JSON through a friendly interface rather than manually modifying files.

## Managing Bar Widget Settings

Bar widgets follow a specialized pattern for settings management. The `shell/plugins/bar/Bar.qml` container injects settings into each widget at load time. When a widget updates its configuration, the [`shell/plugins/bar/BarModel.js`](https://github.com/omacom/omarchy/blob/main/shell/plugins/bar/BarModel.js) handles partial persistence through the `setWidgetSettings` function:

```javascript
// shell/plugins/bar/BarModel.js
function setWidgetSettings(entry, newSettings) {
    // Merge changes into the entry's stored JSON
    var entryCopy = JSON.parse(JSON.stringify(entry));
    entryCopy.settings = newSettings;
    writeEntry(entryCopy);  // Writes only the changed settings portion
}

```

This approach allows individual bar widgets to modify their `settings` object (as seen in `shell/plugins/bar/widgets/Tray.qml` with `settings.pinned`), while the bar model ensures only the relevant widget’s settings are written back to the plugin’s JSON file.

## Summary

- **Storage Location**: Plugin settings persist as JSON files in `$HOME/.local/state/omarchy/settings/<plugin-id>.json`.
- **QML Access**: Use `property var settings: ({})` in QML files to receive the injected configuration object from the shell.
- **Auto-Persistence**: The shell automatically saves changes to JSON via `FileView` monitoring and debounced timers implemented in `notifications/Service.qml`.
- **UI Declaration**: Add a `"settingsForm"` field to [`manifest.json`](https://github.com/omacom/omarchy/blob/main/manifest.json) to expose configuration dialogs to users.
- **Widget Updates**: Bar widgets utilize [`BarModel.js`](https://github.com/omacom/omarchy/blob/main/BarModel.js) methods to persist individual setting changes without rewriting entire configuration files.

## Frequently Asked Questions

### Where are Omarchy shell plugin settings files located?

Omarchy stores plugin settings in the user’s local state directory at `$HOME/.local/state/omarchy/settings/<plugin-id>.json`. Each plugin maintains its own JSON file named after its identifier, such as [`weather.json`](https://github.com/omacom/omarchy/blob/main/weather.json) or [`notifications.json`](https://github.com/omacom/omarchy/blob/main/notifications.json). If a file is missing when the plugin loads, the shell initializes an empty settings object that the plugin can populate.

### How do I access settings inside a plugin's QML code?

Declare a `property var settings: ({})` in your QML file, as implemented in `shell/plugins/panels/tailscale/Service.qml` and `shell/plugins/bar/widgets/Tray.qml`. The Omarchy shell automatically binds the loaded JSON object to this property before the component initializes, allowing immediate access to values through standard JavaScript object notation like `settings.pinned` or `settings.enabled`.

### What triggers settings to save automatically in Omarchy plugins?

The shell implements a reactive persistence layer using a `FileView` component and a `settingsSaveTimer`. When QML code modifies the `settings` property, the timer schedules a debounced write operation to serialize the object back to the JSON file. Conversely, when the underlying file changes on disk, the `FileView` emits a `onReloaded` signal that updates the live `settings` object, enabling hot-reload of configuration changes.

### How do I add a settings UI to my Omarchy plugin?

Add a `"settingsForm"` key to your plugin’s [`manifest.json`](https://github.com/omacom/omarchy/blob/main/manifest.json) file, specifying the form identifier as shown in [`shell/plugins/panels/weather/manifest.json`](https://github.com/omacom/omarchy/blob/main/shell/plugins/panels/weather/manifest.json). The shell detects this declaration during plugin loading and generates a configuration dialog bound to the plugin’s `settings` object, allowing users to modify values without directly editing the JSON file.