# How Omarchy’s CLI Performs Prefix Listing and Suggestions

> Discover how Omarchy's CLI dynamically lists commands by scanning bin files and suggests corrections using a Levenshtein algorithm for unmatched inputs.

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

---

**The Omarchy CLI dynamically discovers available commands by scanning the `bin/` directory for executables following the `omarchy-<group>-<cmd>` naming convention, builds command routes by parsing user arguments against these prefixes, and suggests corrections using a Levenshtein-distance-based algorithm when inputs do not match known binaries.**

The `basecamp/omarchy` repository implements a modular command-line interface where functionality is partitioned into discrete scripts rather than a monolithic binary. Understanding how Omarchy CLI performs prefix listing and suggestions requires examining the Bash-based routing logic in the main entry point and the filesystem discovery mechanisms that map user input to executable files.

## Understanding the Prefix Discovery Mechanism

At the core of Omarchy's extensibility lies a filesystem-based command discovery system that treats the `bin/` directory as a living registry.

### Scanning the Binary Directory

When initializing the command environment, the CLI iterates over all files matching the `omarchy-*` pattern within `$OMARCHY_BIN_DIR` (typically the repository's `bin/` folder). This glob-based scan identifies every potential command group:

```bash
for file in "$OMARCHY_BIN_DIR"/omarchy-*; do

```

According to the source code in [`bin/omarchy` at line 316](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy#L316), this loop captures all executables prefixed with `omarchy-`, establishing the foundation for the command hierarchy. The script filters for actual executables, ensuring only valid binaries populate the internal command registry.

### Grouping Commands by Prefix

For each discovered group, the system performs a secondary scan to identify sub-commands. When resolving a specific group, the CLI searches for binaries matching `omarchy-$group-*`:

```bash
for file in "$OMARCHY_BIN_DIR/omarchy-$group"-*; do

```

As implemented at [line 345 in `bin/omarchy`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy#L345), this nested iteration enables nested command structures like `omarchy theme list` or `omarchy server start`, where `theme` and `server` represent groups and `list`/`start` represent specific actions within those groups.

## Building and Resolving Command Routes

Once the available command space is mapped, the CLI interprets user input by constructing candidate routes and verifying their existence against the filesystem.

### Parsing Argument Prefixes

The routing logic splits user arguments into a **prefix count**—the number of arguments forming the command path—and the remaining parameters. The system constructs two critical variables:

```bash
route="omarchy $(join_words " " "${args[@]:0:prefix_count}")"
binary="omarchy-$(join_words "-" "${args[@]:0:prefix_count}")"

```

Lines [397](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy#L397) and [399](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy#L399) in `bin/omarchy` demonstrate this dual construction: `route` generates the human-readable command string, while `binary` constructs the actual filename (with hyphens replacing spaces) that the system attempts to execute.

### Binary Resolution Logic

Before executing, the CLI validates that the constructed binary exists and is executable:

```bash
[[ -x $OMARCHY_BIN_DIR/omarchy-$group ]] && return 0

```

This check at [line 355](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy#L355) ensures the script exits early with success only when a matching executable file exists. If validation fails, control passes to the suggestion engine rather than attempting execution.

## Command Suggestion Engine

When argument parsing fails to resolve to a valid binary, Omarchy provides intelligent feedback through fuzzy string matching.

### The suggest_command Function

The CLI delegates correction suggestions to a dedicated helper function:

```bash
suggestion=$(suggest_command "${args[0]}")

```

Located at [line 1063 in `bin/omarchy`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy#L1063), this function iterates through all known command binaries and calculates similarity scores between the user's input and available commands.

### Fuzzy Matching Implementation

The suggestion engine employs a **Levenshtein distance** algorithm to determine the closest match. When a sufficiently similar command is identified, the CLI outputs a diagnostic message:

```bash
if [[ -n $suggestion ]]; then
    echo "Did you mean: omarchy $suggestion ?" >&2
fi

```

As shown at [line 1065](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy#L1065), this pattern provides immediate value to users who mistype commands, offering corrections like suggesting `omarchy theme list` when the user enters `omarchy them list`.

## Listing Available Commands

Beyond reactive suggestions, the CLI provides proactive discovery through the `omarchy commands` interface. This functionality leverages the same prefix scanning logic used during route building but formats output for human or machine consumption:

```bash

# Display all commands including hidden internals

omarchy commands --all

# Export command metadata as JSON

omarchy commands --json

```

The listing mechanism relies on the directory scanning routines established in the prefix discovery phase, ensuring the command catalogue always reflects the current state of the `bin/` directory without requiring manual registry updates.

## Summary

- **Filesystem-based discovery**: The CLI scans `$OMARCHY_BIN_DIR` for `omarchy-*` patterns to dynamically build the command registry from executable scripts.
- **Prefix parsing**: User arguments are split into route components using `prefix_count`, constructing human-readable routes and filesystem-compatible binary names via `join_words`.
- **Validation logic**: The system verifies binary existence and executability at line 355 before attempting invocation.
- **Fuzzy suggestions**: The `suggest_command` function implements Levenshtein-distance matching to recommend corrections when inputs fail validation.
- **Dynamic listing**: The `omarchy commands` subcommand provides real-time inventory of available functionality using the same discovery mechanisms.

## Frequently Asked Questions

### How does Omarchy handle nested command groups like `omarchy theme install`?

Omarchy treats hyphen-separated filename components as hierarchical paths. When resolving `omarchy theme install`, the system scans for binaries matching `omarchy-theme-*`, identifying `install` as a valid sub-command within the `theme` group. This convention allows arbitrary nesting depth by simply naming files `omarchy-group-subcommand` and placing them in the `bin/` directory.

### What algorithm does the suggestion engine use to recommend corrections?

The `suggest_command` function utilizes a **Levenshtein distance** calculation to measure string similarity between the user's input and all known command names. It returns the binary name with the smallest edit distance, enabling robust typo correction for commands like suggesting `list` when the user types `lsit`.

### Can I add new commands without modifying the core CLI script?

Yes. The architecture supports zero-configuration extensibility. Adding a new command requires only creating an executable file following the `omarchy-<group>-<cmd>` naming convention in the `bin/` directory. The prefix discovery mechanism automatically includes new binaries in the next CLI invocation without requiring registration in a central manifest.

### Why does the CLI use filesystem scanning instead of a static command list?

Scanning the `bin/` directory enables **dynamic extensibility** and eliminates synchronization errors between the codebase and command registry. As implemented in `basecamp/omarchy`, this approach allows third-party plugins or local customizations to inject functionality simply by dropping executable scripts into the path, ensuring the `omarchy commands` listing always reflects the actual available binaries.