# How Omarchy CLIs Communicate with the Shell: IPC Architecture Explained

> Discover how Omarchy CLIs communicate with the shell using Unix domain sockets and JSON IPC. Learn how omarchy-shell forwards requests to Quickshell via omarchy-ipc.

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

---

**Omarchy CLI commands communicate with the shell through a Unix domain socket using a JSON IPC protocol, where `omarchy-shell` forwards requests to a running Quickshell instance via the `omarchy-ipc` binary.**

Omarchy provides numerous command-line utilities under `bin/` that control desktop behavior without direct kernel or display server access. The **Omarchy shell** — a thin wrapper around the Quickshell QML compositor — handles all UI-related requests through a centralized IPC mechanism. This article breaks down exactly how Omarchy CLI-to-shell communication works, with specific source references from the omacom/omarchy repository.

## The Communication Pipeline

Omarchy CLI commands follow a strict four-step flow to reach the running desktop environment. Each layer abstracts complexity while maintaining low-latency performance.

### Step 1: CLI Invokes the omarchy-shell Wrapper

Every user-facing command that modifies UI state — such as `omarchy-toggle-nightlight`, `omarchy-update-status`, or `omarchy-weather-location` — delegates to the helper script `bin/omarchy-shell`. This Bash wrapper parses arguments, optionally adds the `-q` (quiet) flag, and prepares the call for the IPC layer.

The wrapper does not implement business logic itself. It serves as a consistent entry point that normalizes command formatting across all Omarchy utilities.

### Step 2: omarchy-shell Delegates to omarchy-ipc

The wrapper constructs an IPC command line with this structure:

```bash
omarchy-shell <service> <method> [payload…]

```

It then executes the `omarchy-ipc` binary, which writes a JSON-encoded request to the Unix domain socket at:

```

$XDG_RUNTIME_DIR/omarchy/shell.sock

```

This socket path is shared with the QML side, ensuring both CLI and GUI components use identical transport.

### Step 3: Quickshell Routes to Service Plugins

Inside `shell/shell.qml`, the running Quickshell instance opens the socket and dispatches incoming requests to the appropriate **service plugin**. Plugins reside under `shell/plugins/` and implement method handlers for their domain.

For example, `shell/plugins/services/idle/Service.qml` receives calls like `lock isLocked` and executes the corresponding QML-implemented functionality.

### Step 4: Response Handling and Exit Codes

The `omarchy-ipc` binary reads the JSON reply from the socket and streams it to stdout. The wrapper script interprets this response:

| Reply | Behavior |
|-------|----------|
| `ok` | Success, exits 0 |
| `error` | Prints diagnostic message (e.g., "omarchy-shell is not ready"), exits 1 |

Because the socket is owned by the user who launched Quickshell, all communication stays within the same session boundary — no privilege escalation or cross-user exposure occurs.

## Key Source Files and Their Roles

| File | Path | Function |
|------|------|----------|
| CLI wrapper | `bin/omarchy-shell` | Argument parsing, flag handling, result interpretation |
| IPC client | `bin/omarchy-ipc` | Binary that serializes JSON and manages socket I/O |
| Shell entry point | `shell/shell.qml` | Socket listener, request router to plugins |
| Idle service | `shell/plugins/services/idle/Service.qml` | Example plugin implementing `lock`, `isLocked` methods |
| CLI contract docs | [`docs/omarchy-shell.md`](https://github.com/omacom/omarchy/blob/main/docs/omarchy-shell.md) | Protocol specification and flag documentation |

## Practical Usage Examples

### Toggle Night Light from Terminal

```bash

# Quietly enable the night-light service

omarchy-shell -q nightlight setEnabled true

```

The `-q` flag suppresses non-error output, suitable for scripting or keybind integration.

### Refresh Indicators Panel

```bash
omarchy-shell omarchy.indicators refresh

```

This triggers a manual refresh of the system indicators without waiting for automatic update cycles.

### Query Lock State

```bash

# Returns "true" or "false" to stdout

omarchy-shell lock isLocked

```

The raw boolean string enables shell conditional logic: `if [ "$(omarchy-shell lock isLocked)" = "true" ]; then …`.

### Custom Plugin Invocation

```bash

# Summon a user-defined widget with JSON payload

omarchy-shell shell summon mywidget '{"msg":"Hello"}'

```

This pattern allows third-party extensions to expose their own IPC methods through the same infrastructure.

## Design Benefits of the IPC Architecture

- **Lightweight CLIs**: Command implementations remain thin wrappers; complex state lives in the long-running Quickshell process
- **Centralized state**: No race conditions from multiple processes manipulating shared resources
- **Well-defined protocol**: JSON-over-socket provides extensibility and debugging visibility
- **Session security**: Unix permissions on `$XDG_RUNTIME_DIR/omarchy/shell.sock` enforce natural access boundaries

## Summary

- Omarchy CLI commands do not modify UI state directly — they forward requests through `omarchy-shell`
- The `omarchy-shell` wrapper delegates to `omarchy-ipc`, which communicates via Unix domain socket at `$XDG_RUNTIME_DIR/omarchy/shell.sock`
- Quickshell's `shell/shell.qml` receives JSON requests and routes them to appropriate plugins under `shell/plugins/`
- Reply handling uses simple `ok`/`error` semantics with standard exit codes for script integration
- All communication remains within the user session, with socket permissions providing security isolation

## Frequently Asked Questions

### What happens if Quickshell is not running when I run an omarchy-shell command?

The `omarchy-ipc` binary attempts to connect to the socket and fails. The wrapper script catches this, prints "omarchy-shell is not ready" to stderr, and exits with code 1. No partial state changes occur since the request never reaches a handler.

### Can I use omarchy-shell in shell scripts and keybindings?

Yes. The `-q` flag suppresses stdout for silent operation, and exit codes follow POSIX conventions (0 success, 1 error). The boolean-returning methods like `lock isLocked` output raw `true`/`false` strings ideal for `$(…)` substitution.

### Why use a separate omarchy-ipc binary instead of shell-only IPC?

The binary handles JSON serialization, socket lifecycle management, and protocol versioning in compiled code. This insulates shell scripts from formatting complexities and enables future protocol evolution without breaking user scripts that depend on `omarchy-shell` remaining stable.

### Where are new service plugins registered for IPC access?

Plugins under `shell/plugins/services/` expose methods through QML properties and functions. The routing logic in `shell/shell.qml` dynamically dispatches based on the service name in the IPC request. No central registration file is required — adding a new plugin directory with proper QML exports makes its methods automatically available to `omarchy-shell` callers.