contents

burrow & IPC#

burrow is carrot's companion CLI. It talks to a JSON socket that any script or status bar can use directly; everything burrow can do, nc can do too.

The socket#

$XDG_RUNTIME_DIR/carrot.$WAYLAND_DISPLAY.sock, for example /run/user/1000/carrot.wayland-1.sock. The protocol is one JSON value per line in both directions. Replies are wrapped: {"ok": ...} on success, {"error":"..."} on failure. If WAYLAND_DISPLAY is unset, burrow finds any carrot.*.sock in the runtime dir.

$ echo '"workspaces"' | nc -U "$XDG_RUNTIME_DIR/carrot.$WAYLAND_DISPLAY.sock"
{"ok":[{"index":1,"windows":2,"active":true,"output":"eDP-1","layout":"dwindle"}]}

Actions#

Actions are the same vocabulary as keybinds, as JSON. A bare string for argument-less actions, an object for the rest (workspace numbers are 0-based on the wire, 1-based everywhere humans type them):

"toggle-fullscreen"
"center-column"
"toggle-full-width"
{"focus-workspace":2}
{"focus-dir":"left"}
{"adjust-split-ratio":0.1}
{"set-layout":"toggle"}
{"spawn":["foot"]}
{"spawn-sh":"a | b"}

Dispatch always replies {"ok":true}. With burrow:

burrow workspace 3          # absolute (1-based)
burrow workspace +1         # relative
burrow send-to-workspace 2
burrow toggle-floating
burrow focus-left
burrow split-ratio -0.1
burrow spawn foot
burrow quit

Note the two short forms: the CLI says workspace and split-ratio where the bind actions say focus-workspace and adjust-split-ratio.

The scrolling and pointer verbs (set-layout, consume-or-expel-left/-right, move-column-left/-right, cycle-column-width, cycle-column-width-back, toggle-full-width, center-column, pointer-move, pointer-resize) and the binds query are accepted on the socket in the JSON forms above; the burrow CLI has not grown subcommands for them yet, so send them through nc for now.

Queries#

VerbReturns
monitorseach output: name, x, y, width, height, scale, workspace, focused
workspaceseach workspace: index (1-based), windows, active, output, layout (dwindle or scrolling)
windowswindows on the active workspace: title, app-id, geometry, floating, fullscreen, focused
clientsevery window everywhere, adding id, pid, workspace, output, xwayland, mapped

burrow prints these human-readable by default; burrow --json <verb> keeps the wire JSON for scripts.

Control verbs#

VerbDoes
reloadre-read the config; a parse error keeps the running config and reports every error; cold keys (outputs, debug, startup spawns) print a needs-restart notice
bindslist the active binds with their chords, actions, and title labels, for shell-drawn hotkey overlays (raw socket only; no CLI subcommand yet)
dpms-off / dpms-onblank or wake every output (any input also wakes)
dump-shadowwrite the focused window's CPU pixel shadow to /tmp/carrot-shadow-<id>.ppm, a forensic tool for telling client bugs from render bugs
subscribeturn the connection into a live event stream

The event stream#

burrow subscribe prints ndjson forever: first a snapshot ({"workspaces":[...]} then {"windows":[...]}), then one event per line as things happen. It exists so status bars never have to poll.

EventFires when
{"workspace":N}the active workspace changes
{"window-opened":{"title":...,"app-id":...}}a window maps
{"window-closed":{"title":...}}a window unmaps
{"window-focused":{"title":...,"app-id":...}}keyboard focus moves
{"fullscreen":bool}fullscreen toggles
{"event":"config-loaded","failed":bool,"errors":[...],"cold-keys-pending":[...]}a config load or reload finishes, success or not

Exit codes#

0 success, 1 runtime errors (no socket, an {"error"} reply), 2 usage errors.