How the Omarchy CLI Router Resolves Subcommands: Inside bin/omarchy

The Omarchy CLI router resolves subcommands through a three-phase process: discovery and registration of command metadata, longest-prefix binary matching, and fallback resolution with preserved argument forwarding.

The omacom/omarchy repository implements a sophisticated command-line interface driven by a single router script located at bin/omarchy. When users execute omarchy followed by arguments, the router transforms textual input into executable subcommands through deterministic prefix matching and route table lookups. Understanding how the omarchy CLI router resolves subcommands reveals a design that supports deep command hierarchies while maintaining simplicity and flag preservation.

Command Discovery and Registration

The router begins by mapping the entire command space available in the bin/ directory. This discovery phase builds the internal route tables that power subsequent resolution.

Scanning for Executables with load_commands

At startup, the load_commands function scans every executable file whose name begins with omarchy- in the same directory. The router treats each file as a potential command endpoint, regardless of whether it represents a top-level command or a nested subcommand. This filesystem-based discovery allows the CLI to remain extensible—adding new commands requires only dropping new executables into bin/ with the proper naming convention.

Parsing Metadata Comments in register_command

Each command file can embed configuration through special comment lines that the router parses during registration. As implemented in omacom/omarchy, the register_command function processes these metadata tags beginning around lines 200–210 of bin/omarchy.

Common metadata patterns include:


# omarchy:group=update

# omarchy:name=install

From this metadata—or derived directly from the filename—the router constructs route strings such as omarchy update or omarchy update aur. These routes populate three key data structures:

  • COMMAND_ROUTE – Associates textual routes with their implementing binaries
  • COMMAND_FALLBACK_ROUTE – Stores secondary routing options for ambiguous prefixes
  • COMMAND_ALIASES – Maps shortcut names to full command paths

Longest-Prefix Direct Resolution

Once the route tables are populated, the router enters the resolution phase when the user provides arguments. This phase prioritizes exact binary matching over route table lookups.

The resolve_direct_route Algorithm

Starting at line 398 of bin/omarchy, the resolve_direct_route function implements a greedy longest-prefix matching algorithm. The function iterates over the argument list from longest to shortest prefix, building candidate binary names by joining arguments with hyphens.

The resolution process follows this pattern:

  1. Build candidate name: omarchy-$(join_words "-" "$@")
  2. Check if file exists and is executable
  3. On first match, record resolution metadata and stop

The router stores resolution details in three variables:

  • DIRECT_RESOLVED_BINARY – The absolute path to the executable that will be invoked
  • DIRECT_RESOLVED_COUNT – The number of argument tokens consumed by the match
  • DIRECT_RESOLVED_ROUTE – The textual route string that matched

Argument Consumption and Binary Mapping

When executing omarchy theme set dracula, the router tests prefixes in descending order of length:


# Candidate 1: omarchy-theme-set-dracula (does not exist)

# Candidate 2: omarchy-theme-set (exists at bin/omarchy-theme-set) -> MATCH

The router consumes theme and set as the route prefix, leaving dracula as remaining arguments. This design enables arbitrarily deep subcommand hierarchies—such as omarchy config get editor—while keeping the routing logic linear and predictable.

Fallback Resolution and Execution

When direct binary resolution fails, the router falls back to the route tables built during the discovery phase.

Route Table Lookups

If no executable matches the longest argument prefix, the router consults COMMAND_ROUTE, COMMAND_FALLBACK_ROUTE, and COMMAND_ALIASES to locate the intended command definition. Hidden commands—those marked with appropriate metadata—are omitted from help listings unless the user explicitly requests --all.

Preserving Flags and Arguments

The router guarantees that flags intended for the final command are never swallowed during resolution. Around lines 28–35, the helper function remaining_has_help_flag checks for --help, --json, or -- separators in the remaining arguments. The router then executes the resolved binary, passing all remaining arguments unchanged:


# Example: Flags preserved through routing

$ omarchy update --json aur

In this case, resolve_direct_route identifies bin/omarchy-update as the target binary. The router invokes it with --json aur intact, allowing the command to handle JSON output formatting or interpret aur as a package source.


# Complete routing example with separator

$ omarchy config set -- editor --wait

Here, the router resolves to bin/omarchy-config-set, but preserves both the -- separator and the subsequent flags for the command implementation to process.

Summary

  • The omarchy CLI router operates from a single entry point at bin/omarchy that orchestrates subcommand discovery and dispatch.
  • Discovery phase (load_commands, register_command): Scans bin/omarchy-* executables and parses metadata comments (lines 200–210) to populate route tables including COMMAND_ROUTE and COMMAND_ALIASES.
  • Resolution phase (resolve_direct_route): Implements longest-prefix matching (lines 398–405) to map arguments to binaries like omarchy-theme-set, storing results in DIRECT_RESOLVED_BINARY and related variables.
  • Execution phase: Falls back to route tables when direct binary resolution fails, preserving all flags, --help, --json, and -- separators for the target command (lines 28–35).
  • The prefix-tree architecture supports deep hierarchies (omarchy theme set dark) while remaining deterministic and extensible through filesystem-based command discovery.

Frequently Asked Questions

How does the Omarchy router handle ambiguous command prefixes?

The router resolves ambiguity through longest-prefix matching in resolve_direct_route. It tests candidate binaries by consuming arguments from left to right until finding an existing executable. If no direct binary matches, it falls back to the COMMAND_ROUTE and COMMAND_FALLBACK_ROUTE associative arrays to find the intended command. This ensures that omarchy update takes precedence over a hypothetical shorter match.

Can command files exist outside the bin/ directory?

According to the omacom/omarchy source code, the router restricts discovery to executables within the same directory as the router script (bin/). The load_commands function specifically scans for files beginning with omarchy- in this directory. Commands must be installed into bin/ to be recognized, maintaining a centralized, predictable command structure.

What happens to flags like --help when routing commands?

The router preserves all flags and arguments for the final command implementation. The helper remaining_has_help_flag (lines 28–35) specifically checks for help flags, but the router never consumes them. When resolve_direct_route identifies the target binary, it executes the command with all remaining arguments—including --help, --json, or -- separators—passed through unchanged. This prevents the router from intercepting flags meant for subcommands.

How are command groups and aliases defined?

Groups and aliases are defined through metadata comments within command files. The register_command function parses lines like # omarchy:group=update to categorize commands and build route strings. Aliases populate the COMMAND_ALIASES array, allowing multiple invocation paths to target the same binary. Both explicit metadata and filename conventions (omarchy-group-subcommand) contribute to the final route mapping.

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 →