# How to Create a Custom Omarchy Command: A Complete Developer Guide

> Learn how to create a custom Omarchy command by following this developer guide. Discover how Omarchy finds and parses commands from your bin directory.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: how-to-guide
- Published: 2026-08-18

---

**Omarchy discovers custom commands by scanning the `bin/` directory for executables prefixed with `omarchy-` and parsing `# omarchy:` metadata comments to build the CLI namespace.**

Creating a custom Omarchy command allows you to extend the framework with bespoke functionality that appears as a first-class citizen in the CLI. The router, documented in [`docs/cli-router.md`](https://github.com/basecamp/omarchy/blob/main/docs/cli-router.md), automatically registers any properly formatted executable script found in the `bin/` directory or in a personal `$PATH` location like `$HOME/.local/bin`. This guide explains the metadata specification from [`agents/skills/command-metadata.md`](https://github.com/basecamp/omarchy/blob/main/agents/skills/command-metadata.md) and provides working examples you can deploy immediately.

## Understanding the Command Discovery System

Omarchy employs a file-based routing system that requires zero configuration files. The CLI router scans the **`bin/`** directory for any file beginning with the `omarchy-` prefix. When it locates a matching executable, it reads the embedded **metadata comments**—lines beginning with `# omarchy:`—to determine how the command should be presented in the help system and what arguments it accepts.

This metadata is parsed lazily, meaning the router only inspects a script when the command is actually invoked. The system constructs a flat command namespace following the pattern `omarchy <group> <verb>`, where the group and verb are derived from the filename or overridden by metadata fields. For validation, the test suite runs `omarchy commands --check`, which verifies that each discovered file is executable and that its metadata conforms to the schema defined in [`agents/skills/command-metadata.md`](https://github.com/basecamp/omarchy/blob/main/agents/skills/command-metadata.md).

## Step-by-Step Guide to Creating a Custom Omarchy Command

### 1. Select a Command Name

Choose a descriptive name for your command. The physical filename must follow the convention `omarchy-<name>`. For example, a command invoked as `omarchy hello` requires a file named `omarchy-hello`.

### 2. Create the Executable Script

Place your script in the repository’s `bin/` directory, or alternatively in `$HOME/.local/bin` if the directory is on your `$PATH`. Begin the file with a shebang line followed by metadata comments that describe the command’s behavior to the router.

### 3. Embed Metadata Comments

Add structured comments at the top of your script using the `# omarchy:` prefix. The most common fields include:

- **`summary`** – A short description displayed in `omarchy commands` output
- **`args`** – Usage hints shown in help text (e.g., `<host>` or `[name]`)
- **`group`** – Optional categorization; defaults to the script name if omitted
- **`name`** – Override the sub-command name if it differs from the filename
- **`requires-sudo`** – Set to `true` to automatically prompt for elevation
- **`hidden`** – Set to `true` to exclude the command from standard help listings

### 4. Set Executable Permissions

Run `chmod +x bin/omarchy-<name>` to ensure the router can execute the file.

### 5. Validate Registration

Execute `omarchy commands --check` to verify the metadata is well-formed, or test the command directly with `omarchy <name> --help` to view the generated help text.

## Practical Code Examples

### Minimal "Hello World" Command

This example demonstrates basic metadata usage and argument handling:

```bash
#!/usr/bin/env bash

# omarchy:summary=Print a friendly greeting

# omarchy:args=[name]          # optional argument shown in help

# omarchy:examples=omarchy hello Alice

name=${1:-World}
echo "Hello, $name!"

```

Place this as `bin/omarchy-hello`, make it executable, and invoke:

```bash
$ omarchy hello
Hello, World!
$ omarchy hello Bob
Hello, Bob!

```

### Command Requiring Sudo Privileges

For system-level operations, use the `requires-sudo` metadata field to trigger automatic elevation:

```bash
#!/usr/bin/env bash

# omarchy:summary=Refresh the system time service

# omarchy:requires-sudo=true

# omarchy:examples=omarchy time-sync

systemctl restart systemd-timesyncd
echo "Time synchronization restarted."

```

Saved as `bin/omarchy-time-sync`, this script will prompt for sudo authentication when executed via `omarchy time-sync`, as dictated by the router’s privilege-checking logic.

### Grouped Commands with Custom Names

You can organize related commands under a common group using the `group` and `name` fields:

```bash
#!/usr/bin/env bash

# omarchy:group=network

# omarchy:name=ping

# omarchy:summary=Ping a host and colour‑code the result

# omarchy:args=<host>

# omarchy:examples=omarchy network ping example.com

host=$1
if [[ -z $host ]]; then
  echo "Usage: omarchy network ping <host>"
  exit 1
fi

ping -c 3 "$host" && echo "✅ reachable" || echo "❌ unreachable"

```

This registers the command as `omarchy network ping` rather than `omarchy ping`. The `omarchy-windows-vm` script in the repository demonstrates similar advanced grouping and metadata usage.

### Hidden Helper Scripts

For internal utilities that should not appear in the default help output:

```bash
#!/usr/bin/env bash

# omarchy:summary=Internal hook used by other commands

# omarchy:hidden=true

# …implementation…

```

Hidden scripts remain accessible via `omarchy commands --all` but are excluded from the standard help table, making them ideal for shared utility functions invoked by other commands.

## File Locations and Best Practices

According to [`docs/file-layout.md`](https://github.com/basecamp/omarchy/blob/main/docs/file-layout.md), custom commands belong in the `bin/` directory relative to `$OMARCHY_PATH`. However, the router also respects personal scripts placed in `$HOME/.local/bin` provided the directory is included in your `$PATH` environment variable.

When iterating on a new command, remember that the lazy-loading architecture means you can edit the script and test changes immediately without restarting the Omarchy desktop session. The validation command `omarchy commands --check` (referenced in the test suite) ensures your metadata syntax matches the specification in [`agents/skills/command-metadata.md`](https://github.com/basecamp/omarchy/blob/main/agents/skills/command-metadata.md), catching malformed fields before they reach production.

## Summary

- **Discovery mechanism**: Omarchy scans `bin/` for files matching `omarchy-*` and extracts `# omarchy:` metadata comments

- **Required setup**: Create an executable script with a `omarchy-` prefix and appropriate metadata fields
- **Key metadata fields**: `summary`, `args`, `group`, `name`, `requires-sudo`, and `hidden` control help text and routing behavior
- **Validation**: Use `omarchy commands --check` to verify executability and metadata well-formedness
- **Flexibility**: Commands work from either the repository `bin/` directory or personal `$HOME/.local/bin` paths

## Frequently Asked Questions

### Where does Omarchy look for custom commands?

Omarchy searches the **`bin/`** directory within the repository and any directory in your `$PATH` (such as `$HOME/.local/bin`) for executable files starting with `omarchy-`. The router builds the command namespace dynamically from these locations as documented in [`docs/cli-router.md`](https://github.com/basecamp/omarchy/blob/main/docs/cli-router.md).

### What metadata fields are available for Omarchy commands?

The metadata specification in [`agents/skills/command-metadata.md`](https://github.com/basecamp/omarchy/blob/main/agents/skills/command-metadata.md) supports fields including **`summary`** (description), **`args`** (usage syntax), **`group`** (category), **`name`** (sub-command override), **`requires-sudo`** (privilege escalation), and **`hidden`** (visibility control). All fields are optional but recommended for user-facing commands.

### How do I test if my custom command is valid?

Run **`omarchy commands --check`** to validate that your script is executable and that its `# omarchy:` metadata comments are well-formed. You can also test the help generation by running `omarchy <your-command> --help` to see how the router interprets your metadata.

### Can I write custom Omarchy commands in languages other than Bash?

Yes. The router treats any executable file matching the `omarchy-*` naming convention as a valid command, regardless of the interpreter specified in the shebang line. You can use Python, Ruby, Go binaries, or any other executable format provided the file has the correct permissions and metadata comments.