terminal-mac Agent 技能实战:用 MCP 工具与 CLI 安全操控虚拟 Mac

发布时间:2026/11/6 3:29:07

terminal-mac Agent 技能实战:用 MCP 工具与 CLI 安全操控虚拟 Mac 【免费下载链接】terminal-macEntire MacOS running in your terminal.项目地址https://gitcode.com/gh_mirrors/te/terminal-mac点击查看免费下载本文以 terminal-mac 随包发布的 Agent 技能文档为主线讲清楚一个 computer-use Agent 如何在一台独立的虚拟 macOS 上完成「观察 → 操作 → 复核」的闭环优先通过 MCP 工具驱动没有 MCP 时退回 CLI并在遇到登录界面、系统权限弹窗等情形时把控制权交还给用户。读完后你将掌握各工具/命令的准确参数语义、坐标系统、失败判定方式以及源码层面这些行为是如何被实现和约束的。一、定位为什么要一台别人的 Macterminal-mac在 Apple silicon 上通过 Apple Virtualization 运行一个真实的 macOS guest。辅助程序helper跑在 guest 内部由它截取 guest 屏幕、投递输入事件因此 Agent 的每一次点击、每一次键入都发生在虚拟机里不会移动物理 Mac 的指针也不会改写宿主机剪贴板。这个设计直接决定了技能文档的三条基本假设guest 是一台独立的 Mac有自己的应用、文件、账户和权限不继承宿主机正在运行的应用与已登录会话宿主机侧的屏幕与输入 API不参与Agent 操作没有回退到宿主机的路径因此 guest 未登录、helper 未运行、权限未授予时Agent 只能报告状态并请用户处理而不能绕过。技能文档的适用场景写得很明确需要真实 macOS GUI 的任务——测试 Mac 应用、使用某个网站或桌面应用、以及任何希望被沙箱化的 computer-use 任务。运行前提Apple silicon、macOS 14 或更高、首次运行需联网下载恢复镜像在 README.md 中有完整说明。二、第一优先级使用 MCP 工具而不是拼命令如果当前环境已经暴露了来自terminal-macMCP server 的screenshot、click、type、key等工具技能文档要求优先使用它们。原因不只是调用更短MCP 这一层还额外负责把 guest 返回的 PNG 压缩成更小的图片、在动作后追加一次截图、以及把没有登录会话这类超时翻译成可读的处置建议。2.1 四步标准循环技能文档给出的顺序是固定的status确认 VM 正在运行且 guest 的两项权限都是truescreenshot之后你传给其他工具的所有 x/y都是这张图里的像素原点在左上角执行动作clickclicks: 2双击、button: right右键、move、drag、scroll负dy向下滚动、type字面文本或keyreturn、tab、escape、cmdspace、cmdc、cmdshift4等再看一次给动作传screenshot: true或单独调用screenshot然后才决定下一步。2.2 工具清单与参数边界下表是技能文档提到的那组工具的完整参数边界取值范围来自 Sources/TerminalMac/AgentServer.swift 中的 JSON Schema工具必填参数可选参数取值约束语义screenshot无无只读截取 guest 屏幕返回图片与用它作为坐标的提示status无无只读VM 是否运行 guest 两项隐私权限clickx,ybutton,clicks,screenshotbutton仅left/rightclicks1–3单/双/三击movex,yscreenshot坐标 ≥ 0移动指针用于展开 hover 菜单或提示dragx,y,toX,toYscreenshot坐标 ≥ 0按下左键、拖到目标、释放scrollx,y,dydx,screenshotdy/dx在 -1000…1000负dy向下滚相当于上滑typetextscreenshot字面文本向焦点输入框输入文本keykeyscreenshot组合键字符串回车、Tab、方向键与快捷键技能文档同时强调type只用于字面文本回车、Tab 和快捷键必须走key。这不是风格问题——源码里两者走完全不同的实现路径见第四节。2.3 源码视角坐标、双击与再看一眼几个容易踩坑的行为在源码里都有明确落点坐标语义MCP 的screenshot()注释写明返回的是point-sized screenshot即图片像素等于 guest 的屏幕点其他工具接收的 x/y 因此可以直接使用返回的文本也会带上Screen: W×H. Use these pixel coordinates.这句提示Sources/TerminalMac/AgentServer.swift。图片被转成 JPEGguest 交回的是 PNGMCP 层用 0.85 的质量重新编码为 JPEG 以缩小消息体因此模型看到的分辨率不变、体积更小。CLI 路径则原样落盘 PNG。双击不是一个标志位click的clicks: n会被展开成 n 个请求第 k 个请求带count: k从 1 开始逐个续接guest 侧把这些事件写入mouseEventClickStatemacOS 才会识别为双击/三击Sources/TerminalMac/AgentServer.swift、Sources/TerminalMac/Guest.swift。screenshot: true有 400 毫秒延迟注释说明是为了给动画和重绘一点时间随后才截图避免拿到动作生效前的旧帧Sources/TerminalMac/AgentServer.swift。超时预算各自独立click/move/key/scroll为 10 秒drag15 秒type30 秒status5 秒。长文本输入因此比点一下更贵。2.4 注册 MCP server技能文档假设工具已经可用把它接进客户端的方式在 README.md 的 Use with agents 一节claude mcp add terminal-mac -- terminal-mac mcp terminal-mac skills install # → ~/.claude/skills/terminal-mac/SKILL.md其他 MCP 客户端Cursor、VS Code、Codex、Windsurf 等把terminal-mac mcp --config的输出粘进客户端的 MCP 设置即可驱动非default的 VM 用terminal-mac mcp NAME。--config的实现有一个值得注意的细节它输出的是启动器路径而不是版本化 bundle 的路径这样升级后配置不需要改。见 Sources/TerminalMac/CLI.swift。输出的 JSON 形如{ mcpServers: { terminal-mac: { command: /path/to/terminal-mac, args: [mcp] } } }handshake 阶段server 会返回serverInfo名称terminal-mac与当前版本以及一段instructions其中复述了同样的规则先截图、坐标以截图为基准、动作后再截图、遇到登录或权限提示请用户处理Sources/TerminalMac/AgentServer.swift、Sources/TerminalMac/AgentServer.swift。三、没有 MCP 时CLI 的等价能力技能文档给出的 CLI 形态非常克制核心只有一句话每条命令都打印 JSON失败时以非零状态退出NAME默认是default。terminal-mac status NAME # stopped → terminal-mac start NAME terminal-mac action NAME status terminal-mac action NAME screenshot --output /tmp/guest.png # then view the PNG terminal-mac action NAME click X Y [--double] [--button right] terminal-mac action NAME move X Y terminal-mac action NAME drag X Y X2 Y2 terminal-mac action NAME type literal text terminal-mac action NAME key cmdspace terminal-mac action NAME scroll --dy -300 --x X --y Y3.1 命令名与 VM 名的解析顺序action子命令的位置参数解析有点特殊如果第一个位置参数本身就是一个动作名status、screenshot、snapshot、click、move、drag、scroll、type、key之一那么 VM 名取默认值default否则第一个位置参数被当作 VM 名。这样action screenshot和action default screenshot都能工作Sources/TerminalMac/CLI.swift。VM 名不是随便什么字符串都行必须匹配^[a-zA-Z0-9][a-zA-Z0-9_-]{0,47}$即 1–48 位字母、数字、下划线或连字符且以字母或数字开头。这个校验同时用于防止路径穿越测试用例里../host、/tmp、a/b、a b、49 个字符的名字都会被拒绝Sources/TerminalMacCore/Models.swift、Tests/TerminalMacCoreTests/CoreTests.swift。3.2 参数细节与默认可值选项适用动作说明--output PATHscreenshot/snapshot落盘路径默认terminal-mac-NAME.png支持~展开--doubleclick等价于双击--button rightclick右键--text valuetypetype literal text的另一种写法--keykey显式指定组合键--dx,--dyscroll像素级滚动量--dy为负表示向下--timeout全部动作1–120 秒默认 15--全部结束选项解析用于文本以-开头的场景screenshot与snapshot目前是同一个动作snapshot只是别名不是accessibility tree 快照——这一点技能文档与 README.md 都特意声明避免 Agent 误以为能拿到控件树。截图回传也有大小上限CLI 侧读取上限 32 MiBMCP 侧 64 MiBSources/TerminalMac/CLI.swift、Sources/TerminalMac/AgentServer.swift。3.3 打开应用优先用键盘技能文档给出的示例是terminal-mac action NAME key cmdspace terminal-mac action NAME type Safari terminal-mac action NAME key return并在旁边补了一句优先使用键盘快捷键而不是去追小目标。原因很实在菜单栏、工具栏里的小图标在缩放开销与命中误差上都更脆弱而 Spotlight 的输入路径稳定、可重复。四、输入语义为什么type与剪贴板无关技能文档对type的描述是Text is sent as Unicode keyboard events, not through the clipboard. No shell-execution action exists. 这两句话都很关键前者保证不会污染 guest 的剪贴板也不会反向影响宿主机后者说明这套工具没有任何执行 shell 的入口——Agent 只能像人一样操作 GUI。落到源码type的约束更加具体文本以 UTF-8 字节计数上限32 KiB超出即报错文本按 UTF-16 code unit 切块每块最多16 个单元就随一次按键按下/抬出发送避免超出 CGEvent 的单次字符串容量事件源为nil通过keyboardSetUnicodeString携带字符投递到.cghidEventTap——整条链路不触碰任何剪贴板 APISources/TerminalMac/Guest.swift。key则是虚拟键码加修饰键的组合修饰键识别cmd/command、ctrl/control、alt/option、shift键名覆盖字母、数字、常用符号、return/enter、tab、space、backspace、escape/esc、home、end、pageup、pagedown、delete、四个方向键与f1–f12。未知键或未知修饰键会返回明确错误并给出cmdspace这样的示例Sources/TerminalMac/Guest.swift。drag的实现不是起点一次、终点一次而是在两点之间按距离插值出 2–30 个中间点每步间隔约 8 毫秒最后才释放左键——这更接近真人拖动也是文本选择、窗口移动能成功的原因Sources/TerminalMac/Guest.swift。scroll则构造像素单位的滚轮事件dy与dx都在 -1000…1000 之间校验。五、什么时候必须停下来问用户技能文档把停下来的条件写成清单这几条对应的是 Agent无法自行绕过的边界guest 停在登录界面或 helper 没有运行工具报告 no logged-in session请用户登录例如执行terminal-mac view NAME后按 CtrlO。让 guest 开启自动登录可以避免后续每次启动都卡在这里。guest 内出现 macOS 权限弹窗、密码、双因素验证码或支付界面。VM 根本不存在terminal-mac up NAME会从 Apple 下载数 GB 的 macOS并且首次设置必须由用户完成。这三条在实现上都有对应判定超时的两种含义被区分开了。MailboxTimeout带一个pickedUp标记请求文件从未被读取说明根本没有 helper 在轮询典型情况是 guest 还在登录界面请求被读取但没有回音则说明 helper 在忙或卡住。MCP 层据此给出不同文案第一种直接建议用户用terminal-mac view NAME加 CtrlO 登录Sources/TerminalMacCore/Mailbox.swift、Sources/TerminalMac/AgentServer.swift。VM 不存在和VM 已停止是两条不同的错误。requireRunning()每次调用都会检查因此 MCP server 可以在还没有任何 VM 时就启动并列出工具真正调用时若找不到 VM会提示用户运行terminal-mac up若 VM 存在但未运行则提示terminal-mac start NAMESources/TerminalMac/AgentServer.swift。就绪状态是两项权限都真才算真。GuestReadiness的判定逻辑是screenRecording true accessibility true才为ready任一为假都归为permissions而在没有任何回复时是unavailable。测试用例覆盖了这四种组合Sources/TerminalMacCore/Setup.swift、Tests/TerminalMacCoreTests/CoreTests.swift。安装是否完成的判定同样来自命令路径。start会先检查machine.json中的installed字段未完成安装时给出明确失败提示而不是尝试启动一台半成品 VMSources/TerminalMac/CLI.swift。六、安全边界三条不要与它们的实现依据技能文档的安全条款简短但强硬不要在宿主机上运行terminal-mac guest也绝不回退到宿主机的截图或输入工具VM 里的应用、文件、账户与用户的 Mac 相互独立除非用户要求不要把密钥材料移进去stop是请求关机stop --force可能丢失 guest 内未保存的工作只在正常关机无法完成时使用。第一条不是约定而是代码强制的GuestGuard.requireVirtualMac()读取hw.model要求其以VirtualMac开头否则直接抛错。guest子命令、GuestRuntime初始化、以及每个请求的处理入口都会调用它Sources/TerminalMac/Guest.swift、Sources/TerminalMac/Guest.swift。入口层还会在启动阶段先做一次检查失败即退出并返回非零状态Sources/TerminalMac/Entry.swift。需要说明的是这个检查的目的是防止误在宿主机上执行官方文档也明确它不是硬件证明也不构成对已被攻陷宿主机的防御。第三条对应的是两段不同的实现stop调用vm.requestStop()并设置 60 秒期限超时后提示可使用--forcestop --force走vm.stop()并立即退出进程Sources/TerminalMac/VirtualMachine.swift。宿主与 guest 之间只有两条显式通道可读写的control请求/应答 JSON 与截图与只读的toolshelper 应用。从源码结构看共享目录就是在配置阶段按这两个名字注册的宿主机 home、项目目录、剪贴板、麦克风与摄像头都不在共享列表中Sources/TerminalMac/VirtualMachine.swift。控制通道本身也没有网络监听它是一组平铺的 JSON 文件目录句柄用O_NOFOLLOW打开并被钉住读取时校验必须是普通文件、硬链接数为 1、大小不超过上限文件名禁止/、..与空字符应答 ID 必须与请求匹配过期请求直接丢弃并在遍历时删除。这些行为都有对应测试Sources/TerminalMacCore/Mailbox.swift、Tests/TerminalMacCoreTests/CoreTests.swift。token 与凭据不会经过这条通道宿主也从不执行 guest 提供的内容。七、把技能装进 Agent 的几种方式技能文档本身就是可安装的资产。随包发布的构建里SKILL.md位于应用 bundle 的Resources/skills/terminal-mac/SKILL.md开发构建则从可执行文件所在目录向上最多 6 层查找skills/terminal-mac/SKILL.mdSources/TerminalMac/CLI.swift。terminal-mac skills get # 打印与本版本匹配的技能全文 terminal-mac skills path # 打印技能文件所在路径 terminal-mac skills install # 默认安装到 ~/.claude/skills/terminal-mac/SKILL.md terminal-mac skills install --dir PATH # 安装到任意 skills 目录install带一个保护如果目标位置已存在一份不是terminal-mac 的技能判定方式是内容里没有\nname: terminal-mac\n会拒绝覆盖并报错避免误删别的技能Sources/TerminalMac/CLI.swift。对使用AGENTS.md的 AgentREADME.md 建议加一行在使用虚拟 Mac 之前先运行terminal-mac skills get这样 Agent 拿到的指令永远与已安装的版本一致而不是散落在提示词里的一段过期文本。docs/AGENT.md 也说明完整指南就是这份技能文件并保留了 CLI 参考。八、排错速查现象可能原因处置工具报 no logged-in sessionguest 在登录界面或 helper 未运行请用户terminal-mac view NAME后按 CtrlO 登录工具报权限相关错误guest 内未授予 Screen Recording / Accessibility请用户在 guest 内点 helper 的两个 Allow 按钮status显示 VM 停止被stop或未启动terminal-mac start NAME找不到 VM尚未创建请用户执行terminal-mac up NAME需下载 macOS 并完成首次设置坐标点偏用了旧截图的坐标或忽略了 HiDPI重新screenshot严格使用新图左上角原点输入没反应只授予了屏幕录制没有辅助功能检查status中accessibility是否为true其中最后一条在终端查看器里有更直观的提示一旦有帧但输入权限缺失头部会显示 ⚠ input needs Accessibility而 helper 的状态应答同时提供screenRecording与accessibility两个布尔值正是status工具的判断依据Sources/TerminalMac/Viewer.swift、Sources/TerminalMac/Guest.swift。九、验证边界哪些结论可以当真技能文档描述的是应该怎么用不等于全部已在真机验证。仓库的验证记录明确区分了两类结论已完成的自动化检查Debug 构建与 14 个 XCTest 协议/输入/设置测试全部通过Release 构建通过打包应用通过严格递归签名校验宿主 entitlements 含com.apple.security.virtualization而 guest 不含guest --check在物理宿主机上拒绝运行并以非零状态退出。尚未完成的真机验收下载恢复镜像并创建 VM、在原生窗口完成 Setup Assistant、在 guest 内授予隐私权限、验证 Retina/非 Retina 下的坐标对齐、在 Ghostty/Kitty/iTerm2 中实测查看器、暂停/恢复与强制关机等。因此 docs/VALIDATION.md 特别声明在这些检查完成之前内联终端渲染、guest 隐私授权、guest 截图与 guest 输入行为都不应被描述为已实测通过。自动化测试覆盖的是邮箱往返、过期与清理、文件边界防御、名称与选项校验、分片 UTF-8 与终端输入序列——它们是协议级证据不是VM 已成功安装、启动并被操控的证据。把这条边界带上Agent 在真实环境中才不会被过度承诺误导。赞分享【免费下载链接】terminal-macEntire MacOS running in your terminal.项目地址https://gitcode.com/gh_mirrors/te/terminal-mac点击查看免费下载相关推荐如何用一句话指挥 AI 做 SQL 注入测试CyberStrikeAI 技能系统完整指南如何用一句话指挥 AI 做 SQL 注入测试CyberStrikeAI 技能系统完整指南 当你对 CyberStrikeAI 说一句对这个登录接口做 SQL三步跑通 DataEase 内网离线部署无网络环境完整安装指南三步跑通 DataEase 内网离线部署无网络环境完整安装指南 你负责的那台服务器完全隔离外网想在上面跑一套开源 BI 工具 DataEase 来做数据可视数据可视化数据分析后端前端XCOM 2模组管理终极指南Alternative Mod Launcher完整解决方案XCOM 2模组管理终极指南Alternative Mod Launcher完整解决方案 厌倦了XCOM 2官方启动器的限制Alternative Mod桌面应用游戏开发上一篇Security-101 安全运营入门SecOps 关键概念与 NIST 事件响应工作流全解析下一篇Security-101 课程精讲IAM 零信任架构——以身份作为现代 IT 环境的新边界创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/6 3:29:07

