How CLIs Communicate with a Running Quickshell Instance: The Complete IPC Breakdown

Omarchy's command-line tools communicate with the active Quickshell process through the Quickshell IPC interface, using Unix-domain sockets via the qs ipc subcommand.

Omarchy's CLI architecture separates the command-line experience from the graphical shell runtime. When you run commands like omarchy-theme-set or omarchy-system-sleep-lock, these tools don't manipulate files directly—they send structured messages to the live Quickshell instance through its inter-process communication (IPC) system. This article explains exactly how that communication works, with reference to the actual implementation in the omacom/omarchy repository.

The Core IPC Mechanism: qs ipc and omarchy-shell

All Quickshell CLI communication in Omarchy flows through a single wrapper script: bin/omarchy-shell. This script constructs the canonical IPC command that every tool uses.

The IPC Command Structure

The underlying invocation follows this pattern:

qs ipc -n -p "$OMARCHY_PATH/shell" call -- <target> <action> [arguments…]

Each component serves a specific purpose:

Component Purpose
qs The Quickshell binary executable
ipc Subcommand that opens a Unix-domain socket to the running instance
-n Non-interactive mode (no TTY required)
-p "$OMARCHY_PATH/shell" Socket path—locates the Unix socket under Omarchy's installation
call -- Initiates a call transaction; -- separates qs flags from payload arguments
<target> The QML service registered in Quickshell (e.g., shell, notifications, media)
<action> Method to invoke on that target
[arguments…] JSON-encoded parameters passed to the action

The shell/README.md documents this syntax as the canonical pattern, with the example:

quickshell ipc -p $OMARCHY_PATH/shell call shell ping

IPC Targets and Their Capabilities

Quickshell exposes multiple IPC targets that correspond to major subsystem services. Each target is implemented as a QML object that registers itself with the IPC system.

The shell Target

The shell target is defined in shell/shell.qml and provides core system operations:

Method Purpose
ping Health check; returns ok
applyTheme Applies color and shell configuration JSON
listPlugins Returns JSON array of loaded plugins
debugBarGeometry Returns diagnostic positioning data

Plugin management specifically delegates to shell/services/PluginRegistry.qml, which implements listPlugins, setPluginEnabled, and related methods.

The notifications Target

Handles Do-Not-Disturb state and OSD messaging:

Method Parameters Returns
setDnd true / false Confirmation string
getDnd none "on" or "off"

The osd Target

Controls on-screen display overlays:

Method Parameters
show JSON object with message, duration (seconds), optional styling

Practical CLI Communication Examples

Health Check: Pinging the Running Shell

omarchy-shell shell ping

# → ok

This verifies that Quickshell is running and responsive. The test/shell.d/runtime-smoke-test.sh test suite uses this as its first validation step.

Applying Themes from CLI Scripts

The bin/omarchy-theme-set script demonstrates multi-argument IPC calls:

#!/bin/bash

colors_payload='{"accent":"#ff6600","background":"#1e1e2e","foreground":"#cdd6f4"}'
shell_payload='{"bar":{"height":24,"position":"top"},"gaps":{"inner":8,"outer":4}}'

omarchy-shell shell applyTheme "$colors_payload" "$shell_payload"

applyTheme receives two JSON objects: color definitions and shell geometry settings. Quickshell applies these without restart.

Toggling Do-Not-Disturb


# Enable DND

omarchy-shell notifications setDnd true

# Check current state

omarchy-shell notifications getDnd

# → on

Listing Loaded Plugins with JSON Processing

omarchy-shell shell listPlugins | jq '.[] | select(.enabled) | .name'

The shell/services/PluginRegistry.qml implementation returns a structured array that CLI tools can filter and transform.

Displaying Custom OSD Messages

omarchy-shell osd show '{"message":"Recording started","duration":3,"icon":"media-record"}'

Response Handling and Error Semantics

CLIs communicate with a running Quickshell instance synchronously—each call blocks until the IPC roundtrip completes. Responses follow consistent patterns:

Response Meaning
ok Success, no data returned
unknown Target or action not found
JSON object Structured data (plugin lists, geometry, etc.)
Error string Exception message from QML execution

The bin/omarchy-shell wrapper handles exit codes: non-zero if the Quickshell binary fails or returns unknown, zero on ok or valid JSON.

Architecture Summary: From CLI to QML

The complete communication flow:

  1. User invokes omarchy-theme-set or another CLI tool
  2. Tool sources bin/omarchy-shell (or constructs equivalent qs ipc … command)
  3. qs ipc connects to Unix socket at $OMARCHY_PATH/shell
  4. Quickshell's IPC system routes to the named <target> QML object
  5. QML method executes, modifying runtime state or querying internal data
  6. Textual response returns through the socket
  7. CLI parses response and presents user-friendly output

This design means Omarchy's shell remains fully scriptable without file-watching hacks or configuration reloads. The same IPC mechanism powers both interactive commands and the automated test suite in test/shell.d/runtime-smoke-test.sh, which exercises ping, summon, status, and other IPC surface area.

Summary

  • Entry point: bin/omarchy-shell wraps all Quickshell IPC operations
  • Transport: Unix-domain sockets via qs ipc -p $OMARCHY_PATH/shell
  • Protocol: Textual call -- <target> <action> [args…] with JSON payloads
  • Key targets: shell (core), notifications (DND/OSD), osd (overlays), media (playback)
  • Implementation: QML objects in shell/shell.qml and shell/services/*.qml register themselves as IPC targets
  • Testing: test/shell.d/runtime-smoke-test.sh validates the full IPC surface

Frequently Asked Questions

What happens if Quickshell isn't running when I run a CLI command?

The qs ipc command fails with a connection error and non-zero exit status. CLI scripts that source bin/omarchy-shell will surface this as a failure. Some tools may fall back to file-based configuration changes that apply on next launch, but runtime IPC commands require an active Quickshell instance.

Can I extend the IPC system with custom targets?

Yes. Any QML object in the Quickshell hierarchy can expose IPC methods by integrating with the same registration pattern used in shell/services/PluginRegistry.qml. Your custom service becomes callable via omarchy-shell <your-target> <your-method> once registered.

How does this differ from D-Bus or other IPC mechanisms?

Quickshell uses its own lightweight Unix-socket protocol rather than D-Bus. This avoids D-Bus dependencies and matches Quickshell's single-process architecture. The -p flag lets multiple Quickshell instances coexist with isolated socket paths—critical for multi-user or testing scenarios demonstrated in test/shell.d/runtime-smoke-test.sh.

Where is the socket file located?

The socket path is $OMARCHY_PATH/shell, typically resolving to something like /home/user/.local/share/omarchy/shell or your custom installation prefix. The -n flag ensures qs doesn't require a controlling terminal, enabling script and service integration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →