# Omarchy Two-Pass Dispatch: How the CLI Router Resolves Commands

> Understand Omarchy's two-pass dispatch CLI router. It prioritizes exact filename matches and uses metadata resolution as a fallback for efficient command routing.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: internals
- Published: 2026-09-03

---

**Omarchy's CLI router uses a two-pass dispatch system that first probes for exact filename matches, then falls back to metadata-driven route resolution only when needed.**

Omarchy's command-line interface centers on a router located at `bin/omarchy` that transforms spaced user commands into executable binaries following the `bin/omarchy-*` naming convention. The **Omarchy two-pass dispatch** mechanism balances speed with flexibility, ensuring common commands execute instantly while still supporting aliases, renames, and complex routing rules. This design avoids caching overhead and keeps startup latency minimal for the majority of invocations.

## The Two-Pass Dispatch Architecture

The router resolves every command through two distinct phases. Understanding both passes is essential for debugging routing issues or extending Omarchy's command set.

### Pass 1: Fast-Path Filename Probe

The router's **hot path** performs direct filesystem checks without loading any metadata.

It joins the supplied arguments with hyphens and tests whether an executable exists at that exact path. The probe works from most-specific to least-specific, dropping one trailing word at a time.

```bash

# Command: omarchy theme set foo

# Probe order:

# 1. bin/omarchy-theme-set-foo  (if exists, execute)

# 2. bin/omarchy-theme-set      (if exists, execute with "foo" as argument)

# 3. Proceed to metadata fallback

```

This pass executes entirely through `stat` system calls—no file parsing, no memory allocation for route tables. According to the router documentation at lines 49-56, this design targets the common case where commands map directly to existing binaries.

### Pass 2: Metadata Fallback Resolution

When the fast-path finds no match, the router lazily loads metadata from **all** `omarchy-*` binaries and builds a complete route table.

The fallback implements the same **longest-prefix matching** rule: drop trailing words until a registered route matches, with dropped words becoming the command's arguments. As documented at lines 62-66, this secondary pass enables:

- Command aliases and redirects
- Metadata-driven renames
- Hidden or contextual commands

The lazy loading ensures this heavier work only occurs for the minority of invocations that need it.

## Core Dispatch Mechanics

### Longest-Prefix Resolution Rule

Both passes apply identical semantics for argument handling. The router strips words from the right until resolution succeeds, as specified at lines 49-51 of [`docs/cli-router.md`](https://github.com/omacom/omarchy/blob/main/docs/cli-router.md):

```bash
omarchy theme set dark active

# Tries: theme-set-dark-active → theme-set-dark → theme-set

# On match "theme-set", passes ["dark", "active"] as arguments

```

### Help Interception

The router traps `--help` and `-h` flags **during both passes**, regardless of where they appear in remaining arguments. This ensures help displays before any binary executes, as noted at lines 67-70:

```bash
omarchy update aur --help

# Fast-path resolves to bin/omarchy-update

# Help flag caught, displays aur subcommand help

```

### Bare-Invocation Guard

Commands declaring required arguments trigger a usage display when invoked without them. Documented at lines 76-80, this guard prevents partial execution:

```bash
omarchy theme set

# "set" declares required arguments, none provided

# → Shows usage instead of launching setter

```

### Execution Model

Once resolved, the router uses **`exec`** to replace its own process with the target binary. Only leftover arguments pass through—redundant routing words are stripped. The router exits with code `127` for unknown routes or missing binaries, as described at lines 82-84.

## Practical Examples

### Fast-Path Execution

```bash

# Direct filename match exists

omarchy theme set dark

# → exec bin/omarchy-theme-set with ["dark"]

```

### Metadata Fallback Execution

```bash

# No bin/omarchy-share exists

omarchy share

# → Metadata scan finds route table entry

# → Resolves to bin/omarchy-menu-share, executes

```

### Nested Command Routing

```bash
omarchy pkg install --verbose neovim

# Pass 1: probes bin/omarchy-pkg-install-verbose-neovim → no

#         probes bin/omarchy-pkg-install-verbose → no

#         probes bin/omarchy-pkg-install → yes

# → exec bin/omarchy-pkg-install with ["--verbose", "neovim"]

```

## Key Source Files

- **`bin/omarchy`** — The main router script implementing two-pass dispatch, located at the repository root.
- **[`docs/cli-router.md`](https://github.com/omacom/omarchy/blob/main/docs/cli-router.md)** — Authoritative documentation covering resolution rules, pass ordering, and execution semantics.
- **[`agents/skills/command-metadata.md`](https://github.com/omacom/omarchy/blob/main/agents/skills/command-metadata.md)** — Defines metadata keys (`omarchy:name`, `omarchy:hidden`, `omarchy:alias`) that drive the fallback pass.

## Summary

- **Omarchy two-pass dispatch** prioritizes speed: most commands resolve through simple filename probes without parsing overhead.
- The **fast-path** uses hyphen-joined argument strings to test executable existence via `stat` calls.
- The **metadata fallback** lazily builds a route table from binary comment headers, enabling aliases and renames.
- Both passes share **longest-prefix matching** and **help interception** semantics.
- Successful resolution triggers **`exec`** replacement; failures exit with code `127`.

## Frequently Asked Questions

### What triggers the metadata fallback pass in Omarchy's router?

The metadata fallback activates only when the fast-path probe finds no matching executable. If you run `omarchy share` and `bin/omarchy-share` does not exist, the router scans all `omarchy-*` binaries, extracts their metadata headers, and builds a route table to find a registered alias or renamed command.

### How does Omarchy handle help flags in subcommands?

The router intercepts `--help` or `-h` in both passes, regardless of position. If you run `omarchy update aur --help`, the fast-path resolves to `bin/omarchy-update`, detects the help flag among remaining arguments, and displays help for the `aur` subcommand before any binary executes.

### Why does Omarchy use exec instead of spawning subprocesses?

Using `exec` replaces the router process entirely with the target binary. This eliminates process overhead, preserves signal handling and file descriptors naturally, and ensures the executed command receives only the relevant arguments—routing words already consumed by resolution never reach the child.

### Can a command in Omarchy have required arguments?

Yes. Commands declare requirements in their metadata. If invoked without sufficient arguments—`omarchy theme set` with no theme name—the bare-invocation guard triggers and displays usage information instead of executing the binary. This is documented at lines 76-80 of [`docs/cli-router.md`](https://github.com/omacom/omarchy/blob/main/docs/cli-router.md).