Subscriptions & Events
Subscribe to real-time state change events from OmniWM.
Delivery Pipeline
Section titled “Delivery Pipeline”IPCServer.start() attaches IPCApplicationBridge to WMController. Controller state changes publish channel snapshots through the bridge, and IPCConnection expands the requested channels for each client, sends the initial subscribe response, starts per-channel stream tasks, and emits initial snapshots unless --no-send-initial is set.
Initial snapshots are best-effort seed state, not a strict ordering barrier. If state changes during subscription setup, a live update can race with the initial snapshot.
Subscription channels are coalesced state streams, not a lossless event log. Slow consumers may only observe the newest buffered update for a channel.
Workspace-bar and IPC projection work is only produced when the UI or IPC currently has active consumers; core window relayout is not consumer-gated.
Channels
Section titled “Channels”| Channel | Result Type | Description |
|---|---|---|
focus |
focused-window | Focused window snapshot updates |
workspace-bar |
workspace-bar | Workspace bar projection updates |
active-workspace |
active-workspace | Interaction monitor and active workspace updates |
focused-monitor |
focused-monitor | Focused monitor updates |
windows-changed |
windows | Managed window inventory updates |
display-changed |
displays | Display state updates |
layout-changed |
workspaces | Workspace layout updates |
subscribe
Section titled “subscribe”Stream the subscribe response and subsequent events to stdout as JSON.
omniwmctl subscribe <channels> [--no-send-initial]omniwmctl subscribe --all [--no-send-initial]Channels are specified as a comma-separated list or with --all for all channels.
| Flag | Description |
|---|---|
--all |
Subscribe to all channels |
--no-send-initial |
Skip sending initial state snapshot |
Output is always JSON. Stdout begins with a single pretty-printed IPCResponse envelope with kind: "subscribe" and status: "subscribed". After that, OmniWM emits a best-effort initial state snapshot for each subscribed channel unless --no-send-initial is used, followed by live IPCEventEnvelope updates as they occur.
Examples:
# Watch focus changesomniwmctl subscribe focus
# Watch all eventsomniwmctl subscribe --all
# Watch workspace and window changes without initial stateomniwmctl subscribe active-workspace,windows-changed --no-send-initialSubscribe to events and execute a command for each event received. The event data is passed to the child process on stdin.
omniwmctl watch <channels> [--no-send-initial] --exec <command> [args...]omniwmctl watch --all [--no-send-initial] --exec <command> [args...]The --exec flag is required and marks the boundary between watch flags and the child command. Everything after --exec is the child command and its arguments.
watch consumes the subscribe handshake client-side instead of printing it. It runs one child process per event, waits for that child to finish before handling the next event, writes exactly one NDJSON event line to the child’s stdin, and reports non-zero child exits to stderr without terminating the watcher.
Environment variables passed to child process:
| Variable | Description |
|---|---|
OMNIWM_EVENT_CHANNEL |
Subscription channel name (e.g., focus) |
OMNIWM_EVENT_KIND |
Event result kind |
OMNIWM_EVENT_ID |
Event ID |
The child process inherits the parent’s stdout, stderr, and environment. Bare executable names are resolved through PATH; use an absolute executable path when you want a fixed command target. The event JSON is written to the child’s stdin.
If you persist event streams, prefer a per-user directory such as ~/Library/Logs/OmniWM/ and restrictive permissions such as umask 077.
Examples:
# Log focus changes to a filemkdir -p ~/Library/Logs/OmniWMumask 077 && omniwmctl watch focus --exec tee -a ~/Library/Logs/OmniWM/focus.ndjson
# Run a script on workspace changesomniwmctl watch active-workspace --exec ./on-workspace-change.sh
# Process all events with jqomniwmctl watch --all --exec jq '.result'