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 identifier
  • active — whether it's currently visible on a monitor
  • windows — number of windows
  • monitor — 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.