Events & Subscribe
The IPC server supports event subscriptions. A client can request to receive a stream of real-time events from the window manager. Events carry rich payloads with full window and workspace metadata, designed for status bar integration.
Subscribing
Send the subscribe command to switch a connection into streaming mode:
tarmacctl subscribe
Or filter by specific event types:
tarmacctl subscribe workspace_changed window_focused
Once subscribed, the connection stays open and events are streamed as JSON lines.
Raw socket subscription
echo '{"command":"subscribe","args":["workspace_changed","window_focused"]}' | socat - UNIX-CONNECT:/tmp/tarmac-$USER.sock
For an indefinite subscription:
socat - UNIX-CONNECT:/tmp/tarmac-$USER.sock <<< '{"command":"subscribe","args":[]}'
Event types
workspace_changed
Fired when the active workspace changes on any monitor. Includes a full snapshot of all workspace states for bar integration.
{
"event": "workspace_changed",
"data": {
"old": "1",
"new": "3",
"workspaces": [
{ "id": "1", "active": true, "windows": 3, "monitor": 0, "urgent": false },
{ "id": "2", "active": false, "windows": 0, "monitor": null, "urgent": false },
{ "id": "3", "active": true, "windows": 1, "monitor": 0, "urgent": false }
],
"focused_workspace": "3",
"focused_monitor": 0
}
}
The workspaces array contains every workspace with:
id— workspace identifieractive— whether it's currently visible on a monitorwindows— number of windowsmonitor— which monitor it's on (null if not active)urgent— reserved for future use (always false)
window_focused
Fired when a window gains focus. Includes full window metadata.
{
"event": "window_focused",
"data": {
"window_id": 1234,
"title": "GitHub - Mozilla Firefox",
"app_name": "Firefox",
"app_bundle": "org.mozilla.firefox",
"workspace": "1"
}
}
window_created
Fired when a new window is detected and added to management.
{
"event": "window_created",
"data": {
"window_id": 5678,
"title": "~",
"app_name": "WezTerm",
"app_bundle": "com.github.wez.wezterm",
"workspace": "1"
}
}
window_closed
Fired when a managed window closes.
{
"event": "window_closed",
"data": {
"window_id": 1234,
"app_name": "Firefox"
}
}
monitor_changed
Fired when focus moves to a different monitor.
{
"event": "monitor_changed",
"data": {
"index": 1,
"monitor_count": 2,
"focused_workspace": "2"
}
}
layout_changed
Fired when the layout is recalculated on a workspace (after adding/removing/resizing windows).
{
"event": "layout_changed",
"data": {
"workspace": "1",
"window_count": 4,
"layout_type": "mixed"
}
}
layout_type is one of: "tiled", "floating", or "mixed" (has both tiled and floating windows).
mode_changed
Fired when the window manager mode changes.
{
"event": "mode_changed",
"data": {
"mode": "normal"
}
}
Filtering
Pass event type names as arguments to subscribe to only receive those events:
tarmacctl subscribe workspace_changed
tarmacctl subscribe window_focused window_closed
Pass no arguments (or *) to receive all events:
tarmacctl subscribe
tarmacctl subscribe "*"
Use cases
Status bar integration (sketchybar)
The workspace_changed event includes a full workspace snapshot, so your bar can render all workspace indicators at once:
tarmacctl subscribe workspace_changed | while read -r line; do
# Get active workspace
ws=$(echo "$line" | jq -r '.data.focused_workspace')
sketchybar --set workspace label="$ws"
# Update all workspace indicators
echo "$line" | jq -r '.data.workspaces[] | "\(.id) \(.active) \(.windows)"' | while read id active count; do
sketchybar --set "ws.$id" icon.highlight="$active" label="$count"
done
done
Window title in bar
tarmacctl subscribe window_focused | while read -r line; do
title=$(echo "$line" | jq -r '.data.title')
app=$(echo "$line" | jq -r '.data.app_name')
sketchybar --set window_title label="$app — $title"
done
Activity logging
tarmacctl subscribe window_focused | while read -r line; do
echo "$(date): $line" >> /tmp/tarmac-activity.log
done
Custom focus behavior
tarmacctl subscribe window_focused | while read -r line; do
app=$(echo "$line" | jq -r '.data.app_name')
if [ "$app" = "Finder" ]; then
tarmacctl toggle-floating
fi
done
Event bus internals
The event bus is a thread-safe broadcast channel (256-event buffer per subscriber). Each subscriber gets its own sync_channel. If a subscriber falls behind and the buffer fills, it's automatically disconnected. The main thread publishes events; IPC threads consume them.