关于 agent-desktop-linux
agent-desktop-linux 是面向 Linux 图形桌面的 UI 自动化技能,供 Agent 通过无障碍接口观察并操作应用。文档列出 X11、Wayland 与 GNOME 环境中的能力差异及运行条件。
主要功能
- 01通过 AT-SPI 观察界面
- 02按引用操作界面控件
- 03启动应用并管理窗口
- 04捕获屏幕及管理剪贴板
- 05等待界面变化并处理通知
适用场景
- 01检查应用窗口和界面内容
- 02操作控件或输入文本
- 03等待应用窗口出现或关闭
- 04查看 GNOME 通知
MCP 相关
README 未说明其与 MCP 的关系。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vercel-labs/ agent-desktop --skill agent-desktop-linux安装后在 Claude Code 中输入/agent-desktop-linux确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/bus-and-permissions.mdcapture-and-clipboard.mddisplay-servers-and-input.mdshell-tray-and-notifications.mdtroubleshooting.mdwindows-and-lifecycle.md详细介绍
agent-desktop-linux
此文件仅介绍 Linux 上的差异。观察-操作循环、引用、JSON 封装、会话和追踪在所有平台上都相同。
需要 Ubuntu 24.04+(x86_64 或 aarch64)、已登录用户的图形会话以及正在运行的 AT-SPI 总线。其他发行版需要应用 at-spi2-core 桥接修复 dc0dc33;Ubuntu 22.04 的桥接会在 Action.GetActions 处中止。归档加载器要求 glibc 2.35 或更高版本。请在目标应用的桌面会话中运行 CLI:会话总线、显示环境和运行时目录均来自该会话的环境。在 TTY 登录环境、缺少会话变量的 SSH shell、没有总线的容器或其他用户的会话中,都无法看到应用。经测试的桌面环境为 GNOME;X11 和 Wayland 会话均可运行,但在输入、捕获和窗口控制方面有所不同。观察和语义操作无需辅助工具。
能力表
| 组 | 命令 | Linux 上的状态 |
|---|---|---|
| 观察 | snapshot、find、get、is | 通过 AT-SPI 在 X11 和 Wayland 上运行。支持 window、sheet、alert 和 menu;GNOME 还支持 shell 表面。虚拟托盘 getter 有限制;请参阅 shell 参考并检查 status |
| 表面 | list-surfaces | 列出应用的窗口、工作表和已打开菜单;shell 读取使用 snapshot --surface |
| 按引用交互 | click、right-click、type、set-value、clear、select、toggle、check、uncheck、expand、collapse、scroll-to | 需要可读取的实时标识和所需的 AT-SPI 能力。菜单引用解析限制请参阅 shell 参考;X11 有头回退也需要可用的几何信息,且不会绕过标识检查 |
| 滚轮滚动 | scroll、mouse-wheel | 物理滚轮输入;仅支持 X11 和 --headed |
| 指针手势 | double-click、triple-click、hover、drag | 仅支持 X11 上的 --headed。在 Wayland 上无法对准指针,因此这些操作会以 ACTION_NOT_SUPPORTED 拒绝 |
| 焦点 | focus | 焦点权限需要 --headed。对尚未处于 focused 状态的可聚焦节点调用 AT-SPI Component.GrabFocus,不操作指针,并验证状态;GTK4 应用会拒绝此调用,因此在那里 focus 会以 ACTION_FAILED grab_focus_rejected 结束,聚焦其窗口应使用 focus-window |
| 键盘和鼠标 | press、mouse-click、mouse-move、mouse-wheel | press 和文本按键可在 X11 及经能力检测的 Mutter Wayland 会话上运行;指针命令仅支持 X11 和 --headed。请参阅 references/display-servers-and-input.md |
| 按住输入 | key-down、key-up、mouse-down、mouse-up | 在所有平台上均安全拒绝:在 Linux 上,key-down 和 key-up 返回 ACTION_NOT_SUPPORTED;无头模式下 mouse-down 和 mouse-up 返回 POLICY_DENIED,使用 --headed 时返回 ACTION_NOT_SUPPORTED |
| 应用和窗口 | launch、close-app、list-windows、list-apps、focus-window、move-window、resize-window、minimize、maximize、restore | 启动和列表查询可在 X11 和 Wayland 上运行;focus-window 需要 X11。其他窗口控制和正常关闭需要 X11 客户端。请参阅 references/windows-and-lifecycle.md |
| 显示器 | list-displays | 可用 |
| 捕获 | screenshot | X11:无需权限即可捕获窗口;仅在非合成管理器下才能捕获显示器。Wayland:需要门户授权,可裁剪显示器画面。不指定选择器时返回主显示器。请参阅 references/capture-and-clipboard.md |
| 剪贴板 | clipboard-get、clipboard-set、clipboard-clear | 可用;支持文本、图像和文件列表。Wayland 需要 wl-clipboard |
| 等待 | wait | 支持毫秒、--element、--window、--text、--menu、--menu-closed、--event。菜单等待共用菜单表面检测器;--notification 会等待 GNOME 上的新通知 |
| 通知 | list-notifications、dismiss-notification、dismiss-all-notifications、notification-action | 仅支持 GNOME Shell;列表查询可在无头模式下进行,修改操作需要在 X11 上使用 --headed,且 dismiss-notification 和 notification-action 还需要 --expected-app 或 --expected-title。字段从 shell 的 widget 布局读取,仅在 GNOME Shell 46.0 上验证过,并且每次修改都会通过其效果进行验证。Wayland 会在输入前拒绝 shell 指针操作。通知所有者不是 shell 或其自身辅助程序时,会返回 PLATFORM_NOT_SUPPORTED。请参阅 shell 参考 |
| Shell 表面 | open-system-surface | 仅 system-tray 和 action-center 可能可用。system-tray 需要 StatusNotifierWatcher(否则会以 watcher: absent 拒绝);action-center 需要已验证的角色祖先关系。quick-settings 会以 shell_container_unproven 拒绝,taskbar 始终拒绝,且不支持 start-menu 和 system-tray-overflow,尽管 --help 会列出它们。请参阅 shell 参考 |
| 光标叠加层 | cursor-overlay | 需要活动会话;请参阅下方的光标叠加层。X11 启用后返回 data.rendered: true;Wayland 会保存设置并返回 data.rendered: false |
| 系统 | status、permissions、version、batch、skills、session、trace | 可用 |
First Contact
- 先运行
agent-desktop status。supported_surfaces为空表示辅助功能总线没有响应,而不是桌面为空。请阅读references/bus-and-permissions.md;不要重启你没有启动的总线。 --app接受list-apps打印的名称(gnome-calculator、nautilus),或由已验证的可执行文件和参数身份支持的桌面条目名称或 ID,绝不能是窗口标题或任意注册表标签。桌面条目存在后,即可接受诸如Files这样的桌面条目名称。list-windows --app会精确匹配(包括别名);list-apps --app会将所列名称中的子字符串与精确的适配器别名合并匹配,且不区分大小写。- 窗口 ID 是不透明地址,长度为 34 到 70 个字符,在窗口进程存续期间有效;重启后请再次运行
list-windows。list-apps的各行包含bundle_id(已知时为桌面 ID)和process_instance。 - GTK4 应用的嵌套层级很深。
--max-depth和--skeleton计算的是语义层级,因此空布局包装器也会增加输出层级。-i --compact仍会显示嵌套的无名group节点:请继续查看其后内容。 - 文件视图为空并不能证明文件夹为空。 如果图标视图没有显示任何文件项,请尝试可用的列表视图或详细视图,然后获取新的快照并确认应用实际显示了哪些项。
- 窗口会先于其内容出现。 请先运行
wait --window "Text Editor" --app gnome-text-editor,然后再运行wait --text;该命令会匹配节点自身的名称、值或描述。对于 Web 引擎应用(根据其 AT-SPI 工具包元数据检测),窗口观察会等待三次完整读取结果相同且出现 Web 文档角色,或达到请求的深度截断。若 Shell 尚无文档,预算耗尽时仍会保持未完成状态。若--timeout短于首次读取所需时间,则会返回TIMEOUT,而不会返回部分树。 - 引用必须是唯一的。 Linux 不存储元素地址,因此只有当快照捕获的窗口中仅有一个元素符合其角色、原生 ID、名称和描述,且当前仍恰有一个活动元素符合条件时,引用才会解析成功。唯一性按整个窗口计算,而不是按
--skeleton或--max-depth快照展示的浅层树计算,因此即使浅层树从未显示过的同类元素,也会导致引用被拒绝。 位置、尺寸和值都不计入身份,因此布局变化本身不会使引用失效,但同类元素会:相同的按钮,或共用同一角色且没有其他字段的视图,会在任何操作到达应用之前以AMBIGUOUS_TARGET、details.kind: identity_not_unique拒绝;已经消失的元素则会返回STALE_REF、saved_ref_absent。列表变化后,请获取新的快照。要在 X11 上从两个相同控件中选中一个,请使用--headed mouse-click --xy;Wayland 会话会拒绝有头指针输入,因此在那里,同类元素既没有引用,也无法通过指针操作。引用属于其所在窗口,因此标题相同的两个窗口各自解析自己的引用。 - Chromium 和 Qt 应用需要启动标志或变量才能显示在总线上;
Electron 应用不需要这些,仅当
chrome-sandbox未设置 setuid 时才需要--no-sandbox。请参阅references/troubleshooting.md。 - 有头引用操作需要窗口能够获得焦点。 如果窗口管理器从未激活某个窗口,操作会以
activation_not_granted结束。请参阅references/windows-and-lifecycle.md。 - GTK4 密码字段可能会显示其文本。 只有密码角色的内容会被隐藏。 请将带隐藏字符的 GTK4 输入框视为可被所有观察命令读取。
- 被阻止的组合键会在未指定
--force时被拒绝。 请参阅references/display-servers-and-input.md。 - 打开菜单角色的弹出窗口后,请检查
data.surfaces。 若存在menu条目,请使用snapshot --surface menu --app <name> -i。若没有,请先使用wait --menu和list-surfaces,再判断打开操作是否失败。由列表支持的下拉菜单属于窗口,而不是菜单表面;请参阅 Shell 参考。 - Shell 指针输入需要接收方证明。 在 X11 上,有头 Shell 单击的接收方须由 Shell 自身的树证明:接收方必须是目标且保持不动,否则单击会在触发任何指针事件前被拒绝。Wayland 上的 Shell 单击会被拒绝。通知需要 GNOME 通知服务;托盘快照也需要 StatusNotifierWatcher。
- 状态根目录必须是私有的。 如果
AGENT_DESKTOP_HOME或~/.agent-desktop允许组写入或所有用户访问,snapshot会以INTERNAL失败;请对其运行chmod 700,或让工具创建该目录。
等待窗口
等待应用窗口出现(--window 需要指定标题或标题子字符串):
agent-desktop wait --window "Text Editor" --app gnome-text-editor --timeout 10000
若要等待由你触发的关闭,请将操作批处理,以便在关闭前获取基线(Calculator 没有未保存文档提示,不会打断操作):
agent-desktop batch '[{"command":"close-app","args":{"app":"gnome-calculator"}},{"command":"wait","args":{"event":"window-closed","app":"gnome-calculator","timeout":10000}}]' --stop-on-error
若要监视其他人关闭窗口,请在对方关闭窗口前启动
agent-desktop wait --event window-closed --app gnome-text-editor --timeout 10000。没有 --window-closed 标志。
光标叠加层
启动会话,并将返回的 ID 传递给每个叠加层命令:
session_id=$(agent-desktop session start --name docs-example | jq -r '.data.session_id')
agent-desktop cursor-overlay enable --session "$session_id"
agent-desktop cursor-overlay disable --session "$session_id"
agent-desktop session end "$session_id"
如果没有会话,cursor-overlay enable 和 disable 会返回 INVALID_ARGS。
在 X11 上,启用会返回 data.rendered: true;在 Wayland 上,它会保存设置并返回 data.rendered: false,但不会绘制叠加层。
session start --cursor --multi-agent 会返回 data.rendered: false,因为在 Agent 执行操作前不会绘制任何内容。在 X11 上,随后每个 Agent ID 都会获得自己的光标;在 Wayland 上则不会绘制光标。
Linux 上的差异
- Firefox/Gecko 的
select可以在不触发change或input事件的情况下更改所选值,因此依赖这些事件的页面处理程序不会运行。即使读回的值匹配,结果仍为delivered_unverified。继续操作前,请检查应用程序中的相应效果:仅凭读回值不能证明操作已提交。 - 在同一个 GTK4 按钮上,两次
click调用间隔不到约 250 ms 时,只会生效一次。两次调用都会返回ok: true和delivered_unverified。若要多次点击同一个按钮,请在两次点击之间等待效果出现:在显示结果的元素上使用wait --element <ref> --predicate value --value <expected>,或使用wait 300。 - Ref 操作是语义化的 AT-SPI 调用,不会移动指针,也不会更改活动窗口。在
--headed模式下,refclick、right-click和type会先尝试物理输入,只有在因not_delivered而拒绝后才会回退到语义操作(Windows 则相反)。在 Wayland 上,headed 指针命令和 headedselect会立即以ACTION_NOT_SUPPORTED拒绝,原因是wayland_session;headedtype则需要 Mutter RemoteDesktop 功能。完整规则见references/display-servers-and-input.md。 select会先尝试语义方式,再尝试指针方式;在 X11 上,指针方式需要显式请求--headed。Qt 组合框的语义选择只会高亮其弹出窗口中的行,因此无头模式下的选择会在更改高亮前以POLICY_DENIED、类型pointer_required拒绝。在 headed 模式下,对于无法将工具包索引映射到行的列表(GTK4 列表),它会点击该行并检查其selected状态;对于没有语义打开操作的组合框(libadwaita 组合框行),它会点击组合框将其打开,通过弹出窗口自己的列表选择选项,并检查组合框显示的值。在无头模式下,除非组合框已显示该选项,否则列表会以selection_index_unproven拒绝,而没有语义打开操作的组合框会以POLICY_DENIED、类型pointer_required拒绝。通过自身切换控件打开的 GTK4 下拉框,无需--headed即可使用select,并会检查其显示的值。- Ref 可能不提供安全的语义修改方式。在这种情况下,无头请求会返回不支持的操作错误,不会臆造
hidden或disabled状态,也不会切换到物理输入。GTK4 条目和密码框的Activate操作就是此类情况:使用type编辑字段,或者在确实要点击指针时显式请求--headed。 - 打开原生 Wayland Qt 组合框时,会在调用其操作前返回
ACTION_NOT_SUPPORTED,类型为native_popup_requires_input。Qt 需要用户输入序列号才能显示该弹出窗口。已打开的组合框仍可收起;已确认使用 Xwayland 的 Qt 窗口仍保留其语义打开操作。 - 无头
type通过EditableText写入内容。终端的文本节点是名为Terminal的textfield,其唯一操作是RightClick;对它使用无头type会因检查项supported_action返回POLICY_DENIED,且其值为 null。它只有在--headed模式下才能接收按键。 - 在按键组合中,
cmd和meta均表示 Super 键。按键名称采用 macOS 和 Windows 的名称,以及 X keysym 名称。press只接受映射后的按键;type则可处理键盘布局无法生成的字符。 - 窗口操作面向 X11 客户端;
focus-window和 headed 范围内的press需要 X11 会话。无头范围内的press在任一显示服务器上都需要目标当前获得焦点。聚焦另一个工作区上的窗口可能会切换用户当前的桌面。 - 精确的 FFI ref 调用(
ad_resolve_element_exact和ad_execute_ref_action_exact_with_policy)在所有平台上都会以ACTION_NOT_SUPPORTED失败;其边界规则优先适用:边界必须相对于窗口。 - Ref 会重新识别唯一元素,而非控件实例。对于会销毁并重新创建行的工具包(GTK4、Qt6),若名称唯一,ref 会解析到替代元素,因此操作会作用于新元素。相同控件会改为以
AMBIGUOUS_TARGET拒绝。 - 对于仍将已移除控件列在列表中的工具包(GTK4 未设父级的控件、Qt6
setParent(None)),ref 可能会解析到用户已无法看到的控件。此时 GTK4 会返回ok和delivered_unverified,但不会产生效果。任何身份规则都无法解决这一问题;请检查应用程序自身的效果。
参考资料
references/bus-and-permissions.md:总线初始化、三种总线状态、status和permissions输出、状态根目录规则。references/display-servers-and-input.md:X11 与 Wayland 对照表、press、type、指针、滚轮、拖动、被阻止的组合键、按键名称。references/windows-and-lifecycle.md:launch、close-app、窗口操作、焦点、工作区、已停止的应用、后台press。references/capture-and-clipboard.md:X11 和 Wayland 上的screenshot、Wayland 授权对话框、剪贴板所有者和辅助程序。references/shell-tray-and-notifications.md:菜单和 GTK4 弹出窗口、GNOME 概览/顶栏、Shell 读取与输入、通知身份校验、SNI 和 AppIndicator 要求及拒绝情形、沙盒指南。references/troubleshooting.md:症状与原因对照表、Chromium、Electron 和 Qt 标志、工具包限制、包含platform_detail的错误代码。
从二进制文件中读取任意文件:
agent-desktop skills get agent-desktop-linux references/troubleshooting.md。