# How JSONC Format Powers Omarchy's Menu System: A Deep Dive into Configuration-Driven UI

> Discover how Omarchy leverages JSONC format for its menu system, allowing declarative customization without code changes. Explore configuration driven UI.

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

---

**Omarchy uses JSONC (JSON with comments) as the single source of truth for its entire menu hierarchy, enabling declarative menu customization without code changes.**

The JSONC format plays a central role in how the Omarchy desktop environment defines, extends, and documents its interactive menu system. Unlike traditional binary or compiled menu configurations, Omarchy stores its complete top-level menu definition in `default/omarchy/omarchy-menu.jsonc`. This approach separates presentation logic from data structure, making the system both maintainable and approachable for contributors.

---

## What Is JSONC and Why Omarchy Chose It

**JSONC** extends standard JSON by allowing JavaScript-style `//` comments. This single addition transforms a rigid data format into a self-documenting configuration language.

The decision to use JSONC rather than plain JSON or YAML follows a specific design philosophy in Omarchy: data structures should carry their own documentation. The `omarchy-menu.jsonc` file contains extensive inline comments that explain field semantics, provider mechanisms, and extension patterns—information that would otherwise require a separate documentation file prone to drift.

---

## Anatomy of the Omarchy Menu JSONC File

Located at `default/omarchy/omarchy-menu.jsonc`, the core menu definition uses **dot-separated IDs** to represent hierarchical relationships. Each segment creates a nested submenu, enabling flat file storage of arbitrarily deep menu trees.

### Key Properties in Menu Entries

Every object in the JSONC file supports these fields:

- **`icon`** — Glyph from the Omarchy icon font displayed alongside the label
- **`label`** — Human-readable text shown in the UI
- **`action`** — Shell command executed when the entry is selected
- **`target`** — URL or path for link-type entries
- **`aliases`** — Array of alternate names for `omarchy menu summon <alias>` invocation
- **`when`** — Optional shell condition; entry appears only if the test returns true
- **`provider`** — References a custom QML provider for specialized submenu rendering
- **`title`** — Optional header text when the submenu is open (defaults to `label`)
- **`iconFont`** — Override font family for the icon glyph

### Entry Type Inference

The Quickshell runtime at `shell/plugins/menu/Menu.qml` infers each entry's **kind** automatically:

| Condition | Resulting Kind |
|-----------|---------------|
| Contains `action` | Command item |
| Contains `target` | Link item |
| Neither present | Submenu container |

This inference eliminates boilerplate—developers supply only semantically relevant fields.

---

## Practical JSONC Examples from the Source

The following snippets demonstrate real patterns from `default/omarchy/omarchy-menu.jsonc`:

```jsonc
// Omarchy menu definition.
// Kind is inferred: action -> action, target -> link, otherwise submenu.
// Dotted IDs define the tree. provider:"name" points a submenu at one of the shell's providers...
//   aliases        alternate `omarchy menu summon <name>` routes; also searchable.
//   iconFont       font family used for the icon glyph, when it differs from the menu font
//   title          header text shown when the submenu is open; defaults to label

"system": {"icon":"","label":"System","aliases":["power-menu"]},
"learn.keybindings": {"icon":"","label":"Keybindings","action":"omarchy-menu-keybindings"},
"trigger.share.clipboard": {"icon":"","label":"Clipboard","action":"omarchy-menu-share clipboard"},
"setup.plugin.remove": {"icon":"󰭌","label":"Remove Plugin","when":"compgen -G \"$HOME/.config/omarchy/plugins/*/manifest.json\"","action":"omarchy-menu-plugin remove"},

```

The `system` entry illustrates alias functionality—both `omarchy menu summon system` and `omarchy menu summon power-menu` resolve to the same submenu. The `setup.plugin.remove` entry demonstrates conditional visibility using a shell glob test that checks for existing plugin manifests.

---

## Runtime Consumption: From JSONC to Interactive UI

The transformation from static file to interactive menu occurs in `shell/plugins/menu/Menu.qml`. The parsing pipeline follows three stages:

1. **File reading** — The QML plugin loads `omarchy-menu.jsonc` from the system path
2. **Comment stripping** — JavaScript regex removes `//` comments: `raw.replace(/\/\/.*$/gm, '')`
3. **JSON parsing and tree building** — The cleaned content parses into an object, then maps to internal Quickshell data structures keyed by dotted IDs

This runtime parsing means menu changes require no compilation or restart—modifications to the JSONC file reflect immediately in the next menu invocation.

---

## Extending the Menu System Without Code Changes

The JSONC architecture enables **zero-code customization** for most menu extensions. Adding a new entry requires only:

1. Opening `default/omarchy/omarchy-menu.jsonc`
2. Creating a dotted ID at the appropriate hierarchy level
3. Populating the relevant properties (`action` for commands, `target` for links, or neither for submenus)

For conditional entries, the `when` property accepts any shell command that returns exit code 0 for visibility. This integration with the shell environment allows dynamic menu contents based on system state—installed packages, running processes, or file existence.

---

## Command-Line Integration with JSONC Aliases

The `aliases` field creates multiple entry points for the same functionality. This design aligns the menu system with Omarchy's CLI-first philosophy.

```bash

# Summon the "system" submenu (alias "power-menu" works too)

omarchy menu summon system
omarchy menu summon power-menu

# Run the keybindings helper directly via its action

omarchy-menu-keybindings   # same command that the menu entry triggers

# Use a dotted ID to invoke a submenu item in a script

omarchy menu summon learn.keybindings

```

The dotted ID syntax enables precise targeting of nested items without traversing parent menus programmatically.

---

## Summary

- **JSONC location**: `default/omarchy/omarchy-menu.jsonc` serves as the canonical menu definition
- **Self-documenting**: Inline `//` comments explain schema and semantics without external documentation
- **Hierarchical IDs**: Dot-separated keys like `"learn.keybindings"` define tree structure in a flat file
- **Type inference**: The runtime deduces entry kinds from field presence, eliminating boilerplate
- **Runtime parsing**: `shell/plugins/menu/Menu.qml` processes JSONC on each menu invocation for instant updates
- **Conditional visibility**: The `when` property integrates shell conditions for dynamic menu contents
- **CLI aliases**: Multiple `aliases` per entry create flexible command-line invocation patterns

---

## Frequently Asked Questions

### How does Omarchy parse JSONC comments?

The Quickshell plugin at `shell/plugins/menu/Menu.qml` uses a JavaScript regex to strip comments before parsing: `raw.replace(/\/\/.*$/gm, '')`. This removes `//` line comments while preserving the underlying JSON structure, then passes the cleaned content to `JSON.parse()`.

### Can I add custom menu items without modifying Omarchy's source code?

Yes. The JSONC file is parsed at runtime, so adding entries to `default/omarchy/omarchy-menu.jsonc` requires no recompilation. For user-specific customizations without touching system files, check whether Omarchy's configuration overlay system supports user-level menu overrides in `~/.config/omarchy/`.

### What happens if a menu entry has both `action` and `target` properties?

The type inference logic in `Menu.qml` prioritizes explicit fields: an `action` takes precedence and creates a command item, while `target` creates a link only when no `action` is present. Having both likely results in command behavior, though this pattern should be avoided for clarity.

### How do conditional menu entries work in practice?

The `when` property accepts any shell command. Entries appear only when the command exits with status 0. The `setup.plugin.remove` entry demonstrates this with `"when":"compgen -G \"$HOME/.config/omarchy/plugins/*/manifest.json\""`, which tests for the existence of any plugin manifest files before showing the removal option.