# Tool reference

Every tool returns one JSON envelope from the CLI: `ok` with `data`, or `ok: false` with `error.code` and usually `error.disposition`. Retry an action only when `error.disposition.retry` is `safe`. Any other delivery value means the action may already have landed, so read the live state instead of repeating it.

`session`, `agent_id` and `trace` are accepted by every tool. `session` keeps concurrent agents in separate ref spaces, `agent_id` narrows that to one subagent, and `trace` appends a reliability trace as JSONL.

## desktop_status

No parameters. Reports the CLI version, platform, permission state, state directory and the surfaces this platform can snapshot.

## desktop_apps

| Parameter | Type | Notes |
| --- | --- | --- |
| `app` | string | Narrows the window list to one application |
| `include_windows` | boolean | Also return the window inventory |

A tray-only process owns no window and does not appear.

## desktop_snapshot

| Parameter | Type | Notes |
| --- | --- | --- |
| `app` | string | Application name as `desktop_apps` reports it |
| `window_id` | string | Disambiguates when several windows match |
| `surface` | enum | `window`, `focused`, `menu`, `menubar`, `sheet`, `popover`, `alert`, `taskbar`, `system-tray`, `system-tray-overflow`, `start-menu`, `action-center` |
| `root` | string | Drill into one subtree by container ref |
| `max_depth` | 1-40 | Tree depth limit |
| `interactive_only` | boolean | Only elements that can be acted on |
| `compact` | boolean | Collapse single-child unnamed nodes |
| `skeleton` | boolean | Shallow overview with `children_count` on cut branches |
| `include_bounds` | boolean | Add x, y, width and height per element |
| `wait_for` | string | Poll until a `role:text` selector appears |
| `wait_for_gone` | string | Poll until no element matches |
| `wait_timeout_ms` | integer | Budget for either wait |
| `timeout_ms` | 1000-600000 | Wall clock for the call |
| `max_chars` | 2000-200000 | Output cap; a larger tree is pruned and reports `tree_nodes_dropped` |
| `headed` | boolean | Use physical delivery instead of the accessibility API |

Never skeleton a surface. A menu or sheet is already focused and small.

## desktop_find

`app`, `window_id`, `role`, `name`, `value`, `text`, `description`, `native_id`, `exact`, `limit` (0-500), `timeout_ms`, `max_chars`.

An empty match list means the element is not in the current tree. It may live in a menu that is not open, or the app may not have settled.

## desktop_act

| Parameter | Type | Notes |
| --- | --- | --- |
| `action` | enum | `click`, `double-click`, `triple-click`, `right-click`, `focus`, `set-value`, `clear`, `select`, `toggle`, `check`, `uncheck`, `expand`, `collapse`, `scroll`, `scroll-to`, `hover`, `press` |
| `ref` | string | Required for every action except `press` |
| `value` | string | For `set-value` and `select` |
| `keys` | string | For `press`, such as `ctrl+s` or `return` |
| `direction` | enum | `up`, `down`, `left`, `right` for `scroll` |
| `amount` | 1-50 | Scroll units |
| `window_id` | string | Targets a non-frontmost app for `press` |
| `force` | boolean | For `press`: allow combos the adapter blocks |
| `verify` | boolean | Re-read the touched region and return it as `verification` |
| `timeout_ms`, `max_chars`, `headed` | | As above |

`set-value` is the headless way to fill a field. `type` is refused headless on Windows because it synthesizes keystrokes, so prefer `set-value`, `select`, and `check` or `toggle`, which are idempotent. `focus`, `hover`, other headed actions, and `press` with `force: true` need `allow_focus: true` because they can interrupt the desktop.

## desktop_query

`kind` (`get` or `is`), `ref`, and `property`. For `get`: `text`, `value`, `title`, `bounds`, `role`, `states`. For `is`: `visible`, `enabled`, `checked`, `focused`, `expanded`, `selected`.

This is the cheap verification path: one element instead of a whole window.

## desktop_wait

`kind` is `element`, `text`, `window`, `menu`, `menu-closed`, `notification` or `time`. Supply `ref` for an element, `text` for text, `window` for a title, and `ms` for a fixed pause or the overall budget. `app` narrows the wait to one application.

## desktop_screenshot

`app`, `window_id`, `handle`, `title`, `screen`, `path`, `return_image` (default true).

A window target is captured through the helper with `PrintWindow` and `PW_RENDERFULLCONTENT`, which renders a covered window offscreen without bringing it forward. `screen` captures a whole display through the CLI and does need the screen. The PNG is returned as a viewable image and its path is reported alongside.

## desktop_window

| Parameter | Type | Notes |
| --- | --- | --- |
| `action` | enum | `launch`, `close`, `focus`, `resize`, `move`, `minimize`, `maximize`, `restore`, `foreground` |
| `app` | string | For `launch`: a bare System32 name or an absolute path. Elsewhere: the app that owns the window |
| `window_id`, `handle`, `title` | string | Window selectors; `handle` is unambiguous |
| `app_args` | string[] | Launch arguments |
| `activate` | boolean | For `launch`: bring it forward and wait for the window |
| `no_attach` | boolean | For `launch`: force a fresh instance |
| `force` | boolean | For `close`: terminate instead of asking |
| `width`, `height`, `x`, `y` | integer | For `resize` and `move` |
| `normal` | boolean | For `restore`: also undo a maximized state |
| `allow_focus` | boolean | Permit this call to take the foreground |

With the helper and a window selector, `restore`, `move` and `resize` use a no-activate path and report `focus_unchanged`. Without it, their CLI fallbacks need `allow_focus`. `focus`, `maximize` and `launch` also need `allow_focus`. `foreground` reads the window that currently holds focus.

## desktop_surfaces

`action` is `list` (surfaces of an app, with `app`), `open` (a shell surface from `surface`, needs `allow_focus`) or `displays` (bounds and scale factor per display).

## desktop_notifications

`action` is `list`, `dismiss`, `dismiss-all` or `act`. `dismiss` and `act` need `index` from the list. `act` can take `action_index` for a specific button. `app` filters list and dismiss-all.

## desktop_clipboard

`action` is `get`, `set` or `clear`. `set` needs `text`. Clipboard content is private, so do not echo it into logs or commits.

## desktop_batch

`commands` is an array of `{ "command": string, "args": object }`, plus `stop_on_error`, `allow_focus`, `timeout_ms` and `max_chars`. The batch is sequential and not atomic, so `stop_on_error` still returns completed steps. Foreground-changing commands need `allow_focus: true`; nested batches are refused. Use it for multi-step work and commands without a dedicated tool, such as `session`, `trace` or `cursor-overlay`.

## desktop_install

`action` is `status`, `verify` or `install`. `status` reports which executable would run and where it was looked for. `verify` runs `version` and `status` against it. `install` runs `npm install -g agent-desktop` and proves the result. `force` reinstalls. Every `install` asks for confirmation when a dialog is available.

The helper that provides focus-free window operations is separate, and `verify` reports whether it resolved. Rebuild it with `npm run build:helper`, or point `PI_AGENT_DESKTOP_HELPER` at another copy.
