mcpField
A
agent-computer-use

agent-computer-use

github.com/kortix-aiAgent 工作流68170 次安装4 周前更新
代码仓库

关于 agent-computer-use

通过 agent-cu CLI 控制桌面应用的计算机操作技能。它强调截图、操作、验证的循环,并提供元素选择器、键盘与鼠标操作及常见应用工作流指引。

主要功能

  1. 01通过 agent-cu CLI 控制桌面应用
  2. 02屏幕截图与元素选择器
  3. 03点击、输入、滚动和按键
  4. 04基于状态验证操作结果
  5. 05批量命令与应用工作流

适用场景

  1. 01导航和操作桌面应用
  2. 02在浏览器中填写网页表单
  3. 03在 Music 中搜索并播放音乐
  4. 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 会提示用户批准。用户有以下三个选项,按推荐顺序排列:

  1. 最简单 — 在终端中运行 agent-cu setup。交互式向导会将 Bash(agent-cu *) 写入正确的设置文件。只需设置一次。如果用户似乎对反复出现的批准提示感到沮丧,可以建议此选项。

    如果你(Agent)自己运行,但无法响应提示,请使用非交互式标志:

    • agent-cu setup --yes → 无监督 + 全局(推荐默认值)
    • agent-cu setup --mode <unsupervised|supervised> --scope <global|project> 用于指定组合
  2. 最快 — 在批准提示中选择 "Yes, and don't ask again for: agent-cu *"。此选项只适用于该特定子命令模式;其他子命令仍会再次提示。

  3. 手动 — 在 ~/.claude/settings.json 的 permissions.allow 下添加 "Bash(agent-cu *)"。

不要尝试自行修改用户的设置文件——请让用户改用 agent-cu setup。

思考方式

像坐在电脑前的人一样思考。 操作之前,先问自己:我会在屏幕上看到什么?会点击什么?会输入什么?

人会:

  1. 查看屏幕(快照)
  2. 找到所需内容(识别引用)
  3. 执行一个操作(点击、输入、按键)
  4. 检查发生了什么变化(重新截图)

你必须照做。不要跳过步骤。不要假设操作后界面没有变化。

核心循环

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"

规则

  1. 操作前务必先截取快照。 看不到的内容就无法操作。
  2. 操作后务必再次截取快照。 UI 已发生变化,之前的引用已失效。
  3. 下一步用引用,长期操作用 ID。 引用(@e5)适合在截取快照后立即执行下一步操作,速度最快。完整的 id="..." 选择器在多次快照后依然有效,适合之后还要返回操作的目标。
  4. 截取快照时使用 -i -c。 启用交互模式并压缩输出,可减少 10 倍噪声。
  5. 应用提供稳定 ID 时,优先使用 id= 而非 name=。 ID 不会随状态变化,名称则常会变化。
  6. 检测状态时,读取 name 属性,而不是 id。 许多应用会将 id 固定为槽位,而通过改变 name 反映当前状态(播放/暂停、静音/取消静音、收藏/取消收藏)。
  7. 导航后等待。 优先使用 wait-for 等待已知的界面标志;如果没有,则使用 sleep 2-3。
  8. 每次只执行一个操作,然后验证。 未检查状态前,不要连续执行多个修改操作。
  9. 使用 type -s @ref,而不是 type -a App。选择器路径使用 AXSetValue(可靠),应用路径使用键盘模拟(脆弱,需要焦点)。
  10. 已知目标元素时,使用 scroll-to @ref。 它可在无头模式下使用;scroll down 需要焦点。
  11. 不要硬编码特定应用的逻辑。 不要编写像 play_song_in_music() 这样的辅助函数。对所有应用都使用相同的基本操作(snapshot、click、type、key、find)。场景树会指引你要做什么——读取它、执行操作、验证结果。
  12. 为每个操作准备备用方案。 如果 click 未产生预期的状态变化,逐步升级处理:双击 → scroll-to + click → 键盘快捷键 → 直接操作按钮(例如,使用传输控件 id="play",而不是按曲目行上的 Return)。请参阅恢复手册。
  13. 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)"},但预期的状态变化(新页面、播放、菜单)没有发生。

按以下顺序诊断:

  1. 是否使用了 AXPress,还是退回到坐标操作?
    • pressed "Name" at (X,Y) = AXPress 成功(最佳)。
    • clicked at (X,Y) = 坐标点击;元素可能已移动或被遮挡。
  2. 元素的实际状态是否与你认为的一致? 读取承载状态的元素的 name 属性(例如 Music 的传输按钮),而不只是查看树。
  3. 此操作是否需要焦点? 有些应用(尤其是 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}}

评论

支持 Markdown