关于 agent-computer-use
通过 agent-cu CLI 控制桌面应用的计算机操作技能。它强调截图、操作、验证的循环,并提供元素选择器、键盘与鼠标操作及常见应用工作流指引。
主要功能
- 01通过 agent-cu CLI 控制桌面应用
- 02屏幕截图与元素选择器
- 03点击、输入、滚动和按键
- 04基于状态验证操作结果
- 05批量命令与应用工作流
适用场景
- 01导航和操作桌面应用
- 02在浏览器中填写网页表单
- 03在 Music 中搜索并播放音乐
- 04读取日历事件或发送 Slack 消息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kortix-ai/ agent-computer-use --skill agent-computer-use安装后在 Claude Code 中输入/agent-computer-use确认已加载。
详细介绍
agent-computer-use — 计算机操作技能
你可以使用 agent-cu,这是一个用于控制桌面应用的 CLI 工具。你可以点击按钮、输入文本、读取屏幕内容、滚动、拖动文件、移动窗口——所有操作都可通过终端完成。
首次运行设置(用户操作)
首次运行 agent-cu 命令时,Claude Code 会提示用户批准。用户有以下三个选项,按推荐顺序排列:
-
最简单 — 在终端中运行
agent-cu setup。交互式向导会将Bash(agent-cu *)写入正确的设置文件。只需设置一次。如果用户似乎对反复出现的批准提示感到沮丧,可以建议此选项。如果你(Agent)自己运行,但无法响应提示,请使用非交互式标志:
agent-cu setup --yes→ 无监督 + 全局(推荐默认值)agent-cu setup --mode <unsupervised|supervised> --scope <global|project>用于指定组合
-
最快 — 在批准提示中选择 "Yes, and don't ask again for:
agent-cu *"。此选项只适用于该特定子命令模式;其他子命令仍会再次提示。 -
手动 — 在
~/.claude/settings.json的permissions.allow下添加"Bash(agent-cu *)"。
不要尝试自行修改用户的设置文件——请让用户改用 agent-cu setup。
思考方式
像坐在电脑前的人一样思考。 操作之前,先问自己:我会在屏幕上看到什么?会点击什么?会输入什么?
人会:
- 查看屏幕(快照)
- 找到所需内容(识别引用)
- 执行一个操作(点击、输入、按键)
- 检查发生了什么变化(重新截图)
你必须照做。不要跳过步骤。不要假设操作后界面没有变化。
核心循环
snapshot → identify → act → verify
agent-cu snapshot -a Music -i -c # what's on screen?
# read the output, find the right @ref
agent-cu click @e5 # do one thing
agent-cu snapshot -a Music -i -c # what changed?
每个操作都会改变界面。 之前的引用现在都已过时。务必重新截图。
打开应用
开始操作之前,务必等待应用就绪:
agent-cu open Safari --wait
agent-cu snapshot -a Safari -i -c
不要与尚未打开并完成截图的应用交互。
查找元素
步骤 1:使用 -i -c 截图(交互式 + 精简):
agent-cu snapshot -a Calculator -i -c
此操作只显示可点击或可输入的元素,并提供类似 @e1、@e5、@e12 的引用。
步骤 2:阅读输出。根据元素名称、角色或 ID 找到所需元素。
步骤 3:使用引用。引用是定位元素最快、最可靠的方式。
如果缺少元素,请增加深度:
agent-cu snapshot -a Safari -i -c -d 8
点击
对于按钮、链接、菜单项,请使用 click:
agent-cu click @e5 # single click (AXPress, headless)
agent-cu click @e5 --count 2 # double-click (opens files, plays songs)
click 会先尝试 AXPress(在后台执行,不会窃取焦点)。只有双击或右键点击时,才会回退到鼠标模拟。
对于具有稳定 ID(在不同快照间不会改变)的元素:
agent-cu click 'id="play"' -a Music
agent-cu click 'id~="track-123"' -a Music # partial id match
输入
指定目标元素(首选——使用 AXSetValue,无头操作):
agent-cu type "hello world" -s @e3
在当前聚焦的字段中输入(键盘模拟,需要应用处于焦点状态):
agent-cu type "hello world" -a Safari
有引用时,务必优先使用 -s @ref。这样更可靠。
按键
agent-cu key Return -a Calculator
agent-cu key cmd+k -a Slack
agent-cu key cmd+a -a TextEdit
agent-cu key Escape -a Safari
滚动
agent-cu scroll down -a Music # scroll main content area
agent-cu scroll down --amount 10 -a Music # scroll more
agent-cu scroll-to @e42 # scroll element into view (headless)
滚动需要应用处于焦点状态。无头操作请使用 scroll-to。
读取内容
agent-cu text -a Calculator # all visible text
agent-cu get-value @e5 # one element's value/state
agent-cu get-value 'id="title"' -a Music # by selector
对于大型应用,请对特定元素使用 get-value,而不是对整个应用使用 text。
窗口管理
agent-cu move-window -a Notes --x 100 --y 100
agent-cu resize-window -a Notes --width 800 --height 600
agent-cu windows -a Finder # get window positions and sizes
这些操作即时完成且无头执行——使用 AXSetPosition/AXSetSize。
拖放
拖动需要应用处于焦点状态,并且两个区域都可见且互不重叠。
像人一样思考:你需要同时看到源位置和目标位置。
# Step 1: Set up windows side by side
agent-cu move-window -a Finder --x 0 --y 25
agent-cu resize-window -a Finder --width 720 --height 475
# (open a second Finder window for destination)
# Step 2: Snapshot to find the file
agent-cu snapshot -a Finder -i -c -d 8
# Step 3: Get the file's position
agent-cu get-value @e32 # check position
# Step 4: Drag to destination
agent-cu drag @e32 @e50 -a Finder # drag by refs
# or by coordinates:
agent-cu drag --from-x 300 --from-y 55 --to-x 1000 --to-y 200 -a Finder
选择器语法
引用(始终优先使用)
@e1, @e2, @e3 # from most recent snapshot
DSL
'role=button name="Submit"' # role + exact name
'name="Login"' # exact name
'id="AllClear"' # exact id (most stable)
'id~="track-123"' # id contains (case-insensitive)
'name~="Clear"' # name contains (case-insensitive)
'button "Submit"' # shorthand: role name
'"Login"' # shorthand: just name
'role=button index=2' # 3rd match (0-based)
'css=".my-button"' # CSS selector (Electron apps only)
链式选择器
'id=sidebar >> role=button index=0' # first button inside sidebar
'name="Form" >> button "Submit"' # submit button inside form
Electron 应用(CDP)
Electron 应用(Slack、Cursor、VS Code、Postman、Discord)会自动检测。首次使用时,agent-cu 会通过启用 CDP 支持重新启动这些应用。
所有操作均可无头执行——无需激活窗口、使用鼠标或窃取焦点:
agent-cu snapshot -a Slack -i -c # full DOM tree via CDP
agent-cu click @e5 # JS element.click()
agent-cu key cmd+k -a Slack # CDP key dispatch
agent-cu type "hello" -a Slack # CDP insertText
agent-cu scroll down -a Slack # JS scrollBy()
agent-cu text -a Slack # document.body.innerText
在 Electron 应用中输入:insertText 会将文本输入到当前聚焦的元素中。若要在特定输入框中输入:
agent-cu snapshot -a Slack -i -c # find the input ref
agent-cu click @e18 # click to focus it
agent-cu key cmd+a -a Slack # select all
agent-cu key backspace -a Slack # clear
agent-cu type "your text" -a Slack # now type
验证
不要假设操作已成功。请检查能反映状态的属性来验证,而不只是再次查看元素树。
id 与 name 的区别(至关重要)
许多应用会为按钮设置一个固定的 id(槽位)和一个会变化的 name(当前标签)。
音乐应用的播放控制按钮是典型示例:
id始终为"play"——它标识该按钮是“播放控制按钮”,即使当前正在播放也是如此。name会根据播放状态在"play"和"pause"之间切换。
要检测状态,请读取 name,而不是 id:
# check if music is playing
agent-cu find 'id="play"' -a Music --compact
# → [{"name":"pause", ...}] ← means: playback is ON
# → [{"name":"play", ...}] ← means: playback is OFF
许多应用都采用相同模式:收藏/取消收藏、静音/取消静音、展开/折叠、关注/取消关注。要确认切换操作是否成功,请务必在操作后读取元素的当前 name。
使用 --expect 进行内联验证
agent-cu click @e5 --expect 'name="Dashboard"'
# clicks, then polls for an element with name="Dashboard". Fails if it never appears.
读取值
agent-cu get-value @e3 # one element's value + role + position
agent-cu find 'id="play"' -a Music --compact # most stable if id is known
agent-cu snapshot -a Safari -i -c # broad check
幂等输入文本
agent-cu ensure-text @e3 "hello" # only types if value differs
读取动态计算值(例如计算器结果)
有些应用不会将结果显示为带标签元素上的常规 value——它隐藏在 staticText 节点中。使用 tree 查找任何带有 value 的节点:
agent-cu tree -a Calculator -d 8 --compact | python3 -c "
import json, sys
d = json.load(sys.stdin)
def walk(n):
if n.get('value'): print(n.get('role'), '=', repr(n['value']))
for c in n.get('children', []): walk(c)
walk(d)
"
# → staticText = '1,234×7'
# → staticText = '8,638'
**区域设置提示:**数字会根据区域设置格式化。印度区域设置会显示 7^8 = 57,64,801,国际格式会显示 5,764,801。它们表示相同的值。比较前,请去除逗号和空格。
等待
当 UI 加载需要时间时:
agent-cu wait-for 'name="Dashboard"' # poll until element appears
agent-cu wait-for 'role=button' --timeout 15
sleep 2 # simple delay after navigation
批量操作
串联多个命令,避免每条命令都单独启动:
echo '[["click","@e5"],["key","Return","-a","Music"]]' | agent-cu batch --bail
实际使用模式
在音乐应用中搜索并播放歌曲(已验证流程)
# 1. Open and snapshot
agent-cu open Music --wait
agent-cu snapshot -a Music -i -c
# → @e1 is the Search sidebar item
# 2. Click Search
agent-cu click @e1 -a Music
# 3. Type into the search field — use role=textField, not a ref (the ref
# for the search field changes as the view switches)
agent-cu type "Espresso Sabrina Carpenter" -s 'role=textField' -a Music --submit
sleep 2 # let search results populate
# 4. Pick a result. Grep the snapshot for items matching the track name —
# the `id` embeds a stable catalog id, so grab that.
agent-cu snapshot -a Music -c | grep -i "espresso" | head -5
# → [@e53] other("axcell") "Espresso" id=Music.shelfItem.TopSearchLockup[id=top-search-section-top-1744253558,...]
# 5. Open the album (double-click). Use the full id string, not the ref —
# refs can drift between snapshots during long flows.
agent-cu click 'id="Music.shelfItem.TopSearchLockup[id=top-search-section-top-1744253558,parentId=top-search-section-top]"' -a Music --count 2
sleep 2
# 6. Find the track row and play. The track has a stable id pattern.
agent-cu snapshot -a Music -c | grep "track-lockup" | head -3
# → [@e52] group "Espresso" id=Music.shelfItem.AlbumTrackLockup[...]
# 7. Select, then try Return to play. If that fails, fall back to the
# transport play button directly.
agent-cu click @e52 -a Music
agent-cu key Return -a Music
sleep 1
# 8. Verify via the transport button's `name` — "pause" means playing.
agent-cu find 'id="play"' -a Music --compact
# if name="play", playback didn't start. Fallback:
agent-cu click 'id="play"' -a Music
此流程的要点:
- 如果重大 UI 变化前后的快照之间存在间隔,引用(
@e53)可能会失效。跨快照定位时,优先使用完整的id="..."。 type -s 'role=textField' --submit能可靠地将输入文本、清除内容和按 Return 键组合起来。- 双击搜索结果通常会_打开_项目,而不是_播放_项目。请先进入详情视图,再触发播放。
- 务必通过播放控制按钮的
name验证播放状态(id="play"是槽位;name保存状态)。 - 如果
Return未能触发播放,请改为点击播放控制按钮。请准备备用方案。
在计算器中执行多步计算(已验证流程)
# 1. Open and snapshot — Calculator buttons have stable ids (Seven, Multiply, Equals, etc.)
agent-cu open Calculator --wait
agent-cu snapshot -a Calculator -i -c
# 2. Use batch for the whole keystroke sequence. Avoids 17 per-process starts.
# Example: 7^8 = 7×7×7×7×7×7×7×7 = 5,764,801
echo '[
["click","id=\"AllClear\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Multiply\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Multiply\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Multiply\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Multiply\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Multiply\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Multiply\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Multiply\"","-a","Calculator"],
["click","id=\"Seven\"","-a","Calculator"],
["click","id=\"Equals\"","-a","Calculator"]
]' | agent-cu batch
# 3. Read the result — walk the tree for any staticText with a value.
agent-cu tree -a Calculator -d 8 --compact | python3 -c "
import json, sys
d = json.load(sys.stdin)
for n in [d]:
def walk(n):
if n.get('value'): print(n.get('role'), '=', repr(n['value']))
for c in n.get('children', []): walk(c)
walk(n)
"
# → staticText = '7×7×7×7×7×7×7×7' ← expression
# → staticText = '57,64,801' ← result (Indian locale; strip commas → 5764801)
要点:
- 如果应用为每个交互元素都提供稳定的
id=(计算器就是如此),则无需在点击之间截取快照——直接批量操作即可。 - 结果不在带标签的元素上;请遍历树,查找带有
value的节点。 - 数字会根据区域设置格式化。解析前请去除逗号和空格。
在 Slack 中打开私信并发送消息
agent-cu key cmd+k -a Slack
sleep 1
agent-cu snapshot -a Slack -i -c
# find and click the search input
agent-cu click @e18
agent-cu key cmd+a -a Slack
agent-cu key backspace -a Slack
agent-cu type "Vukasin" -a Slack
sleep 1
agent-cu key Return -a Slack
sleep 2
agent-cu type "hey, check this out" -a Slack
agent-cu key Return -a Slack
查看日历事件
agent-cu open Calendar --wait
agent-cu snapshot -a Calendar -i -c -d 6
# read the visible dates
agent-cu text -a Calendar
# navigate to next month
agent-cu click @e3 # next month button
sleep 1
agent-cu text -a Calendar
填写网页表单
agent-cu open Safari --wait
agent-cu snapshot -a Safari -i -c
agent-cu type "https://example.com/form" -s @e34
agent-cu key Return -a Safari
sleep 3
agent-cu snapshot -a Safari -i -c -d 8
agent-cu type "John Doe" -s @e5
agent-cu type "[email protected]" -s @e6
agent-cu type "Hello world" -s @e7
agent-cu click @e8 # submit button
agent-cu snapshot -a Safari -i -c # verify submission
在 Finder 窗口之间拖动文件
# set up side-by-side windows
agent-cu move-window -a Finder --x 0 --y 25
# (ensure two windows open, Downloads left, Desktop right)
agent-cu snapshot -a Finder -i -c -d 8
# find the file (look for textfield with val="filename")
agent-cu click @e32 # select the file
agent-cu drag --from-x 300 --from-y 55 --to-x 1000 --to-y 200 -a Finder
浏览 App Store
agent-cu open "App Store" --wait
agent-cu snapshot -a "App Store" -i -c -d 10
agent-cu click 'id="AppStore.tabBar.discover"' -a "App Store"
sleep 2
agent-cu scroll down --amount 5 -a "App Store"
agent-cu snapshot -a "App Store" -i -c -d 10
agent-cu text -a "App Store"
规则
- 操作前务必先截取快照。 看不到的内容就无法操作。
- 操作后务必再次截取快照。 UI 已发生变化,之前的引用已失效。
- 下一步用引用,长期操作用 ID。 引用(
@e5)适合在截取快照后立即执行下一步操作,速度最快。完整的id="..."选择器在多次快照后依然有效,适合之后还要返回操作的目标。 - 截取快照时使用
-i -c。 启用交互模式并压缩输出,可减少 10 倍噪声。 - 应用提供稳定 ID 时,优先使用
id=而非name=。 ID 不会随状态变化,名称则常会变化。 - 检测状态时,读取
name属性,而不是id。 许多应用会将id固定为槽位,而通过改变name反映当前状态(播放/暂停、静音/取消静音、收藏/取消收藏)。 - 导航后等待。 优先使用
wait-for等待已知的界面标志;如果没有,则使用sleep 2-3。 - 每次只执行一个操作,然后验证。 未检查状态前,不要连续执行多个修改操作。
- 使用
type -s @ref,而不是type -a App。选择器路径使用 AXSetValue(可靠),应用路径使用键盘模拟(脆弱,需要焦点)。 - 已知目标元素时,使用
scroll-to @ref。 它可在无头模式下使用;scroll down需要焦点。 - 不要硬编码特定应用的逻辑。 不要编写像
play_song_in_music()这样的辅助函数。对所有应用都使用相同的基本操作(snapshot、click、type、key、find)。场景树会指引你要做什么——读取它、执行操作、验证结果。 - 为每个操作准备备用方案。 如果
click未产生预期的状态变化,逐步升级处理:双击 →scroll-to+click→ 键盘快捷键 → 直接操作按钮(例如,使用传输控件id="play",而不是按曲目行上的 Return)。请参阅恢复手册。 - ID 稳定且数量较多时,批量操作。 对于计算器、表单和键盘输入流程,将 JSON 数组传入
agent-cu batch更合适——只需启动一个进程,而非 N 个。
恢复手册
遇到问题时,原则是:诊断确切的故障模式,然后应用相应的备用方案。切勿盲目重试同一命令。
找不到元素(引用已失效)
症状:对来自较早快照的 @ref 操作时,出现 error: element not found matching SelectorChain { ... }。
原因:引用对应特定的树路径;重大 UI 变更(导航、滚动、打开模态框)会使其失效。
修复:重新截取快照并使用新的引用,或改用稳定的 id=:
agent-cu snapshot -a Safari -i -c
# …find it again, or use the full id you saw earlier:
agent-cu click 'id="the-stable-id"' -a Safari
对于需要跨多个快照操作的目标,优先使用 id="..."。引用仅用于单步操作。
选择器不明确
症状:出现 error: ambiguous selector: found N elements matching。
修复:添加 index=,或按角色/名称缩小范围:
agent-cu click 'role=button index=0' -a Music
agent-cu click 'role=button name="Save"' -a TextEdit
点击成功但没有任何反应
症状:返回 {"success": true, "message": "clicked at (X,Y)"},但预期的状态变化(新页面、播放、菜单)没有发生。
按以下顺序诊断:
- 是否使用了 AXPress,还是退回到坐标操作?
pressed "Name" at (X,Y)= AXPress 成功(最佳)。clicked at (X,Y)= 坐标点击;元素可能已移动或被遮挡。
- 元素的实际状态是否与你认为的一致? 读取承载状态的元素的
name属性(例如 Music 的传输按钮),而不只是查看树。 - 此操作是否需要焦点? 有些应用(尤其是 Web UI)需要位于前台。
agent-cu open App --wait会激活应用。
备用方案顺序:
# Ladder 1: AXPress failed — try double-click
agent-cu click @e5 --count 2
# Ladder 2: Element offscreen — bring it in, then click
agent-cu scroll-to @e5
agent-cu click @e5
# Ladder 3: The clicked element isn't the one that triggers the action —
# drill into the container and find the explicit action button
agent-cu snapshot -a Music -c | grep -E "play|pause|Next"
agent-cu click 'id="play"' -a Music
# Ladder 4: Keyboard shortcut fallback
agent-cu key Return -a Music # activate selected item
agent-cu key space -a Music # play/pause
输入未生效
症状:文本未出现在字段中。
原因及修复方法:
# Cause: no ref — fell back to keyboard sim which needs app focus
agent-cu type "hello" -a Safari
# Fix: use selector path (AXSetValue, reliable)
agent-cu type "hello" -s @e3
# Cause: field wasn't focused when keyboard sim fired
agent-cu click @e3 # focus it first
agent-cu type "hello" -s @e3 # then type
# Cause: existing value not cleared
agent-cu type "new" -s @e3 --append # wrong: keeps old text
agent-cu type "new" -s @e3 # right: clears first
已提交搜索,但结果尚未出现在树中
症状:--submit 后立即执行 snapshot,显示的仍是旧页面。
修复:等待后重新截取快照。优先使用轮询,而不是 sleep:
agent-cu type "query" -s 'role=textField' -a Music --submit
agent-cu wait-for 'name~="Top Results"' --timeout 5
agent-cu snapshot -a Music -i -c
如果 wait-for 不知道稳定的界面标志,则改用 sleep 2。
快照深度不足——找不到元素
增加深度:
agent-cu snapshot -a Safari -i -c -d 8
agent-cu snapshot -a Safari -i -c -d 12 # for deeply nested apps
Ref 指向了错误的对象
症状:@e5 点击了某个对象,但不是你预期的对象。
原因:快照悄悄重新运行了(你获取了两次快照),Ref 被重新编号了。
解决方法:对任何重要操作,始终先检查 Ref 解析到的元素:
agent-cu get-value @e5 -a Safari
# confirm role, name, id are what you expect, THEN click
Electron 应用未使用 CDP
agent-cu 会自动检测 Electron 应用。如果 CDP 无法正常工作:
agent-cu snapshot -a Slack -i -c -v # verbose shows CDP status
首次运行需要约 5s,因为应用会使用 --remote-debugging-port 重新启动。之后的每次运行都会使用缓存的连接(约 15ms)。
DSL 选择器解析错误
症状:unknown filter key: 'id_contains'。
解决方法:部分匹配的语法是 id~=(波浪号加等号),而不是 id_contains=:
agent-cu click 'id~="track-"' -a Music
agent-cu click 'name~="Submit"' -a Safari
输出格式
所有输出均为 JSON:
{"success": true, "message": "pressed \"7\" at (453, 354)"}
{"error": true, "type": "element_not_found", "message": "..."}
{"role": "button", "name": "Submit", "value": null, "position": {"x": 450, "y": 320}}