mybatis-plus - 乐观锁的使用

mybatis-plus - 乐观锁的使用 添加版本号更新插件 Bean public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return inte…

2026/11/6 3:29:07

WSL2 AI 环境搭建实录:Docker 与 Miniconda 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/6 4:34:17

单链表实现与核心操作详解

1. 单链表基础概念解析单链表作为数据结构中最基础也最重要的线性结构之一,是每个程序员必须掌握的硬核技能。记得我初学链表时,曾被指针的指针绕得头晕目眩,直到亲手实现了一遍所有操作才真正理解其精髓。本文将用8000字的篇幅,带…

2026/11/6 4:34:17

测试工程师如何识别和预防需求缺陷

1. 需求战场的隐形地雷:测试工程师的排雷手册在软件开发的战场上,需求缺陷就像埋藏在前进道路上的地雷,随时可能引爆项目危机。作为测试工程师,我们不仅是最后的防线,更应该成为冲锋在前的排雷兵。根据行业数据&#x…

2026/11/6 4:34:17

云原生时代运维转型:从手动配置到DevBox自动化

1. 运维角色的历史演变与技术冲击2000年初期的运维工作场景与今天截然不同。那时的运维工程师需要亲自上架服务器、配置交换机、安装操作系统,工作内容高度依赖物理设备操作。我曾见过一位老运维的笔记本,上面密密麻麻记录着不同机房的设备位置、IP分配和…

2026/11/6 4:34:17

JS金额补零到两位小数:toFixed浮点坑与整数分方案

做前端这些年,被问得最多的一类“小问题”就是金额为什么少了个 0。JS 金额补充到 2 位小数、末尾自动补零、整数后面补上“.00”——单看每一条都简单得不像个问题,真写进项目里,边界情况能把人折腾一下午。前阵子帮朋友看一个记账小工具&am…

2026/11/6 4:34:16

动态规划解决子序列问题:从LIS到最大子序和

1. 动态规划在子序列问题中的应用概述动态规划(Dynamic Programming)是解决子序列问题的利器,尤其擅长处理那些需要全局最优解的序列匹配问题。在算法领域,子序列问题通常分为两大类:连续子序列和非连续子序列。连续子…

2026/11/6 4:29:16

数据库连接操作详解:从内连接到外连接

1. 数据库连接操作的本质理解在数据库查询中,连接(Join)操作就像是在两个数据表之间搭建桥梁。想象你手上有两份Excel表格:一份记录着公司所有员工的基本信息,另一份存储着各部门的绩效数据。当我们需要分析"每个…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/6 1:03:39

MCU晶振电路设计全解析:从负载电容计算到PCB布局调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