tendril0.0.4

platforms

Every desktop, and some that aren't

The same commands work on X11 and Wayland, macOS, Windows 11 and Android, and they reach other machines over SSH or from WSL. Where a platform needs a helper tool, Tendril says which; where it cannot do something yet, the result says so.

What runs where

PlatformDiscoverCaptureInputElements
Linux, X11nativenativenative XTestAT-SPI, else the window tree
Linux, Waylandhyprctl, swaymsg, wlr-randrdesktop portal; grim as fallbackydotool; wtype for keys onlyAT-SPI
macOSosascriptscreencaptureosascriptAX
Windows 11nativenativenativenative Win32
AndroidADBscreencapinputUIAutomator

"Native" means inside the binary, with no subprocess. Cameras use ffmpeg everywhere: AVFoundation on macOS, V4L2 on Linux, DirectShow on Windows. Audio uses pw-record or parecord on Linux and afrecord on macOS; on Windows it is probe-only for now. When no input helper is installed on Wayland, run fails with a structured unsupported_capability error rather than doing nothing.

Linux

On X11 everything is built in: discovery through XRandR and EWMH, capture, and focus, keyboard and pointer through XTest. Wayland has no single portable path, so Tendril uses each compositor's own tools for discovery and the desktop portal for screenshots, and documents the supported combinations. Input on Wayland goes through ydotool (which needs its daemon) or, for keys only, wtype.

macOS

macOS gates screen capture, input, microphone and camera behind permissions. tendril permissions reports all four with remediation steps and changes nothing; --request, in a foreground session, shows the system prompts and opens the right System Settings panes.

tendril permissions --jsontendril permissions --request

Windows

Windows 11 support is native inside the binary: monitor and window enumeration, GDI capture, focus transfer, keyboard and mouse input, and Win32 control enumeration for list-elements. Audio capture is probe-only until a WASAPI recorder lands.

Android

--android SERIAL drives a phone or emulator over ADB; --android auto picks the only connected device and fails clearly when there are none or several.

tendril --android emulator-5554 list --jsontendril --android emulator-5554 list-elements --jsontendril --android auto capture -o screen.pngtendril --android emulator-5554 run 'launch("com.example"),assert_visible("Ready")'tendril --android emulator-5554 run 'notifications(),wait(500ms),back()'
Run actionOn Android
lclick(x,y), dblclickOne or two input tap
drag, scrollinput swipe
send("…"), plain textinput text
Return, Back, Home, volume keys, key codesinput keyevent
tap_text, tap_desc, tap_resourceTap by text, content description or resource id from the UI dump
scroll_until("Done")Swipe and re-read until the selector is visible, then tap it
assert_visible, assert_absentCheck the UI without touching it
launch("pkg")Start or switch to an app
back(), home(), recents(), notifications(), quicksettings()System navigation

Every Android run leaves a debug trail (the commands, the UI dump and the screenshot) in a per-run directory, or in TENDRIL_ANDROID_ARTIFACT_DIR.

Remote machines and WSL

Same invocation, different placesA local tendril invocation can run in four places. Without flags it drives the local desktop. With --remote user at host it strips that flag and runs the same tendril command over SSH on another machine, streaming the result back. With --wsl-tunnel, from WSL or Linux, it runs the Windows build, tendril.exe, on the Windows host. With --android and a serial it drives an Android device or emulator over ADB. tendril … same arguments same envelopes local desktop X11, Wayland, macOS, Windows --remote user@host OpenSSH → tendril on that host --wsl-tunnel → tendril.exe on the Windows host --android SERIAL ADB → device or emulator
One invocation, four places.Remote modes strip only their own flag and run the identical command elsewhere, so envelopes and errors look the same.
tendril --remote user@host --json listtendril --remote user@host --window ID run 'send("hello")'tendril --wsl-tunnel --json listtendril --remote user@host --wsl-tunnel --json list        # a Windows host behind a remote WSL

A disposable desktop

For browser and desktop work that must not touch a person's screen, tendril-headless (shipped in the package, and as scripts/tendril-headless.sh) starts an isolated 1920 × 1080 X11 session with XTest, a lightweight window manager and a browser, and prints the variables to point Tendril at it. It is process-scoped, keeps only lifecycle metadata under the runtime directory, and has smoke tests for clipboard, Unicode, drag, hover, scroll and file-upload behaviour. The captures on the home page came from one.

tendril-headless --name site --display 151 start[tendril-headless] starting Xvfb :151 at 1920x1080x24[tendril-headless] starting window manager: openbox[tendril-headless] starting browser: …/bin/chromiumexport DISPLAY=:151export XDG_SESSION_TYPE=x11tendril-headless --name site stop

Runtime dependencies

A source-backed audit lists every external tool Tendril calls, per command and platform, and classifies each as self-contained, a documented prerequisite or a compatibility fallback, with a direction for replacing it. Linux X11 and Windows are self-contained today; macOS relies on tools that ship with the system; Wayland and cameras rely on documented helpers that the Nix package can supply.