# How Shell IPC Works Between Omarchy bin/ Scripts and the Quickshell Instance

> Learn how Omarchy shell IPC works between bin/ scripts and Quickshell. Discover how JSON payloads are marshaled through Unix-domain sockets for execution via the quickshell ipc command.

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

---

**Omarchy's command-line tools marshal JSON payloads through a Unix-domain socket, delegating execution to the Quickshell daemon via the `omarchy-shell` helper and `quickshell ipc` command.**

The Omarchy desktop environment uses a decentralized architecture where lightweight shell scripts in `bin/` communicate asynchronously with the running Quickshell instance. This **shell IPC** mechanism relies on a Unix-domain socket transport layer, allowing CLI utilities to trigger QML service actions without blocking the user interface.

## The IPC Architecture Overview

Omarchy's IPC stack consists of three distinct layers: the command-line wrapper, the socket transport helper, and the QML service registry. When you execute an `omarchy` command, the request traverses from Bash through a JSON-encoded socket message to a specific QML service implementation.

The transport uses `$XDG_RUNTIME_DIR/quickshell.sock` as the communication endpoint. This design keeps the desktop shell responsive while exposing a synchronous-feeling interface to shell scripts and external tools.

## Step-by-Step Message Flow

### Step 1: CLI Wrapper Builds the JSON Payload

The entry point at **`bin/omarchy`** parses sub-commands and constructs a compact JSON object describing the requested operation. For example, an OSD command generates a payload like `{cmd: "osd.show", args: {icon: "󱓞", message: "Hello world", duration: 3000}}`.

Once serialized, the script invokes the **`omarchy-shell`** binary, passing the target service ID and the JSON string as arguments. This abstraction keeps the main CLI logic separate from the underlying transport mechanics.

### Step 2: Socket Transmission via omarchy-shell

The **`bin/omarchy-shell`** helper executes the `quickshell ipc send` command, which writes the JSON payload to Quickshell's Unix-domain socket at `$XDG_RUNTIME_DIR/quickshell.sock`. This low-level transport is handled by the Quickshell CLI tool, ensuring atomic message delivery to the daemon.

The helper blocks until the daemon acknowledges receipt, providing synchronous error handling for the calling script while the actual work happens asynchronously inside the QML runtime.

### Step 3: Quickshell Daemon Routing

Upon receiving the socket message, the Quickshell daemon decodes the JSON and routes it through **`shell/services/PluginRegistry.qml`**. This registry maintains a map of service IDs to QML component instances, dynamically loading plugins from the `shell/plugins/` directory.

The registry extracts the `cmd` field to determine the target service (e.g., `osd`, `nightlight`, `media`) and invokes the corresponding method on the registered QML object. This hot-reloadable architecture allows adding new IPC endpoints without restarting the desktop shell.

### Step 4: Service Execution

The targeted QML service—such as **`shell/plugins/services/media/Service.qml`** or **`shell/plugins/services/nightlight/Service.qml`**—executes the requested action. Services leverage Quickshell APIs like **`Quickshell.execDetached`** to spawn external processes without blocking the UI thread, or **`Quickshell.Hyprland`** to manipulate Wayland compositor state.

For resource resolution, services call **`Quickshell.iconPath`** to locate themed icons, ensuring consistent visual presentation across CLI-triggered actions.

### Step 5: Result Feedback

If the command expects a return value, the service writes a response JSON back to the socket. The `omarchy-shell` wrapper reads this reply and exits with the appropriate status code, which the original `bin/omarchy` script forwards to the user. This round-trip maintains the standard Unix exit-code contract while operating over an asynchronous message bus.

## Key Implementation Details

### Environment Propagation

The QML root at **`shell/shell.qml`** injects critical environment variables into the Quickshell runtime using **`Quickshell.env`**. This includes `HOME`, `OMARCHY_PATH`, and `XDG_RUNTIME_DIR`, ensuring that child processes spawned via `Quickshell.execDetached` inherit the correct configuration context to locate resources and execute subsequent `omarchy` commands.

### Service Registration Protocol

Each plugin under `shell/plugins/services/*/` declares a unique `serviceId` in its QML metadata. The `PluginRegistry` scans the `pluginsDir` at startup, registering each service under its ID. The CLI uses this namespace to address commands (`omarchy <service-id> <action>`), creating a discoverable, modular command structure.

## Practical Examples

Trigger a transient OSD notification:

```bash
omarchy osd show '{"icon":"󱓞","message":"Hello world","duration":3000}'

```

This executes the full IPC pipeline: `bin/omarchy` builds the payload, `bin/omarchy-shell` transmits it via `quickshell ipc`, the registry routes to the OSD service, and **`shell/plugins/services/osd/Service.qml`** renders the notification using `Quickshell.execDetached`.

Toggle the night-light service:

```bash
omarchy nightlight toggle

```

Here, the target is **`shell/plugins/services/nightlight/Service.qml`**, which toggles the Wayland night-light state through the `Quickshell.Hyprland` API rather than spawning external processes.

## Summary

- **Transport Layer**: Uses `$XDG_RUNTIME_DIR/quickshell.sock` via the `quickshell ipc` command for reliable Unix-domain socket communication.
- **Entry Points**: `bin/omarchy` parses CLI arguments and `bin/omarchy-shell` handles socket transmission.
- **Routing**: `shell/services/PluginRegistry.qml` dynamically dispatches JSON commands to registered QML services.
- **Execution**: Services utilize `Quickshell.execDetached` and `Quickshell.Hyprland` to perform actions without blocking the UI.
- **Environment**: `shell/shell.qml` propagates critical env vars via `Quickshell.env` to ensure resource paths resolve correctly in spawned processes.

## Frequently Asked Questions

### How does the `omarchy` CLI find the running Quickshell instance?

The `omarchy-shell` helper locates the active session through the `$XDG_RUNTIME_DIR/quickshell.sock` Unix-domain socket. This path is determined by the Quickshell daemon on startup and is predictable within the user's runtime directory, eliminating the need for PID files or D-Bus registration.

### Can I call Quickshell services from custom shell scripts?

Yes. Any script can invoke `omarchy-shell <service-id> '<json-payload>'` to send commands to the desktop. The JSON format follows the `{cmd: "...", args: {...}}` schema expected by **`shell/services/PluginRegistry.qml`**, allowing custom integrations with Omarchy's service layer.

### What happens if the Quickshell daemon is not running?

If the socket at `$XDG_RUNTIME_DIR/quickshell.sock` does not exist, the `quickshell ipc` command invoked by `bin/omarchy-shell` will fail with a connection error, and the wrapper exits with a non-zero status. The `bin/omarchy` script propagates this failure, alerting the user that the desktop environment is inactive.

### Where are new IPC services defined?

New services are implemented as QML files in **`shell/plugins/services/`**, each declaring a unique `serviceId`. The **`shell/services/PluginRegistry.qml`** automatically discovers and registers these components at runtime, enabling hot-reloading of functionality without restarting the IPC infrastructure.