How Omarchy CLIs Communicate with the Shell: IPC Architecture Explained

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:

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 Protocol specification and flag documentation

Practical Usage Examples

Toggle Night Light from Terminal


# 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

omarchy-shell omarchy.indicators refresh

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

Query Lock State


# 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


# 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.

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 →