How to Create Menu Entries with Guards and Provider Functions in Omarchy
Use the when field for conditional visibility guards and the action field for provider functions in omarchy-menu.jsonc to build dynamic, context-aware menu entries.
Omarchy’s extensible menu system is driven by a JSON-C configuration file that supports runtime conditional logic and external command providers. By leveraging guards to control visibility and provider functions to execute actions, you can create menu entries that adapt to the current environment, available binaries, or specific system states. This guide walks through the implementation details found in the omacom/omarchy source code.
Understanding the Omarchy Menu Structure
Omarchy defines its core menu hierarchy in default/omarchy/omarchy-menu.jsonc. Each entry uses a dotted identifier (e.g., setup.plugin.remove) that determines its placement in the menu tree. The configuration accepts four primary fields per entry:
icon: A Unicode character or Nerd Font icon for the visual indicatorlabel: The display text shown in the launcherwhen: An optional shell command that acts as a guard to determine visibilityaction: The provider function or command executed when the entry is selected
User customizations belong in ~/.config/omarchy/extensions/omarchy-menu.jsonc, which Omarchy hot-reloads automatically alongside the default configuration.
Using Guards to Conditionally Display Entries
The when Field Syntax
The guard mechanism relies on the when field, which Omarchy evaluates using bash -c. If the command exits with status 0, the entry is displayed; any non-zero exit code filters the entry from the current menu render. This allows you to check for command existence, file presence, environment variables, or service states before showing an option.
In default/omarchy/omarchy-menu.jsonc, the Remove Plugin entry demonstrates this pattern by checking for existing plugin manifests:
"setup.plugin.remove": {
"icon": "",
"label": "Remove Plugin",
"when": "compgen -G \"$HOME/.config/omarchy/plugins/*/manifest.json\"",
"action": "omarchy-menu-plugin remove"
}
Common Guard Patterns
You can implement guards using standard shell constructs:
- Command existence:
omarchy-cmd-present omarchy-menu-plugin - File presence:
[[ -e "$HOME/.config/omarchy/plugins/myplugin/manifest.json" ]] - Session type check:
[[ $XDG_SESSION_TYPE == wayland ]] - Package availability:
omarchy-pkg-present git
Implementing Provider Functions with the action Field
Built-in Providers
The action field specifies the provider function—the executable or script that runs when a user selects the entry. Most built-in actions delegate to bin/omarchy-menu-plugin, a central dispatcher that handles enable, disable, clone, and remove operations while launching the Quickshell IPC surface.
The emoji picker entry shows a simple provider invocation:
"trigger.emoji": {
"icon": "",
"label": "Emoji",
"aliases": ["emoji","emojis"],
"action": "omarchy-menu-emoji"
}
Custom Provider Scripts
For specialized workflows, you can point action to custom scripts. These scripts can invoke omarchy-menu-select to present dynamic submenus or execute arbitrary system commands. The provider receives no arguments by default, but you can wrap logic in shell scripts that parse the environment or call other Omarchy utilities.
Creating Custom Menu Entries
User Extension File
Create or edit ~/.config/omarchy/extensions/omarchy-menu.jsonc to add personal entries without modifying core files. The format mirrors the default configuration, supporting the same when and action fields.
A minimal custom entry that only appears when Neovim is installed:
// ~/.config/omarchy/extensions/omarchy-menu.jsonc
{
"personal.notes": {
"icon": "🗒️",
"label": "My Notes",
"when": "[[ -x $(command -v nvim) ]]",
"action": "omarchy-menu-plugin exec nvim ~/notes.md"
}
}
Practical Examples
1. Platform-Specific Entry Display a Wayland information panel only on Wayland sessions:
{
"system.wayland-info": {
"icon": "",
"label": "Wayland Info",
"when": "[[ $XDG_SESSION_TYPE == wayland ]]",
"action": "omarchy-menu-plugin exec weston-info"
}
}
2. Service Management Guard Show a removal option only when the SSH daemon is enabled:
{
"service.sshd.remove": {
"icon": "",
"label": "Remove SSH Daemon",
"when": "systemctl is-enabled sshd.service >/dev/null",
"action": "omarchy-menu-plugin systemctl disable sshd.service && omarchy-menu-plugin systemctl stop sshd.service"
}
}
3. Dynamic List Provider
Create a custom script at ~/.local/bin/my-menu-list-git-repos to populate a dynamic submenu:
#!/usr/bin/env bash
# List all git repos under $HOME/projects
repos=($(find "$HOME/projects" -maxdepth 2 -type d -name ".git" -printf "%h\n"))
omarchy-menu-select "Pick a repo" "${repos[@]}" --mode=launch
Then reference it in your extension file:
{
"dev.git-repos": {
"icon": "",
"label": "Git Repos",
"action": "$HOME/.local/bin/my-menu-list-git-repos"
}
}
Summary
- Guards use the
whenfield with shell commands evaluated bybash -cto conditionally display entries based on runtime state - Provider functions specified in the
actionfield execute when an entry is selected, typically delegating toomarchy-menu-pluginor custom scripts - Core definitions live in
default/omarchy/omarchy-menu.jsoncwhile user extensions belong in~/.config/omarchy/extensions/omarchy-menu.jsonc - The dotted identifier syntax (e.g.,
personal.notes) determines menu hierarchy placement - Changes to extension files trigger automatic hot-reloads without restarting the session
Frequently Asked Questions
How does Omarchy evaluate the when guard condition?
Omarchy passes the when string directly to bash -c at menu render time. If the command exits with status 0, the entry is included; otherwise it is filtered out. This evaluation occurs every time the menu opens, ensuring entries reflect the current system state.
Can I override default menu entries without editing core files?
Yes. Create entries in ~/.config/omarchy/extensions/omarchy-menu.jsonc using the same identifier as a default entry. Omarchy merges configurations with user extensions taking precedence, allowing you to override icons, labels, guards, or actions without modifying default/omarchy/omarchy-menu.jsonc.
What is the difference between omarchy-menu-plugin and direct commands in the action field?
omarchy-menu-plugin is a specialized dispatcher that runs inside the Quickshell IPC surface, providing consistent UI patterns for enable, disable, and exec operations. Direct commands run outside this context and are suitable for simple launches or custom scripts that handle their own UI logic. Use omarchy-menu-plugin exec to launch external applications while maintaining integration with the Omarchy environment.
Where can I find the complete schema documentation for menu entries?
Reference docs/menu.md in the Omarchy repository for the full JSON-C schema, guard syntax specifications, and provider conventions. For end-user guidance on the extension file location and format, consult manual/31-dotfiles.md.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →