Skip to content

Integrations

acsandmann edited this page Aug 3, 2026 · 3 revisions

Integrations

Rift exposes a JSON-over-Mach IPC interface for companion applications, status bars, scripts, and other macOS automation. Integrations can either invoke rift-cli or connect directly to Rift's Mach service with a client library.

Choosing an integration method

  • Use rift-cli from shell scripts, launch agents, SketchyBar plugins, and other command-line workflows.
  • Use rift-client from a Rust application or plugin that needs typed requests and event handling.
  • Use rift.lua from Lua. It is a low-level Lua binding for Rift's Mach IPC client.
  • Use riftapi when you want a higher-level Lua API organized around queries, workspaces, windows, layouts, displays, and events. It builds on rift.lua and is particularly useful in SketchyBar configurations.

All of these clients communicate with the running Rift process; they do not manage windows independently. Rift must be running and its Mach service must be available before requests can succeed.

rift-cli

rift-cli is the simplest integration point and returns JSON, making it suitable for shell scripts and programs that can execute subprocesses.

Query Rift's state:

rift-cli query workspaces
rift-cli query windows
rift-cli query displays

Execute actions:

rift-cli execute window focus left
rift-cli execute workspace switch 2
rift-cli execute workspace set-layout --workspace-id 2 scrolling

Use RIFT_CLI_PRETTY=1 for readable JSON. For the complete command reference, including layout persistence and service management, see the rift-cli reference.

Events and SketchyBar

Rift can stream events to a Mach subscriber or run a command when an event is emitted. The CLI subscription mode passes event data as the final command argument and provides event-specific environment variables, which makes it convenient for SketchyBar and similar status-bar integrations.

rift-cli subscribe cli \
  --event workspace_changed \
  --command sh \
  --args -c 'sketchybar --trigger rift_workspace_changed RIFT_WORKSPACE_NAME="$RIFT_WORKSPACE_NAME"'

The supported event names are workspace_changed, windows_changed, window_title_changed, stacks_changed, and *. See examples of Rift being used from SketchyBar Shell configurations and SketchyBar Lua configurations for community integration ideas.

rift-client

rift-client is Rift's synchronous Rust client crate. It uses the same Mach service as rift-cli and exposes the shared protocol types for querying state, executing typed commands, and subscribing to typed RiftEvent values.

When developing against this repository, add the client as a path dependency:

[dependencies]
rift-client = { path = "crates/rift-client" }

A client can query Rift without shelling out:

use rift_client::RiftMachClient;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RiftMachClient::connect()?;
    let workspaces = client.get_workspaces(None)?;
    println!("{workspaces:#?}");
    Ok(())
}

Subscriptions block until the next matching event arrives:

use rift_client::{EventKind, RiftMachClient};

let client = RiftMachClient::connect()?;
let subscription = client.subscribe(EventKind::WorkspaceChanged)?;
let event = subscription.recv_event()?;

The repository includes complete query, listen, and dimmer examples.

rift.lua

rift.lua is a native Lua Mach IPC client. It is useful for embedded Lua environments and status-bar configurations that need direct access to Rift without invoking rift-cli for every request.

The project builds a Lua module at bin/rift.so, which can then be loaded and connected to Rift:

package.cpath = "./bin/?.so;" .. package.cpath
local rift = require("rift")

local client, err = rift.connect()
if not client then error(err) end

local response, err = client:send_request([[{"get_workspaces":{"space_id":null}}]])
if not response then error(err) end

Requests use raw JSON strings and responses are decoded into Lua tables. The client also supports callback-based subscriptions for workspace_changed, windows_changed, window_title_changed, stacks_changed, and * (all events). Keep the Lua process alive while subscribed so callbacks can continue to run.

Higher-level Lua: riftapi

pyrorhythm/riftapi provides a higher-level wrapper around rift.lua. Its modules expose a more convenient Lua interface for common Rift operations, such as querying workspaces and creating or switching them:

local rift = require("riftapi")

local workspaces, err = rift.query.workspaces()
if not workspaces then
    error(err)
end

rift.workspace.switch(2)

This is a good fit for SketchyBar configurations: use events or periodic refreshes to update the bar, and call rift.workspace.* or other riftapi modules in response to user interaction.

Protocol notes

  • The clients use Rift's per-user bootstrap service. Set RIFT_BS_NAME when running multiple Rift instances and connecting to a non-default service.
  • Queries return current state; subscriptions are intended for reacting to changes.
  • Event and command names are part of the Rift protocol and may evolve while Rift is in active development. Check the CLI reference and client examples when upgrading.

Clone this wiki locally