# How the Menu Definition in `default/omarchy/omarchy-menu.jsonc` Works with Guards and Providers

> Understand how the Omarchy menu definition in default/omarchy/omarchy-menu.jsonc uses guards and providers for dynamic, responsive menu systems that update without shell restarts.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: internals
- Published: 2026-09-09

---

**The Omarchy menu definition uses declarative JSONC configuration where Guard conditions control row visibility and state, while Providers generate dynamic content, enabling a responsive menu system that updates without shell restarts.**

The `omacom/omarchy` repository implements its desktop menu through a static JSONC file located at [`default/omarchy/omarchy-menu.jsonc`](https://github.com/omacom/omarchy/blob/quattro/default/omarchy/omarchy-menu.jsonc). This file serves as the single source of truth for the menu structure, enhanced by two powerful abstractions: **Guards** for conditional logic and **Providers** for dynamic data. Together, these mechanisms allow the Quickshell-based shell to render complex, context-aware menus while maintaining declarative simplicity.

## Understanding Guards in the Omarchy Menu Definition

Guards are Bash-style expressions defined directly in the JSONC that control three aspects of menu rows: visibility, checked state, and interactivity. According to the [menu documentation](https://github.com/omacom/omarchy/blob/quattro/docs/menu.md), these expressions are evaluated in a single batched process to maximize performance.

### When, Checked, and Disabled Conditions

Each guard type serves a distinct purpose in the menu lifecycle:

- **`when`** (w): Hides the row entirely when the expression evaluates to 0
- **`checked`** (c): Displays a checkmark (✓) when the expression evaluates to 1  
- **`disabled`** (d):Dims the row and prevents selection when the expression evaluates to 1, while keeping it visible

The evaluation results are transmitted from the shell to the UI as compact status lines in the format `<id>:<w|c|d>:<0|1>`.

```jsonc
// Example from default/omarchy/omarchy-menu.jsonc
"system.suspend": {
  "icon": "󰒲",
  "label": "Suspend",
  "when": "! omarchy-toggle-enabled suspend-off",
  "action": "systemctl suspend"
},
"trigger.toggle.idle-lock": {
  "icon": "󰅶",
  "label": "Stay Awake",
  "disabled": "[[ -f $HOME/.config/idle-lock.conf ]]",
  "action": "omarchy-toggle-idle"
}

```

### Batched Bash Evaluation for Performance

Rather than spawning individual processes for each condition, the `omarchy.menu` plugin collects all guard expressions and evaluates them in one Bash invocation. This batching strategy caches common lookups—such as `omarchy-pkg-present` checks—ensuring the menu remains responsive even with dozens of conditional rows.

## Working with Providers in omarchy-menu.jsonc

While static JSONC defines fixed menu structures, **Providers** enable dynamic content generation. Defined in `shell/plugins/menu/Menu.qml` through a `providers` map, these scripts emit tab-delimited rows on-demand, allowing the menu to reflect real-time system state.

### Volatile vs Static Providers

Providers operate in two modes depending on their data source:

- **Static providers**: Execute once during menu initialization
- **Volatile providers**: Re-run each time their submenu opens, useful for detecting newly installed fonts or recent files

```jsonc
// Submenu delegating to the fonts provider
"style.font": {
  "icon": "",
  "label": "Font",
  "provider": "fonts"
},
"apps": {
  "icon": "󰀻",
  "label": "Apps",
  "provider": "apps"
}

```

The `fonts` provider emits lines in the format `label\tvalue\tcurrent`, while the `apps` provider queries the system's desktop entry database to populate application lists with correct icons and launch actions.

### Merging Static and Dynamic Rows

When a submenu declares both a `provider` and static children, [`MenuModel.js`](https://github.com/omacom/omarchy/blob/main/MenuModel.js) executes the `swapProviderRows` function to combine these sources. This hybrid approach allows persistent entries—such as a "Refresh" button—to coexist with dynamically generated content:

```jsonc
"submenu.example": {
  "provider": "fonts",
  "children": {
    "refresh": {
      "label": "Refresh Font Cache",
      "action": "fc-cache -fv"
    }
  }
}

```

## The Menu Loading Pipeline

The transformation from JSONC files to rendered UI follows a strict four-phase pipeline implemented in [`shell/plugins/menu/MenuModel.js`](https://github.com/omacom/omarchy/blob/main/shell/plugins/menu/MenuModel.js):

### Load and Merge Phase

The `mergeMenuSources` function overlays user-defined extensions onto the base configuration from `default/omarchy/omarchy-menu.jsonc`. This merging preserves the positional order of entries while allowing selective field overrides, enabling users to extend the default menu without modifying core files.

### Guard Evaluation Phase

All guard expressions are batched and executed once per menu (or submenu) load. The results populate a lookup table that `Menu.qml` consults during rendering to determine which rows to display, check, or dim.

### Provider Population Phase

For each submenu containing a `provider` key, the associated script executes—either once or on every entry (if volatile). The provider's stdout is parsed into row objects and merged with any static children before the final model is exposed to the QML layer.

### Hot-Reload Capability

Because the menu monitors its source JSONC files for changes, modifications to `omarchy-menu.jsonc` or user overlays apply instantly without requiring a shell restart, facilitating rapid iteration on menu configurations.

## Practical Configuration Examples

Complete row definitions demonstrate how guards and providers interact in production configurations:

```jsonc
// Row with comprehensive guard usage
"trigger.toggle.screensaver": {
  "icon": "󱄄",
  "label": "Screensaver",
  "when": "omarchy-toggle-enabled screensaver",
  "checked": "[[ \"$(omarchy-get-screensaver-mode)\" == \"on\" ]]",
  "disabled": "[[ -f $HOME/.config/screensaver.lock ]]",
  "action": "omarchy-toggle-screensaver"
}

// Package-aware conditional disabling
"install.style.font.cascadia": {
  "icon": "",
  "label": "Cascadia Mono",
  "disabled": "omarchy-pkg-present ttf-cascadia-mono-nerd",
  "action": "omarchy-install-font 'Cascadia Mono' ttf-cascadia-mono-nerd 'CaskaydiaMono Nerd Font'"
}

```

## Summary

- **Guards** in `default/omarchy/omarchy-menu.jsonc` use Bash expressions to control visibility (`when`), checked state (`checked`), and interactivity (`disabled`) through batched evaluation for performance.
- **Providers** generate dynamic menu content on-demand, with volatile variants refreshing on each submenu open, while static children merge with provider output via `swapProviderRows`.
- The menu system supports hot-reloading and user overlays through `mergeMenuSources`, allowing extensions without core file modification.
- Key implementation files include [`shell/plugins/menu/MenuModel.js`](https://github.com/omacom/omarchy/blob/main/shell/plugins/menu/MenuModel.js) for logic processing and `shell/plugins/menu/Menu.qml` for provider registration and UI rendering.

## Frequently Asked Questions

### What is the difference between when and disabled guards in Omarchy?

The **`when`** guard completely hides a menu row when its expression evaluates to 0, removing it from the menu structure entirely. The **`disabled`** guard keeps the row visible but applies visual dimming and prevents selection when evaluating to 1, useful for showing unavailable options while maintaining menu context.

### How do providers handle dynamic content in omarchy-menu.jsonc?

Providers are external scripts referenced by the `provider` key in submenu definitions. They output tab-delimited text lines that [`MenuModel.js`](https://github.com/omacom/omarchy/blob/main/MenuModel.js) parses into row objects, merging them with any static children defined in the JSONC. Volatile providers execute on every submenu open to reflect current system state, while static providers run once during initialization.

### Can I override the default menu without modifying the source JSONC?

Yes. The `mergeMenuSources` function in [`shell/plugins/menu/MenuModel.js`](https://github.com/omacom/omarchy/blob/main/shell/plugins/menu/MenuModel.js) overlays user-provided JSONC files onto the default `default/omarchy/omarchy-menu.jsonc` configuration. This merging preserves entry positions and only overrides explicitly declared fields, allowing you to extend or modify the menu while keeping the base repository files untouched.

### Why are guards evaluated in a single batched Bash process?

Batching guard evaluations minimizes process spawning overhead by executing all Bash expressions in one shell invocation. This approach caches common lookups—such as package presence checks via `omarchy-pkg-present`—and transmits results in the compact `<id>:<w|c|d>:<0|1>` format, ensuring the menu renders instantly even with complex conditional logic.