How Omarchy's CLI Router Uses Longest-Prefix Matching for Command Dispatch

Omarchy's CLI router implements longest-prefix matching through a Bash associative array called GROUP_DESCRIPTIONS, iterating over all defined prefixes to find the longest match before dispatching to the appropriate sub-command script.

The Omarchy command-line interface routes user commands using a deterministic pattern-matching algorithm built entirely in shell script. Located at bin/omarchy, this dispatcher enables intuitive sub-command handling while resolving ambiguous inputs through prefix length comparison.

The Core Routing Algorithm in bin/omarchy

The router operates in three distinct phases: prefix registration, match evaluation, and script execution.

Phase 1: Prefix Registration via GROUP_DESCRIPTIONS

The dispatcher maintains authoritative command vocabulary in a Bash associative array defined near the top of bin/omarchy:


# EXCERPT from bin/omarchy (lines 22-45)

declare -A GROUP_DESCRIPTIONS=(
  [theme]="Manage desktop themes"
  [install]="Install Omarchy components"
  [update]="Update Omarchy installation"
  [toggle]="Toggle system features"
  [toggle-touchscreen]="Toggle touchscreen support specifically"
  # ... additional groups

)

Each key represents a valid command-group prefix. The values provide human-readable descriptions for help generation, but the keys themselves drive the routing logic.

Phase 2: Longest-Prefix Match Evaluation

When a user executes omarchy <arguments>, the router evaluates every prefix against the supplied input:


# EXCERPT from bin/omarchy (lines 80-98)

best_match=""
best_len=0

for prefix in "${!GROUP_DESCRIPTIONS[@]}"; do
  # Check if user arguments start with this prefix

  if [[ "$@" == "$prefix"* ]]; then
    prefix_len=${#prefix}
    
    # Keep the longest matching prefix

    if (( prefix_len > best_len )); then
      best_match="$prefix"
      best_len=$prefix_len
    fi
  fi
done

This loop implements the longest-prefix matching rule explicitly: longer matches supersede shorter ones, even when multiple prefixes technically satisfy the condition.

Phase 3: Dispatch to Resolved Handler

After identifying the optimal prefix, the router constructs and executes the target script:


# EXCERPT from bin/omarchy (lines 105-113)

if [[ -n "$best_match" ]]; then
  # Transform prefix to script name: theme -> omarchy-theme

  script_path="$OMARCHY_ROOT/bin/omarchy-${best_match}"
  
  # Execute with remaining arguments preserved

  exec "$script_path" "${@:$best_len+1}"
else
  show_help
fi

The exec call replaces the current process, ensuring signal handling and exit codes propagate correctly to the sub-command.

Practical Examples of Prefix Resolution

Example 1: Non-Overlapping Prefixes

$ omarchy theme set preferred

Match evaluation:

  • theme matches (length 5) ✓
  • No longer prefix matches

Dispatch result: Executes bin/omarchy-theme with arguments set preferred

Example 2: Overlapping Prefixes (Demonstrating Longest-Prefix Rule)

$ omarchy toggle touchscreen enable

Match evaluation:

  • toggle matches (length 6) ✓
  • toggle-touchscreen matches (length 17) ✓

Longest-prefix wins: Executes bin/omarchy-toggle-touchscreen with argument enable

This behavior ensures specific handlers take precedence over generic ones without requiring exact argument parsing.

Example 3: Exact Prefix Match

$ omarchy update

Match evaluation:

  • update matches exactly (length 6) ✓

Dispatch result: Executes bin/omarchy-update with no additional arguments

Architecture Benefits of This Design

The longest-prefix matching approach provides several structural advantages:

  • Extensibility: New command groups add single entries to GROUP_DESCRIPTIONS without modifying router logic
  • Predictability: Users intuit that more specific commands (toggle-touchscreen) override general ones (toggle)
  • Discoverability: The associative array doubles as the help system's data source
  • Performance: For typical command sets (under 50 prefixes), linear scan overhead remains negligible

Key Source Files and Locations

File Purpose Critical Lines
bin/omarchy Central dispatcher implementing longest-prefix matching 22-45 (GROUP_DESCRIPTIONS), 80-98 (matching loop), 105-113 (exec dispatch)
bin/omarchy-<group> Individual command implementations (e.g., omarchy-theme, omarchy-toggle-touchscreen) Varies by command
docs/cli.md CLI design documentation and command reference N/A

Summary

  • Omarchy's CLI router resides in bin/omarchy and implements longest-prefix matching through pure Bash
  • The GROUP_DESCRIPTIONS associative array registers all valid command-group prefixes with their descriptions
  • A linear scan compares each prefix against user input, tracking the longest successful match via best_match and best_len variables
  • The winning prefix determines which bin/omarchy-<prefix> script receives execution via exec
  • This design resolves ambiguity deterministically: specific prefixes always defeat generic ones

Frequently Asked Questions

What happens if two prefixes have identical length and both match?

The loop processes GROUP_DESCRIPTIONS in arbitrary hash order, making behavior undefined for equal-length matches. In practice, Omarchy's prefix design avoids this scenario—no two command groups share identical length with overlapping character sequences.

Can users create custom command groups?

Yes, by adding entries to GROUP_DESCRIPTIONS and creating corresponding bin/omarchy-<prefix> scripts. The router treats user-defined prefixes identically to built-in ones during longest-prefix evaluation.

Does longest-prefix matching affect performance with many commands?

No. Bash associative array iteration over typical command sets (dozens of prefixes) completes in sub-millisecond times. The algorithm's O(n) complexity where n equals prefix count remains imperceptible for CLI interaction latencies.

How does the router handle completely unmatched input?

When no prefix satisfies the [[ "$@" == "$prefix"* ]] condition, best_match remains empty and the router invokes show_help, displaying available command groups from GROUP_DESCRIPTIONS in alphabetical order.

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 →