How External Tools Communicate with the Omarchy Shell via IPC
External tools communicate with the Omarchy Shell via a Unix domain socket at $XDG_RUNTIME_DIR/omarchy-shell using JSON-RPC messages, either through the omarchy-shell CLI wrapper or direct socket connections.
The Omarchy Shell is a QML-based desktop environment built on Quickshell that exposes a lightweight inter-process communication (IPC) interface. This mechanism allows any external program—from Bash scripts to Python applications—to invoke methods on running shell services without direct library linking.
IPC Architecture and Socket Location
The shell creates a Unix domain socket at runtime to listen for incoming commands. By default, the socket resides at:
$XDG_RUNTIME_DIR/omarchy-shell(preferred)/run/user/$UID/omarchy-shell(fallback whenXDG_RUNTIME_DIRis unset)
The shell constantly monitors this socket for JSON-RPC-style messages formatted as JSON arrays. When a message arrives, the shell dispatches it to the appropriate internal service and returns a JSON response containing either a result or an error field.
Communication Methods
External tools can interface with the shell using two primary approaches depending on their complexity requirements.
Using the omarchy-shell CLI Wrapper
The bin/omarchy-shell script provides the simplest entry point for external communication. This helper handles socket connection management, JSON marshalling, and timeout enforcement automatically.
The wrapper reads command-line arguments, formats them into the required JSON structure, and writes to the socket. It respects the OMARCHY_SHELL_IPC_TIMEOUT environment variable to limit wait times for unresponsive shells.
# Toggle the main menu
omarchy-shell omarchy.menu toggle '{"menu":"root"}'
# Check lock status with a 200ms timeout
OMARCHY_SHELL_IPC_TIMEOUT=0.2s omarchy-shell lock status
Direct Socket Access
For applications requiring high-frequency communication or multiplexed requests, direct socket programming eliminates process-spawning overhead. Any language supporting Unix domain sockets can implement the protocol by connecting to the socket path and exchanging raw JSON messages.
This approach requires manual handling of:
- Socket connection and disconnection
- JSON serialization/deserialization
- Timeout logic implementation
Message Protocol and Format
All IPC communication follows a strict JSON array structure:
["<target>", "<method>", "<arg-1>", "<arg-2>", ...]
<target>: The registered service name (e.g.,omarchy.menu,omarchy.indicators,omarchy.clock)<method>: The specific operation exposed by that service (e.g.,toggle,refresh,set)<arg-*>: Optional arguments as strings or JSON-encoded objects
The shell responds with a JSON object:
{"result": "success"}
Or in case of errors:
{"error": "Service not found"}
Core Implementation Files
Understanding the source structure helps when debugging IPC issues or extending functionality.
-
bin/omarchy-shell: The primary CLI entry point that performs socket I/O, applies timeout logic viaOMARCHY_SHELL_IPC_TIMEOUT, and marshals arguments to/from JSON according to the protocol specification. -
src/OmarchShellIpc.cpp: The low-level C++ implementation handling socket creation, incoming message parsing, and response dispatching to registered QML services. -
shell/Ui/Panel.qml: UI components expose anipcTargetproperty that forwards QML-side interactions to the IPC layer, often usingQuickshell.execDetachedto invokeomarchy-shellwith appropriate target and method parameters. -
shell/services/PluginRegistry.qml: Registers dynamic plugin services with the IPC dispatcher, allowing plugins to declare customipcTargetidentifiers (e.g.,omarchy.weather) and implement corresponding methods discoverable by external callers.
Practical Integration Examples
Bash One-Liners
Use the helper command for quick scripting and cron jobs:
# Refresh the clock widget
omarchy-shell omarchy.clock refresh
# Set idle stay-awake state
omarchy-shell idle setStayAwake false
Python Socket Client
For direct integration without subprocess overhead:
import socket
import json
import os
runtime_dir = os.getenv('XDG_RUNTIME_DIR', f"/run/user/{os.getuid()}")
sock_path = os.path.join(runtime_dir, "omarchy-shell")
request = json.dumps(["lock", "status"]).encode('utf-8')
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:
s.connect(sock_path)
s.sendall(request + b'\n')
response = s.recv(4096).decode('utf-8')
print(json.loads(response))
Systemd Service Integration
Systemd units can invoke shell methods during system state changes:
[Unit]
Description=Dim screen when idle
After=omarchy-shell.service
[Service]
Type=oneshot
ExecStart=/usr/bin/omarchy-shell idle setStayAwake false
Configuring IPC Timeouts
Prevent scripts from hanging when the shell is not running:
# Fail after 500 milliseconds
OMARCHY_SHELL_IPC_TIMEOUT=0.5s omarchy-shell omarchy.indicators listPlugins
Summary
- The Omarchy Shell creates a Unix domain socket at
$XDG_RUNTIME_DIR/omarchy-shellfor JSON-RPC communication. - The
omarchy-shellCLI wrapper inbin/omarchy-shellprovides convenient socket access with timeout support viaOMARCHY_SHELL_IPC_TIMEOUT. - Messages follow the format
["target", "method", ...args]and receive JSON responses withresultorerrorfields. - QML components expose
ipcTargetproperties defined in files likeshell/Ui/Panel.qmland registered viashell/services/PluginRegistry.qml. - External tools can choose between simple CLI invocation or direct socket programming for optimal performance.
Frequently Asked Questions
Where is the IPC socket located?
The socket path defaults to $XDG_RUNTIME_DIR/omarchy-shell when the XDG_RUNTIME_DIR environment variable is defined. If unset, the shell falls back to /run/user/$UID/omarchy-shell where $UID represents the current user ID.
What programming languages can interface with the shell?
Any language capable of opening Unix domain sockets and parsing JSON can communicate directly with the shell. The repository shows working examples in Bash and Python, but Go, Rust, Node.js, or C applications can implement the same JSON-RPC protocol over the socket without restrictions.
How does the shell handle malformed IPC requests?
According to the protocol implementation in src/OmarchShellIpc.cpp, the shell validates incoming JSON arrays for correct structure. Malformed messages or requests targeting unregistered services receive JSON error responses containing an error field describing the failure, allowing callers to handle exceptions gracefully.
Can custom plugins expose their own IPC endpoints?
Yes. The shell/services/PluginRegistry.qml system allows plugins to declare unique ipcTarget identifiers and implement corresponding methods. Once registered, these targets become discoverable and callable via the same socket interface using the standard ["target", "method"] message format.
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 →