Skip to content

Keyboard & mouse

Input is the one lane that works end to end today. It is CGEvent injection on macOS — no AppleScript, no helper app, no private API — reached either as a one-shot verb or over the input stream on port 9335.

Terminal window
device-bridge type <text>
device-bridge key <combo>
device-bridge click [--x N] [--y N] [--button left|right|middle] [--count N]
device-bridge move-mouse --x N --y N
device-bridge scroll [--dx N] [--dy N]
device-bridge drag --x1 N --y1 N --x2 N --y2 N [--button left|right|middle]

Every one runs and exits. No daemon, no token, no socket.

Terminal window
device-bridge type "hello world"

Types the literal string into whatever is focused. It does not focus anything for you — click or chord your way there first.

Terminal window
device-bridge key cmd+shift+t
device-bridge key ctrl+c
device-bridge key return

The combo is split on +; everything before the last segment is a modifier, the last segment is the key. A bare key name with no modifiers is fine.

Terminal window
device-bridge click --x 400 --y 300 --count 2 # double-click
device-bridge click --button right --x 400 --y 300
device-bridge scroll --dy -120 # scroll down
device-bridge drag --x1 100 --y1 100 --x2 400 --y2 300

Coordinates are global screen coordinates. --count 2 is a real double-click, not two clicks in a row — the click count travels in the event.

macOS gates event injection behind the Accessibility permission. Without it, every verb fails with an explicit error; nothing silently no-ops. Check with:

Terminal window
device-bridge devices
input available=true

If it reports unavailable, add the calling binary under System Settings → Privacy & Security → Accessibility. Note the grant follows the calling process — running from a terminal means the terminal needs it, and a binary launched by a CI agent needs the agent to hold it.

Terminal window
device-bridge start input --port 9335 --token "$WINDOWCTL_TOKEN"

Unlike the media lanes, input is JSON, not binary framing — it is low-rate and ergonomics wins there. Connect to ws://127.0.0.1:9335/?token=… and send one message per action. This is the path a long-running harness uses so it is not paying process-spawn cost per keystroke.

Not built. The Windows design is SendInput (ADR 0001) and nothing is implemented; non-darwin builds compile and report input as unavailable.