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.sockenforce natural access boundaries
Summary
- Omarchy CLI commands do not modify UI state directly — they forward requests through
omarchy-shell - The
omarchy-shellwrapper delegates toomarchy-ipc, which communicates via Unix domain socket at$XDG_RUNTIME_DIR/omarchy/shell.sock - Quickshell's
shell/shell.qmlreceives JSON requests and routes them to appropriate plugins undershell/plugins/ - Reply handling uses simple
ok/errorsemantics 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →