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

> Discover how Omarchy's CLI router uses longest-prefix matching with Bash associative arrays to efficiently dispatch commands to the correct sub-command scripts.

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

---

**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`:

```bash

# 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:

```bash

# 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:

```bash

# 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

```bash
$ 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)

```bash
$ 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

```bash
$ 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`](https://github.com/basecamp/omarchy/blob/main/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.