How the Omarchy Menu System Works: JSONC Schema, Guards, and Providers

The Omarchy menu system builds dynamic, hierarchical menus by parsing a JSONC configuration file with dotted identifiers and evaluating shell-based guard expressions, delegating specialized content to registered QML providers.

Omarchy, an open-source declarative desktop environment, renders its top-level and context menus through a schema-driven architecture defined in the omacom/omarchy repository. The system combines static configuration with runtime shell evaluation to control visibility, state, and behavior of menu items. This article examines the mechanics of menu parsing, guard expression evaluation, and provider delegation as implemented in the source code.

Core Architecture: JSONC Configuration and Dotted Identifiers

The menu structure originates from default/omarchy/omarchy-menu.jsonc. Each entry uses a dotted identifier that implicitly defines the menu hierarchy without requiring explicit nesting syntax. For example, the key trigger.share.file automatically creates a nested path under Trigger → Share → File, where each dot represents a submenu level.

When the QML component shell/plugins/menu/Menu.qml initializes, it reads this JSONC file and constructs an internal tree model by splitting the dotted keys. This approach allows flat configuration files to generate deeply nested menu structures while maintaining human readability.

JSONC Schema Fields and Guard Mechanisms

The schema supports specific fields that act as metadata, execution directives, or conditional guards. These fields are evaluated at runtime to determine the final rendered state of each menu item.

Execution and Delegation Fields

  • action: Specifies the shell command executed when the user selects the entry.
  • provider: References a named QML provider registered in Menu.qml that supplies dynamic submenu content.
  • aliases: Defines alternate searchable names for the entry to improve discoverability.

Guard Expression Fields

  • when: A shell condition that determines visibility. If the condition evaluates to false, the entry is omitted from the menu entirely.
  • disabled: A shell condition that dims the entry and prevents selection while keeping it visible in the list.
  • checked: A shell condition that displays a checkmark (✓) next to the label when the condition evaluates to true.

Visual Presentation Fields

  • icon, label, iconFont, title: Control the visual rendering of the menu item, including Unicode icons and display text.

Runtime Guard Evaluation

Guard expressions are shell commands evaluated during menu rendering. The implementation in Menu.qml processes these conditions to apply conditional logic:

Visibility Filtering occurs when the when field is present. For instance, "when": "omarchy-hw-laptop" ensures the entry only appears on laptop hardware by executing the shell condition and checking the exit status.

State Management uses the checked and disabled fields. The checked field supports complex expressions like "checked": "[[ \"$(omarchy-dns)\" == \"Google\" ]]" to display real-time configuration status. The disabled field accepts conditions such as "disabled": "omarchy-pkg-present spotify" to gray out options for already-installed services.

QML Provider System for Dynamic Content

When a menu entry specifies a provider field, the system delegates the submenu's content generation to a corresponding QML provider. Providers are defined as entries in the providers map within shell/plugins/menu/Menu.qml. The fonts provider, for example, generates a dynamic font-selection submenu with live previews.

Provider Limitations: New providers cannot be added directly in the JSONC configuration. They must be implemented in QML code and registered in the providers map before being referenced by name in the provider field. This architecture separates static configuration from dynamic content generation, keeping the JSONC file declarative while allowing complex QML logic for specialized submenus.

The Menu Rendering Workflow

The system processes menu generation through five distinct stages:

  1. Parsing: Menu.qml reads and validates default/omarchy/omarchy-menu.jsonc.
  2. Model Construction: Dotted identifiers are split on periods to build the hierarchical tree structure.
  3. Guard Evaluation: Shell conditions in when, disabled, and checked fields execute to determine visibility and state.
  4. Provider Resolution: Entries with provider fields trigger the corresponding QML provider to generate dynamic content.
  5. UI Rendering: Final assembly combines icons, labels, checkmarks, and dimmed states based on the evaluated guards.

Practical Configuration Examples

Create a laptop-specific tool that shows a checkmark when enabled:

{
  "system.laptop-only": {
    "icon": "󰣇",
    "label": "Laptop Only",
    "action": "omarchy-launch-laptop-tool",
    "when": "omarchy-hw-laptop",
    "checked": "[[ \"$(my-laptop-status)\" == \"enabled\" ]]"
  }
}

Delegate to the built-in fonts provider for dynamic font selection:

{
  "style.font": {
    "icon": "",
    "label": "Font",
    "provider": "fonts"
  }
}

Disable an install option when the package is already present:

{
  "install.service.spotify": {
    "icon": "󰓇",
    "label": "Spotify",
    "disabled": "omarchy-pkg-present spotify",
    "action": "omarchy-install-service-spotify"
  }
}

Key Source Files

  • default/omarchy/omarchy-menu.jsonc: The central menu definition file containing the JSONC schema, guard expressions, and provider references.
  • shell/plugins/menu/Menu.qml: The QML component that implements provider logic, evaluates guard expressions, and constructs the menu UI.
  • docs/menu.md: Documentation covering schema specifications, guard semantics, and provider implementation requirements.

Summary

  • The Omarchy menu system parses default/omarchy/omarchy-menu.jsonc to generate hierarchical structures from dotted identifiers like trigger.share.file.
  • Guard expressions (when, disabled, checked) evaluate shell conditions at runtime to control visibility, selectability, and checkmark states.
  • The provider field delegates dynamic submenu generation to QML implementations registered in shell/plugins/menu/Menu.qml.
  • Providers require QML implementation; they cannot be defined purely through JSONC configuration.
  • Visual attributes combine with conditional logic to create context-aware, hardware-specific menu interfaces.

Frequently Asked Questions

What file format does the Omarchy menu system use for configuration?

Omarchy uses JSONC (JSON with Comments), which allows standard JSON syntax plus C-style comments and trailing commas. The primary configuration file is located at default/omarchy/omarchy-menu.jsonc.

How do dotted identifiers create menu hierarchies without nested objects?

Dotted identifiers like trigger.share.file utilize the dot notation to represent menu depth, where each segment creates a submenu level. The parser in Menu.qml splits these keys on periods to build the tree structure automatically, keeping the configuration file flat and readable.

Can custom providers be created directly in the JSONC configuration file?

No, custom providers must be implemented in QML within shell/plugins/menu/Menu.qml and registered in the providers map. The JSONC file can only reference existing provider names via the provider field; it cannot define new provider logic.

What is the difference between the when and disabled guard fields?

The when field controls visibility: when its shell condition evaluates to false, the entry is completely hidden from the menu. The disabled field controls interactivity: when true, the entry remains visible but appears dimmed and cannot be selected, typically indicating an unavailable option.

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 →