
Agent Desktop Ffi
C-ABI bindings over agent-desktop's PlatformAdapter.
Install
npx skills add vercel-labs/agent-desktop --skill agent-desktop-ffi -g -a claude-code -y- Repository
- vercel-labs/agent-desktop6.7k
- Category
- AI and agents
- Updated
- 3d ago
- License
- Apache-2.0
- Context cost
- Mediumabout 2,448 tokens
- Runs scripts
- No, instructions only
What it does
C-ABI bindings over agent-desktop's PlatformAdapter. Consumers (Python ctypes, Swift, Node ffi-napi, Go cgo, C++, Ruby fiddle) link libagent_desktop_ffi.{dylib,so,dll} and call `ad_*` functions directly instead of spawning the CLI binary per call. The canonical observe-act workflow is: ad_init → ad_adapter_create[_with_session] → ad_snapshot → read qualified refs (@s8f3k2p9:e5) → ad_execute_by_ref → ad_free_string → ad_adapter_destroy.
agent-desktop-ffi
Direct C-ABI access to PlatformAdapter operations. Build the cdylib with the
release-ffi profile:
cargo build --profile release-ffi -p agent-desktop-ffi
The output is target/release-ffi/libagent_desktop_ffi.dylib (.so on Linux,
agent_desktop_ffi.dll on Windows) plus a committed C header at
crates/ffi/include/agent_desktop.h. The default release profile uses
panic = "abort": a Rust panic inside an extern "C" function would SIGABRT
the host. release-ffi keeps panic = "unwind", which the panic traps need.
Four reference topics, loaded as needed:
- ownership.md: who allocates and who frees every pointer the FFI hands back.
- error-handling.md: errno-style last-error contract, error codes, enum validation, panic boundary.
- threading.md: host-thread contract, mutation ordering across threads and processes, adapter-bound native handles, AXIsProcessTrusted inheritance.
- build-and-link.md: prebuilt archives, ABI handshake, struct size validation, C and Python examples.
Observe-act workflow (canonical path)
ad_init(AD_ABI_VERSION_MAJOR) // verify header ↔ dylib match
adapter = ad_adapter_create_with_session("s1") // or ad_adapter_create()
rc = ad_snapshot(adapter, "Finder", 0, 10, false, false, &json_out)
// parse json_out: locate snapshot-qualified refs in data.tree
ad_free_string(json_out)
// build action:
AdAction act = {0}; act.kind = AD_ACTION_KIND_CLICK;
rc = ad_execute_by_ref(adapter, "@s8f3k2p9:e5", &act, 0, &result_out)
ad_free_string(result_out)
ad_adapter_destroy(adapter)

