关于 Ghost
Ghost 是面向 Windows 和 Linux 上 Agent 与脚本的 MCP 服务及桌面自动化层。它可在后台控制原生应用、窗口、Shell 和浏览器,并检查每项操作是否成功。
主要功能
- 01后台桌面控制
- 02基于辅助功能发现元素
- 03操作结果验证
- 04窗口、Shell 和浏览器工具
- 05CLI 与本地 REST API
适用场景
- 01自动化没有 API 的旧应用
- 02不抢占焦点地执行 GUI 任务
- 03检查桌面操作是否成功
- 04控制窗口和浏览器标签页
MCP 相关
Ghost 通过 `ghost-mcp` 服务提供桌面自动化工具,涵盖应用、窗口、Shell 和浏览器操作。MCP 客户端可使用其统一的控制与验证流程。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Ghost
为 Agent 和程序提供经过验证的全桌面控制能力,支持 Windows 和 Linux。 Ghost 为 Claude Code、Codex、Cursor、任何 MCP 框架或普通脚本提供操作系统 自身的控制界面:没有 API 的应用、窗口、Shell,以及你已登录的浏览器——在后台运行,不占用 你的屏幕或光标,并且每项操作都能证明已成功执行。
如同 Playwright,但面向原生桌面,并专为 Agent 构建。Ghost 负责感知、操作和验证;你当前运行的 模型会完成所需的查看,因此无需设置视觉 API 密钥。
一个 MCP 接口,两套引擎:Windows 上的 Win32 UI Automation,以及 Linux 上通过 D-Bus 运行的 AT-SPI2。操作动词、定位器层级和“先操作后验证”的循环只需编写一次,在两个平台上的行为 都一致。平台支持 · Linux 设置
Ghost 的不同之处
- 在后台运行,并且这一点受到强制保障。 Agent 可以在你继续于另一个窗口中工作时,在应用内点击、输入和使用快捷键——不会抢占焦点,也不会跳动光标。它会向真实控件发送窗口消息,并对无窗口控件使用 UI Automation 模式;大多数工具只能操作前台中的内容。自 0.19 起,这是一项策略,而非偏好设置:焦点策略默认为
background。自 0.20 起,它也变得切实可靠:Ghost 启动的任何内容(应用、带窗口的浏览器)都会在拥有独立输入队列、无法抢占前台的隐藏桌面上启动;普通操作会按窗口标题在那里驱动它。确实无法在后台执行的调用会明确指出操作并失败,而不会悄悄接管屏幕。自 0.22 起,该策略在此处被锁定:没有任何工具调用可以提升它,因此 Agent 无法自行决定接管你的鼠标。你可以通过在服务的环境中设置GHOST_FOCUS_LOCK=off来解除锁定。自 0.23 起,如果窗口自行抢占前台——浏览器在执行自己的辅助功能调用时就会这样做——Ghost 会立即将前台交还,因此你可以继续在当前关注的窗口中输入。在真实桌面上测得,当有人全程持续输入时,每次运行约 490 次按键中,只有 0 到 1 次输入会到达 Agent 正在操作的窗口。 (原理) - 绝不会误操作你的窗口。 会话会记住 Agent 最近指定或启动的窗口,所有针对窗口的操作默认都以该窗口为目标。只有从未锚定过窗口时,才会使用用户的前台窗口,并且响应会对此作出说明。为期三周的真实对话记录显示,在此之前,最常见的故障是“在前台窗口中找不到元素”;这是因为 Agent 搜索的是你打开的窗口。
- 可同时运行多个 Agent。 请求会并行分发,因此一个标签页中 15 秒的等待不会阻塞后续的即时查询;第二个 Ghost 进程也可以在不争抢鼠标的情况下,运行自己的浏览器。
- 在你的机器上验证。
ghost verify会通过标准输入输出驱动真实的 MCP 服务,并依据严格的时间预算审计以上每项声明;如果其中任何一项在你的硬件上不成立,就会以非零状态码退出。 - 每项操作都会经过验证。 Ghost 会在执行操作后重新检查屏幕(或读回控件的值),并返回
verified/focus_confirmed——绝不会盲目返回ok:true。Agent 常常只执行操作,却不知道是否成功;Ghost 会闭合这个反馈环路。 - 可驱动没有 API 的应用。 传统 Win32、WPF、Electron、UWP、供应商门户——这些软件没有集成接口,却最需要自动化。无需 CDP、浏览器或应用配合。
- 无需视觉密钥。 驱动 Ghost 的模型可以读取
ghost_see(包含每个元素的名称、角色和屏幕中心坐标),也可以自行读取ghost_screenshot。Ghost 自带的视觉层级可选,供没有自有模型的调用方使用,并且在配置前处于关闭状态。 - 原生支持无障碍功能,且深入细致。 通过操作系统自身的无障碍 API 发现真实元素——Windows 上使用 UI Automation,Linux 上使用 AT-SPI2——而不是猜测像素。返回的元素包含真实名称、角色和边界。
通过一个脚本即可了解:examples/background_agent_demo.py 会在后台驱动应用,同时让前台仍由你使用。
与 Playwright-MCP / cua-driver / Computer Use 的客观比较:
docs/comparison.md。
人们用它做什么
视觉只是其中最小的一部分。在典型会话中,Agent 调用 Ghost 主要是为了执行操作、管理窗口和进程、运行命令,以及读取状态。
| 用途 | 工具 | 典型调用方 |
|---|---|---|
| 操作没有 API 的应用:安装程序、传统业务软件、供应商门户、WPF 和 Electron 工具 | ghost_act、ghost_key、ghost_scroll、ghost_drag | Agent、RPA 脚本 |
| 窗口和进程控制:隐式启动、聚焦、最小化、还原、关闭、恢复隐藏窗口、清理遗留的浏览器 | ghost_window、ghost_desktop_*、ghost_stats | Agent、运维脚本 |
| 为 Agent 提供终端:构建、git、CLI、持久化 PowerShell 状态、启动另一个 Claude Code 会话 | ghost_shell、ghost_run | Windows 上的编码 Agent |
| 通过 DevTools 端口操控已登录的浏览器:标签页、导航、DOM 点击、JS 求值、页面文本 | 19 个 ghost_browser_* 和 ghost_tab_* 工具 | Agent、网页自动化 |
| 从没有导出功能的应用中读取数据:无障碍文本、标签页文本、OCR | ghost_see mode=text、ghost_tab_text | Agent、报告脚本 |
| 将“是否成功”变成机器可检查的条件:元素是否存在、值是否相等、等待空闲或文本 | ghost_assert、ghost_wait | QA Agent、CI |
| 隔离桌面:通宵运行 GUI 任务,以及永不触碰人工屏幕的并行 Agent | ghost_window op=launch、焦点策略、ghost_desktop_* | 自主运行 |
| 具有重试和条件的可复现多步骤流程,无需模型参与 | 通过 ghost run、POST /run、ghost_execute_intent 执行意图 | 定时任务 |
| 将剪贴板用作连接无法输入文本的应用的桥梁 | ghost_clipboard | 以上所有场景 |
每一行都遵循相同的保障:操作会返回 verified,默认策略绝不会占用你的前台,按下 Ctrl+Alt+G 会立即停止所有 Ghost 进程。
什么是 Ghost?
Ghost 是模型与桌面之间的层。模型负责推理;Ghost 以操作系统的方式查看屏幕,在不影响前台操作的情况下控制真实控件,并报告操作是否成功。它为 Agent、脚本或程序提供对任意桌面应用的程序化控制——无论是原生 Win32、Electron、WPF、UWP、GTK、Qt,还是其他应用。
在 Windows 上,它使用 UI Automation 发现元素、使用 SendInput 注入键盘和鼠标输入,并使用 DXGI/GDI 捕获屏幕。在 Linux 上,它通过 D-Bus 使用 AT-SPI2 发现元素并执行操作,通过 XTEST(X11)或 RemoteDesktop portal / uinput(Wayland)输入,并使用 X11 GetImage 或 Screenshot portal 捕获屏幕。Linux 引擎完全由 Rust 编写,无需安装 -devel 软件包。
有三种交付方式:
ghost-mcp服务 - 主要接口:供 Claude Code、Claude Desktop、Codex、Cursor 和任意 MCP 客户端使用的模型上下文协议服务(Windows 上有 54 个工具)ghostCLI - 一次性命令,非常适合脚本和 CI(ghost click --name "Submit")ghost-http服务 - 本地 REST API,可通过 Python、Node、curl 或任何其他方式调用(curl http://127.0.0.1:7878/list-windows)
MCP 接口包含 20 个桌面操作、19 个用于在后台控制单个浏览器标签页(Chrome、Comet、Edge、Brave)的 ghost_browser_* / ghost_tab_* 工具,以及 15 个仅限 Windows 的工具:焦点策略,以及用于显式控制用户看不到的隔离 Windows 桌面的 ghost_desktop_*。在默认策略下,你很少需要使用后者:ghost_window op=launch 已经会在隐藏桌面 auto 上启动应用,而 ghost_see / ghost_act / ghost_key / ghost_scroll 可通过 window=<title> 操作该应用,就像操作你自己桌面上的窗口一样(响应中的 target.surface 会告诉你目标所在的桌面)。UIA、窗口消息和屏幕捕获在该桌面上都能正常工作。真正的 SendInput 则无法使用,因为 Windows 会拒绝在输入桌面之外发送它;并且,输入操作会通过读取控件的值来验证,因此,如果目标控件丢弃了发送的字符,就会返回错误,而不会误报成功。桌面操作和浏览器工具也可在 Linux 上构建;焦点策略和隐藏桌面仅限 Windows。
无需 Claude。无需浏览器。无需 CDP。它通过操作系统自身的自动化和输入 API 控制应用,因此也适用于没有 API 或自身自动化钩子的原生应用——无论应用是否专为自动化而构建,都同样可靠。
平台
| 平台 | 状态 | 引擎 |
|---|---|---|
| Windows | ✅ 功能完整且已验证 | ghost-core - Win32 UI Automation、SendInput、已发送的窗口消息、DXGI/GDI 捕获 |
| Linux, X11 | ✅ 可用——已通过针对真实 GTK 应用的实时 CI 测试验证 | ghost-linux - 通过 D-Bus 使用 AT-SPI2、XTEST 输入、X11 GetImage 捕获 |
| Linux, Wayland | ⚠️ 已实现,尚未验证——没有测试在硬件上运行过 | 相同的 AT-SPI2 发现与操作;输入和捕获则通过 RemoteDesktop / Screenshot 门户或 uinput 完成 |
| macOS | 🚧 脚手架 | Accessibility + CGEvent + ScreenCaptureKit——待在 Mac 上构建 |
Wayland 值得单独列出,而不是放在脚注中:它是当前 Ubuntu 和 Fedora 上的默认会话,因此大多数 Linux 用户实际运行的都会是它,而这部分恰恰没有任何测试支持。发现和操作层与 X11 共用,且已覆盖;这里最重要的也是这一层——AT-SPI2 会要求应用执行操作,因此无需移动指针,也无需提升窗口。尚未验证的是底层回退方案:门户输入、门户捕获、uinput。如果你使用 Wayland,请把 ghost doctor 作为首先运行的命令,并做好提交 bug 的准备。欢迎反馈,这也是推动该行状态变化最快的方式。
ghost-session 和 ghost-mcp 是共用的:定位器层级、定位依据级联、执行后验证循环以及 20 个核心 MCP 动词只编写一次,并可在两个平台上运行。底层引擎通过一行 cfg 别名切换。浏览器和标签页工具与引擎无关,可在两个平台上构建;焦点策略和隔离桌面仅适用于 Windows,我们会如实说明,而不会假装它们也可用。
移植后,这一优势依然成立。 在 Windows 上,无需抢占焦点即可驱动应用的能力建立在已发送的窗口消息之上。Linux 上,AT-SPI2 操作提供了更简洁的对应方案:应用通过自己的工具包执行操作,因此无需移动指针,也无需提升窗口。X11 和 Wayland 使用的是同一层代码;合成输入只是更底层的回退方案,而 Wayland 尚未经过测试的正是这个回退方案。
这项能力经过了测试,而非仅仅声称如此:CI 会启动一个真实桌面(Xvfb + D-Bus + at-spi-bus-launcher),驱动一个真实的 GTK 应用,并要求通过 AT-SPI 写入的文本能够从应用中读回,且调用按钮确实会关闭对话框。Wayland 门户输入和捕获已实现,但尚未在硬件上验证。
Linux 设置、验证清单及如实说明的限制:
docs/linux-fedora.md。三个平台的功能矩阵:
docs/cross-platform.md。
Ghost 是一款通用自动化工具。请在你拥有或获准进行自动化操作的系统上使用,并遵守所驱动软件的条款。
安装
一键安装 — MCP Bundle(免费)。 每个版本都会在 Releases 页面提供 ghost-windows-x64.mcpb 和
ghost-linux-x86_64.mcpb。在支持 MCP Bundles 的客户端中打开其中一个(Claude Desktop:设置 -> 扩展 ->
从文件安装),Ghost 即会完成注册,无需设置 PATH 或编辑配置,也无需 API 密钥。Ghost 也已列入
MCP 注册表,名称为 io.github.NORTHTEKDevs/ghost,
因此支持注册表的客户端可以从那里安装。Bundle 仅包含 ghost-mcp 服务;
CLI 和 HTTP 服务位于下方的压缩包中。
预编译二进制文件(免费)。 每个版本都会在 Releases 页面提供适用于这两个平台且附带校验和签名的压缩包:
# Linux x86_64
curl -LO https://github.com/NORTHTEKDevs/ghost/releases/latest/download/ghost-linux-x86_64.tar.gz
curl -LO https://github.com/NORTHTEKDevs/ghost/releases/latest/download/ghost-linux-x86_64.tar.gz.sha256
sha256sum -c ghost-linux-x86_64.tar.gz.sha256
tar -xzf ghost-linux-x86_64.tar.gz && ./install.sh
Windows:从同一页面下载 ghost-windows-x64.zip。验证校验和,解压,然后将文件夹添加到 PATH。接着运行 ghost doctor。
检查下载文件的来源。 每个版本的构建产物都附有签名的构建来源证明,因此你可以证明某个文件确实来自此 仓库的发布工作流,且仅来自该工作流,并对应一个明确的提交:
gh attestation verify ghost-windows-x64.mcpb --repo NORTHTEKDevs/ghost
这些二进制文件目前尚未进行代码签名,因此 Windows SmartScreen 会在首次运行时发出警告(点击 更多信息
→ 仍要运行)。该警告针对的是发布者身份;要验证发布者身份,需要购买与已验证法律实体绑定的证书。上面的来源证明更能有力证明文件来源,且无需付费,但 Windows 无法读取它。
配置任何证书颁发机构(CA)的证书后,流水线就会立即进行签名——参见
docs/code-signing.md;关于签署内容、签署方以及哪些内容会离开你的设备(除非你配置了视觉密钥,否则不会有任何内容),请参阅
docs/signing-policy.md。如果防病毒引擎隔离了某个版本,请验证校验和,并参阅
docs/antivirus.md,了解这些二进制文件如何保持可识别,以及如何报告误报。该工具包带来的是便利,而非能力——Ghost 能做的一切都包含在下方的免费源代码中,而且自行构建只需一条命令。
选项 C — 从源代码构建(免费,MIT)。 Ghost 是开源软件。你可以自行编译:
git clone https://github.com/NORTHTEKDevs/ghost
cd ghost
cargo build --release --bin ghost --bin ghost-http --bin ghost-mcp
# binaries in target/release/
要求:Windows 10 build 19041 或更高版本,或者安装了 at-spi2-core 的 Linux(仅从源代码构建时需要 Rust
stable)。
在 Linux 上:
sudo dnf install at-spi2-core xdg-desktop-portal xdg-desktop-portal-gnome
gsettings set org.gnome.desktop.interface toolkit-accessibility true
./scripts/install.sh # build, install, register the MCP server, run doctor
无需安装 -devel 软件包——Linux 引擎完全由 Rust 编写。完整的设置和故障排除说明:docs/linux-fedora.md。
先检查你的设备:
ghost doctor
报告 PASS/WARN/FAIL;若有任何项目为 FAIL,则以退出码 1 退出。提交问题前先运行此命令——它通常会直接指出问题所在。
- Windows: 构建版本、交互式桌面、UI Automation、DPI 感知、显示器布局、屏幕捕获、可选的视觉凭据。
- Linux: 会话类型(X11/Wayland)、AT-SPI 总线可达性、应用是否实际暴露了可访问性树、选定的输入后端以及屏幕捕获。
快速入门 - 编码 Agent 和 MCP 客户端
Ghost 就是为此而构建的。无需配置,也无需 API 密钥。
Claude Desktop: 从最新版本下载 ghost-windows-x64.mcpb(或 Linux 版本包)并打开它:
Settings -> Extensions -> Install from file。
Claude Code:
claude mcp add ghost --scope user -- C:/path/to/ghost-mcp.exe
任何其他 MCP 客户端(Codex、Cursor、自定义运行框架):将二进制文件注册为 stdio 服务。
{
"mcpServers": {
"ghost": { "command": "C:/path/to/ghost-mcp.exe" }
}
}
Ghost 也已列入 MCP registry,标识为 io.github.NORTHTEKDevs/ghost,供从该处安装的客户端使用。
仓库中的 Dockerfile 可构建无头镜像(docker build -t ghost-mcp .),无需显示器即可响应 initialize 和 tools/list;注册表和 CI 使用它来检查服务。容器没有可操作的窗口,因此它不是实际使用时的安装方式。
Agent 如何使用它。 工作循环是观察、操作、确认:
ghost_see window="Invoice Editor"- 返回窗口中的每个元素及其名称、角色、启用状态和屏幕中心坐标。文本模式会改为提取可读文本,所需 token 大约只有图像模式的十分之一。ghost_act window="Invoice Editor" name="Save" action="click"- Ghost 在后台操作控件,并且只有当屏幕或控件的值显示操作已生效时,才返回verified: true。ghost_screenshot window="Invoice Editor"- 获取像素画面,供模型在需要查看布局、图表或画布时使用。
模型读取第 1 步和第 3 步并作出选择;Ghost 无需猜测图像的含义,也不需要视觉密钥。
除了这个工作循环之外:ghost_shell 可运行命令和持久化 PowerShell 会话;ghost_window 可启动、列出、聚焦、还原和关闭窗口(默认在隐藏桌面上);ghost_assert 和 ghost_wait 可将“是否成功”转化为检查;ghost_tab_* 工具则可操作你已登录的浏览器。大多数实际会话中,这些操作的调用次数都比观察操作更多。
Windows 上有 54 个工具(旧名称仍可调度):20 个桌面操作工具,涵盖查看/快照/查找/操作/按键/滚动/拖动/剪贴板/截图/窗口/终端/等待/查询/运行;19 个 ghost_browser_* / ghost_tab_* 工具;以及 15 个仅限 Windows 的焦点策略和隔离桌面工具。如需从源代码构建而非下载:cargo build -p ghost-mcp --release。
每个工具都在独立任务上运行,因此耗时较长的调用不会阻塞快速调用,第二个 Ghost 进程也可以与第一个同时运行。完成挂载后,运行 ghost verify,即可在自己的机器上进行审计。
速度。 Ghost 自身耗时很短:读取文本约需 75 ms,验证点击约需 200 ms,列出窗口只需 1 ms。拖慢 Agent 会话的是调用前后的操作,而以下三个习惯能消除大部分延迟。只需指定一次窗口名称,之后省略 window=:锚点会按句柄跟踪该窗口,即使窗口标题已更改,旧标题也能立即解析,并在响应中标记 title_drift。等待条件,而非等待固定时长:ghost_wait for=element、for=value 和 for=navigate(在后台设置地址栏,并在标题改变时返回,约需 0.4 到 1.4 s;固定等待则需 6 s)会在目标事件发生时立即返回。使用 ghost_run 批量执行,让一个模型轮次完成多个步骤。scripts/speed-probe.mjs 可针对任意 ghost-mcp 二进制文件测量上述所有耗时。
Shell 控制(ghost_shell)
Ghost 既能操作 GUI,也能操作命令行。ghost_shell 可运行终端命令和持久化 PowerShell 会话,适用于构建、git、CLI、在没有文件工具的主机上编辑文件,或启动应用。op=run 是一次性操作(powershell/pwsh/cmd);op=open 会启动一个持久化 PowerShell,会话中的变量和当前工作目录会在多次 op=send 调用间保留。输出会合并标准输出和标准错误,并截取尾部以适应 Agent 的上下文窗口;命令超时后仍会继续运行,可通过 op=read 获取剩余输出;ghost_stop 可终止失控进程。使用默认 powershell 的 op=run 会由预先启动的备用进程处理,因此命令耗时约 85 ms,而启动新的 PowerShell 需要 230-450 ms(备用进程仅使用一次,并会立即替换;设置 GHOST_SHELL_WARM=off 可禁用此功能)。
从 Agent 启动新的 Claude Code 会话:
ghost_shell op=run cmd='Start-Process wt -ArgumentList "pwsh","-NoExit","-Command","claude"',
然后使用 ghost_see / ghost_act / ghost_key 操作新终端窗口。
**安全性:**Shell 访问权限很强。将服务端环境变量设为 GHOST_SHELL=off,即可完全禁用此操作;此后每个 op 都会返回明确的拒绝信息,同时 GUI 自动化操作仍可正常使用。
快速开始 - CLI
# Launch Notepad and type into it
ghost launch notepad.exe
ghost focus-window "Notepad"
ghost type --role edit --text "hello from ghost"
# Keys and hotkeys
ghost press Enter
ghost hotkey --mods Ctrl --key s
# Screenshot
ghost screenshot --out shot.png
# Enumerate windows or UI
ghost list-windows
ghost describe --window "Notepad"
# Click at coords or by name
ghost click-at 500 300
ghost click --name "Save"
# Run a JSON intent (finite-state machine with retries, timeouts, conditions)
ghost run my-flow.json
echo '{"ops":[{"op":"launch","exe":"notepad.exe"}]}' | ghost run -
所有输出均为 JSON,便于通过管道传递给 jq 或脚本。
快速开始 - HTTP 服务
启动服务:
ghost-http --addr 127.0.0.1:7878
然后使用任何语言:
# Bash / curl
curl http://127.0.0.1:7878/list-windows
curl -X POST http://127.0.0.1:7878/click \
-H 'content-type: application/json' \
-d '{"name":"Submit"}'
curl http://127.0.0.1:7878/screenshot -o shot.png
# Python
import requests
requests.post("http://127.0.0.1:7878/launch", json={"exe": "notepad.exe"})
requests.post("http://127.0.0.1:7878/type",
json={"role": "edit", "text": "hello from python"})
// Node
await fetch("http://127.0.0.1:7878/hotkey", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ mods: ["Ctrl"], key: "s" }),
});
端点:/health、/tools、/click、/click-at、/type、/press、/hotkey、/screenshot、/launch、/list-windows、/focus-window、/window-state、/describe、/clipboard(GET/POST)、/run。
快速开始 - Rust SDK
[dependencies]
ghost-session = { git = "https://github.com/NORTHTEKDevs/ghost" }
use ghost_session::{GhostSession, By, session::Region};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let session = GhostSession::new()?;
session.launch("notepad.exe").await?;
let edit = session.find(By::role("edit")).await?;
edit.type_text("hello world")?;
let png = session.screenshot(Region::full()).await?;
std::fs::write("screen.png", png)?;
Ok(())
}
可靠性模型
由 MCP 客户端驱动的桌面自动化面临恶劣的焦点环境:在工具调用之间,客户端自己的终端通常会重新获得操作系统焦点。Ghost 正是为此而构建的:
ghost_act是原子操作——查找 → 执行 → 通过屏幕变化验证。一次调用即可完成,不会出现跨调用竞态。在默认的background策略下,它会直接操作控件,绝不会将窗口置于前台;启用提升策略后,它还会先将目标窗口置于前台(AttachThreadInput,已确认)。- 每个操作响应都如实反映情况:
verified(屏幕是否确实发生变化)、focus_confirmed(正确的窗口是否位于前台),以及任一项不符合预期时的warning——绝不会盲目返回ok:true。重新发出操作前,请先检查verified。 - 不会遗留任何仍在运行的进程。 Ghost 启动的浏览器都放在关闭时自动终止的作业对象中:无论 MCP 服务以何种方式结束,这些浏览器都会随之结束(启动响应中会提供
dies_with_server)。服务启动时还会清理先前服务遗留的浏览器,并在ghost_stats.orphan_sweep中报告清理结果。 - 锚定到窗口——
ghost_see、ghost_find、ghost_act、ghost_key、ghost_click_at、ghost_scroll、ghost_wait、ghost_assert和ghost_screenshot(除非full=true)都接受window参数 (标题子串,会在你的桌面和 Ghost 的隐藏桌面中进行匹配:精确标题优先于前缀,前缀优先于子串;如果并列,未最小化的窗口优先)。匹配到的窗口会成为会话的锚点:后续未指定window的调用都会以它为目标,绝不会操作人当前正在使用的窗口。ghost_window op=focus在background策略下会锚定窗口但不将其置于前台;op=anchor可设置、清除或报告锚点;每个响应都包含target {hwnd, title, surface, source}。如果标题没有匹配项,则会列出打开的窗口并返回代码 -32007。 - 通过浏览器自身的协议操作你的浏览器——当窗口所属的进程以
--remote-debugging-port启动时(Comet、Chrome、Edge、Brave),相同的锚定操作会改用 DevTools 协议,而不是 UI Automation:获取 DOM 名称和aria-label,而非稀疏的树;使用可在重新渲染后继续有效的选择器;向渲染器发送可信输入事件;支持完整的修饰键组合;并模拟焦点,让会检查document.hasFocus()的网页仍能接受输入。整个过程不会影响你的前台操作。响应包含route: {browser, port, tab}和coords: viewport;没有端口的浏览器仍使用原有的 UI Automation 路径。设置GHOST_CDP_ROUTE=off可关闭此功能。只需使用--remote-debugging-port=9333启动一次 Comet 或 Chrome 即可启用此功能。 - 未找到时会列出备选项——“未找到元素”后会列出该窗口中名称最接近的元素,这样 Agent 就不必再调用一次
ghost_see,才能知道应用如何称呼该元素。 - 消除重复项的歧义——当多个元素具有相同的名称或角色(例如多个“关闭标签页”按钮)时,
index可选择第 n 个匹配项;响应会包含matches计数。 - 会自行审计——独立采样器会监视前台窗口和操作系统的最后输入时间;每当发生前台切换但没有真实硬件输入时,都会将其记录为合成操作,并注明当时正在执行的工具调用。
ghost_stats会报告统计结果,因此核心主张会持续得到验证,而非只验证一次。 - 读取,而非截图——
ghost_see mode=text会直接从辅助功能树中提取窗口或网页的可读文本,速度更快,且所需令牌数约为图像的 1/10。 - 延迟一目了然:每个响应都包含
ms;escalated: true表示查找操作需要经过一次网络 VLM 往返(本地层级:缓存 → UIA → OCR,均在设备本地运行)。 - 窗口绝不会消失:最小化的窗口仍会显示在
ghost_window list中(附带state),而op=focus会自动还原它们。被其他程序直接隐藏的窗口(不可见且未最小化)会在op=list include_hidden=true中显示为state: "hidden";op=state state=restore可将其恢复,而不会激活它。op=state也能访问 Ghost 自身隐藏桌面上的窗口,因此可以按名称关闭通过op=launch启动的应用。 - 停止始终有效:
ghost_stop到达时会立即抢占正在执行的调用(由专用 stdin 读取器处理);Ctrl+Alt+G 仍是操作系统级的终止开关。
后台模式(agent-harness / computer-use)
Agent harness(OpenClaw、Hermes/cua-driver 以及任何 MCP 客户端)会挂载一个 computer-use 工具,让大模型操作桌面。Ghost 就是这个工具——它可以不抢占你的焦点或移动你的光标,因此 Agent 可以操作应用,而你继续在另一个窗口中工作。
从 0.19 版本起,这是默认设置,且强制执行。进程级焦点策略
默认为 background,所有只能通过接管真实光标或前台窗口才能生效的基础操作都受此策略约束。不会静默回退:如果调用没有后台操作路径,就会返回错误,指出具体操作以及无需更改策略的路径(在隐藏桌面上启动应用,或通过 CDP 操作浏览器)。
从 0.22 版本起,该策略还会被锁定。如果 Agent 能更改默认设置,那默认设置就只是一句空话;在 0.22 之前,任何 Agent 都可以在后台操作被拒绝时立即调用 ghost_set_focus_policy foreground,而这正是人会注意到 Ghost 移动鼠标的时候。现在,这种调用也会被拒绝,并返回相应错误。决定权在操作者手中,而非 Agent:在 MCP 服务的环境中(即你编写的主机配置)设置
GHOST_FOCUS_LOCK=off,即可重新允许使用 prefer_background 和 foreground,还可以选择设置 GHOST_FOCUS_POLICY 来指定初始策略。ghost_focus_policy 会报告策略及其是否已锁定;服务启动时也会在日志中记录这两项。
// Only if you WANT an agent to be able to drive your real mouse and keyboard:
{ "mcpServers": { "ghost": {
"command": "ghost-mcp",
"env": { "GHOST_FOCUS_LOCK": "off", "GHOST_FOCUS_POLICY": "background" }
}}}
你需要了解并同意的事项
Ghost 有两个设置,用于决定 Agent 可以使用你的电脑到什么程度。安装软件包时会显示这两个复选框;直接运行二进制文件时,它们则是环境变量。服务会在启动时打印这两项设置的状态,因此主机日志始终能解答相关问题。
| 设置 | 默认值 | “开启”的含义 |
|---|---|---|
不让 Ghost 操作你的鼠标和键盘(GHOST_FOCUS_LOCK) | 开启 | Agent 无法提升焦点策略,因此只能在后台操作窗口,无法接管你的光标。只有当你希望 Agent 使用真实输入时才关闭此设置。 |
允许运行 Shell 命令(GHOST_SHELL) | 开启 | ghost_shell 会以你的账户权限运行程序,Agent 正是通过它来运行构建、git 和脚本——这也是大多数 Agent 使用 Ghost 的原因。它拥有对这台机器的完全访问权限。关闭此设置后,所有 Shell 调用都会被拒绝;窗口操作、屏幕读取和输入功能仍然可用。 |
Shell 默认开启是有意为之。它是这款工具的核心能力,不是什么额外奖励;悄悄发布一个缺少人们安装它所需功能的工具,远不如坦诚说明它能做什么。要是你不想授予这么多权限,复选框就在这里,而且拒绝行为也很明确。
锁定策略仍有一件事不受 Ghost 控制:应用可以激活自己的窗口,而当 Agent 通过无障碍 API 向页面输入或点击按钮时,Chromium 就会这样做。浏览器之外的任何东西都无法阻止这种调用。因此从 0.23 版本起,Ghost 会撤销这种激活。干扰审计机制同时也充当哨兵:任何窗口进入前台时,它都会立即收到通知(这是一个 Windows 事件,耗时约 1 毫秒),并立即将焦点切回,除非你主动选择了该窗口——例如点击它或按 Alt-Tab 切换到它。它能区分这些操作与输入,因为它监视的是真实输入,而非模拟输入。ghost_session_state 会报告这种情况发生的次数(foreground_handed_back)。
独立观察程序对其效果进行了测量;测试期间,有人一直在另一个窗口中打字(scripts/background-desktop-probe.mjs、scripts/interference-watch.ps1):
| 0.23 之前 | 现在 | |
|---|---|---|
| 输入被发送到错误窗口的按键次数 | 48 | 约 493 次中有 1 次,测试共 6 轮 |
| 发现焦点被抢占所需的时间 | 从未发现 | 约 1 毫秒 |
| 从 0.23.2 开始,前台窗口的监控改为使用事件,而不是轮询,因此窗口取得焦点后,大约 1 毫秒就会交还焦点。让一个人在整个过程中持续打字,连续进行了 6 次测试,输入到 Ghost 操控的窗口中的按键次数依次为 0、0、0、1、0 和 0。这并非保证——撤销激活永远无法做到保证——若要确保这一点,请让 Ghost 启动应用,这样就根本不会发生激活。 |
若要完全避免激活,而不是只让它短暂激活,请让 Ghost 启动应用:它启动的任何程序都会运行在独立输入队列的隐藏桌面上,根本无法取得你的前台焦点;它启动的浏览器则通过 CDP 操控。
// Drive an app while the human keeps working. No flag needed: background is the default.
ghost_window { "op": "launch", "exe": "notepad.exe" }
// -> { "surface": "hidden", "desktop": "auto", "window": { "title": "Notepad", ... }, "target": {...} }
ghost_act { "role": "edit", "action": "type", "text_input": "hello" } // targets the anchor
// -> { "verified": true, "focus_preserved": true, "cursor_preserved": true, "mode": "hidden" }
ghost_act { "window": "Comet", "name": "Post", "action": "click" } // a window on YOUR desktop
// -> { "verified": true, "focus_preserved": true, "cursor_preserved": true, "mode": "background" }
- 启动过程永不显示窗口。 在此仓库的 CI 机器上进行测量:无论采用哪种启动方式(普通、隐藏、最小化、从后台父进程启动、放置在 -32000,-32000),Edge 和 Chrome 启动时都会激活其第一个窗口。桌面上创建的窗口一旦存在,就会立即夺取键盘输入。因此,在后台策略下,Ghost 绝不会在用户桌面上创建窗口:
ghost_window op=launch、ghost_run启动步骤和ghost_browser_launch mode=windowed都会在带有独立输入队列的隐藏桌面上启动,并将窗口固定好,以便下一次ghost_see能显示它。一名独立观察者以 100 ms 的间隔监测整个启动-操作-关闭过程中的前台窗口,报告称前台窗口变化次数为零。 - 通过发送窗口消息实现真正的后台操作。 使用
BM_CLICK/WM_LBUTTONDOWN·UP(点击)、WM_SETTEXT(输入)和WM_MOUSEWHEEL(滚动)驱动真正的 Win32 控件。这些操作不会激活窗口。 - 无需屏幕即可操作无窗口控件。 UWP/WinUI/Chromium/Electron 控件没有窗口句柄。Ghost 使用 UI Automation 模式驱动它们——点击使用
Invoke,输入使用ValuePattern。Windows 允许时,Chromium 会在收到其中一些操作后激活自己的窗口(就在你使用过该浏览器之后):在 Edge 上测得,对网页输入框或地址栏调用SetValue、对页面按钮调用Invoke,以及发送点击消息,都会在约 90 ms 内将窗口置于前台。自 0.21.10 起,这种情况会立即撤销:Ghost 会监测每个面向用户桌面的操作前后的前台窗口;当目标窗口或其进程的任何窗口成为前台时,会在 30 到 50 ms 内将前台切回你原先使用的窗口,并通过focus_guard记录报告focus_preserved: false。发送的单个按键会到达页面中已聚焦的元素,且不会激活任何内容。 - Shell 子进程绝不会打开终端。 MCP 服务没有控制台,因此直接启动的 shell 也没有控制台,而它运行的每个控制台程序(node、python、cargo、cmd)都会打开一个全新的 Windows Terminal 窗口,并在运行期间占据前台。现在,
ghost_shell会创建带有不可见控制台的 shell;子进程会继承该控制台,不会显示任何窗口。测量结果:此前 7 秒内前台窗口变化了 9 次;之后为零,输出不变。 - 即使窗口被遮挡,也能验证。 通过读取控件值确认
type操作;通过前后PrintWindow图像差异确认click操作,即使窗口不可见也能渲染。每个响应都会包含verified、focus_preserved、cursor_preserved——Ghost 绝不会声称完成了无法确认的后台操作。 - 隐藏桌面使用相同的调用方式。 隐藏桌面上的窗口也通过相同的
window=<title>调用驱动;唯一的区别是target.surface: "hidden"。其中的 Chromium 和 Electron 窗口通过发送消息而非 UIA 操作驱动(在非合成桌面上,Chromium 只有等待约 2 秒的内部延迟后才会处理Invoke/SetValue;而发送的点击消息约 100 ms 即可生效);由于在该桌面上进行软件渲染需要几秒钟,因此会跳过像素验证——请通过ghost_tab_eval或ghost_see确认。真正的SendInput在隐藏桌面上仍然无效(Windows 会拒绝在非输入桌面上执行),因此,只响应真实硬件输入的应用需要在你自己的桌面上使用foreground策略。 - 如实处理单实例应用。 Windows 11 的记事本、Explorer 或使用默认配置文件的浏览器会将启动请求交给已运行的进程,而该进程的窗口位于你的桌面上。Ghost 无法阻止这种情况;它会报告
surface: "user"并给出警告,而不是声称应用处于隐藏状态。
支持 click、type、double_click、right_click、hover 和滚动;还支持用于单个按键的 ghost_key(Enter/Tab/F 键/字符,通过 WM_KEYDOWN/WM_CHAR)。background: true 标志为保持兼容性而接受;后台操作是默认行为。
剪贴板和编辑组合键也能在后台工作——Ctrl+C、Ctrl+X、Ctrl+V、
Ctrl+Z 和 Ctrl+A 会作为应用实际实现的语义消息发送
(WM_COPY、WM_CUT、WM_PASTE、WM_UNDO、EM_SETSEL),而不是发送应用在读取 GetKeyState 时会忽略的按键修饰状态。此集合以外的组合键会被拒绝,而非静默丢弃,因为发送按键消息无法设置这些应用读取的修饰键状态;请为它们使用 foreground 策略。
愿景:你的 Agent 就是模型
Ghost 是眼睛和双手,而不是大脑。当模型通过 MCP 驱动它时,模型负责观察:ghost_see 会将窗口作为带坐标的结构化元素提供给模型,ghost_see mode=text 会提供可读文本,而 ghost_screenshot 会在结构化信息不足时提供像素图像。Claude、GPT、Gemini 和强大的开放权重视觉模型都能直接读取这些内容。无需设置密钥,也无需进行任何配置;Ghost 也不必代替模型解读图像。
可选的内置视觉层适用于没有自有模型的调用方——CLI、HTTP API、意图文件——也适用于描述目标的便捷功能(ghost_find description="the blue Submit button"),当你希望 Ghost 代为解析目标,而不是自己读取元素树时。它支持通过 OpenAI 兼容端点提供服务的任何具备工具调用能力的视觉模型(OpenAI、Gemini、Groq、NVIDIA,或本地 vLLM / Ollama / LM Studio 服务),也支持 Anthropic。将 GHOST_VISION_BASE_URL 和 GHOST_VISION_MODEL 指向端点,并设置 GHOST_VISION_API_KEY(无密钥的本地服务只需设置基础 URL)。如果未配置该功能,描述目标会返回明确的错误并指出替代方案;其他工具不受影响。
紧急停止
随时按 Ctrl+Alt+G,即可立即停止所有正在执行的调用。只读查询(ghost_see、ghost_snapshot、ghost_window 列表)仍会响应,因此即使一切都已停止,你仍可检查发生了什么。
- 取消所有排队的操作
- 立即释放所有按住的修饰键(Shift、Ctrl、Alt)
- 不会遗留按键或修饰键状态
- 自 0.19 起支持会话范围。 停止信号是一个命名的内核事件
(
Local\ghost-emergency-stop-event),因此按下一次即可停止登录会话中的所有 Ghost 进程,而不仅仅是注册了该热键的进程。ghost_reset会恢复服务,同样对所有进程生效。
元素定位器
session.find(By::name("Save")).await? // by accessible name (substring)
session.find(By::role("edit")).await? // by UIA control type
session.find(By::role("button")).await?
在 CLI 中:ghost click --name "Save" 或 ghost click --role button。
意图——声明式流程
将可复现的多步流程编写为 JSON。FSM 执行器支持重试、超时,以及用于 abort_if / retry_if 的 JSONLogic 条件。
{
"ops": [
{ "op": "launch", "exe": "notepad.exe" },
{ "op": "focus_window", "name": "Notepad" },
{ "op": "type", "role": "edit", "text": "hello" },
{ "op": "hotkey", "mods": ["Ctrl"], "key": "s" }
]
}
使用 ghost run flow.json、POST /run 或通过 MCP 调用 ghost_execute_intent 运行。
架构
ghost-cli ghost-http ghost-mcp Rust SDK
\ | / | |
\ | / | |
+-----> ghost-session <-----|-----------+ ← safe Rust API
/ \ |
ghost-core ghost-linux | ← one cfg alias picks the engine
| | |
Win32 UIA, AT-SPI2 over | ← ghost-core: SendInput, DXGI/GDI
posted msgs D-Bus, XTEST | ← ghost-linux: portal / uinput
| | |
Windows OS Linux +-> ghost-browser ← CDP over the DevTools port,
engine-independent
支持性 crate:ghost-cache(UIA 快照 + 增量)、ghost-intent(FSM +
JSONLogic 执行器)、ghost-ground(定位器分层级联)、ghost-platform(按操作系统报告的能力矩阵)。
内置视觉层级(Set-of-Marks)
本节介绍上面的可选层级;通过 MCP 驱动 Ghost 的 Agent 可以从 ghost_see 获取相同信息,无需阅读本节。
当你通过自然语言描述定位元素(ghost_find description="the blue submit button",或者名称/文本查找未命中并升级到 VLM 时),Ghost 不会让模型猜测像素坐标——模型在这方面并不可靠(测试中,直接让模型“给出等号按钮的坐标”,结果偏离目标约 250px)。它采用 Set-of-Marks:在窗口检测到的元素上叠加编号徽标,发送带标记的屏幕截图及各个徽标对应的可访问名称标签,然后询问模型哪个编号匹配。编号会映射回该元素的精确矩形,因此返回的是实际位于元素上的坐标,而不是回归猜测值。
在计算器上进行的一次实时检查中,四种描述(“等号按钮”“加号按钮”“数字 7 按键”“乘号按钮”)都精确命中了对应按钮;相比之下,坐标回归会偏离约 250px。
如实说明适用范围:当检测到的元素带有可访问名称时(大多数应用如此),标签本身就能消除大部分歧义;对于没有标签的图标,模型则主要根据徽标的视觉位置/外观进行判断。
画布/没有无障碍树的应用。 当 UIA 树内容稀疏时(自定义绘制的 UI、远程桌面界面、游戏画布),Ghost 会用内置的 CPU 传统 CV 检测器(ghost_ground::cv_detect)补充 Set-of-Marks 候选项:边缘密度 → 连通组件 → 尺寸/宽高比筛选,无需 GPU,也无需下载模型。当无障碍树中没有可用信息时,它仍能提供真实的边界框供 VLM 选择。它比训练好的检测器更粗略——当 GPU 模型可用时,可选的 OmniParser ONNX 层级(--features yolo + GHOST_YOLO_MODEL)会接入相同的 Set-of-Marks 流程。要端到端完成 CV 标记 → VLM 选择,需要配置视觉密钥。
基准测试——衡量任务成功率,而不是“调用是否返回 ok”
bench/ 包含一个可复现的端到端基准测试:通过真实的 ghost-mcp 二进制程序执行 14 项 Windows 桌面任务,并通过重新观察实际结果为每项任务评分(计算器显示屏上真的显示 42 吗?输入的值真的存在吗?),绝不依赖工具调用的返回结果。
最近一次运行(见 bench/results/latest.md):
14/14 项任务通过(100%),每项任务耗时中位数约 2.7 秒(完整墙钟时间,包含应用启动)——涵盖感知、点击/键盘操作及验证、等待、窗口管理(列出/最小化/还原)、文本提取、消歧、流程串联、剪贴板往返、结构化错误、元素截图和数值断言。
它也证明了自己能够失败:--self-test 会运行有意设置错误的负向对照(例如,在显示屏显示 42 时断言其显示 99),并且只有当测试框架将每一项都判定为失败时才会通过——因此,上面的绿色结果是真实信号,而非走过场。
可在任何 Windows 10/11 计算机上复现:
cargo build --release -p ghost-mcp
python bench/run_bench.py # exit 0 iff every task passed
python bench/run_bench.py --self-test # exit 0 iff the harness caught every planted failure
可靠性浸泡测试
bench/soak.py 会执行大量“操作后验证”循环,并根据单元测试无法检测的指标进行判定:verified 返回 null/false 的频率、焦点丢失率、错误率、每项操作是否确实产生了实际效果(重新观察显示屏,绝不信任返回结果),以及延迟百分位数。
最近一次运行(160 次操作):通过——verify-null 0.0,焦点丢失 0.0,效果不匹配 0(100% 正确),p50 85ms / p95 117ms。见
bench/results/soak.md。
python bench/soak.py # exit 0 iff every reliability threshold holds
python bench/soak.py --cycles 250 # ~1000 acts
python bench/soak.py --self-test # exit 0 iff the harness flags a planted-wrong effect
我们刻意只公布 Ghost 自身测得的数据,绝不为其他工具编造数据列。bench/README.md 提供了与 Playwright-MCP / Computer Use / UI-TARS 进行比较的诚实方案,并解释为什么直接在相同测试套件中比较并不公平(Playwright 仅适用于浏览器;视觉 Agent 需要 API + VM)。
微基准测试
| 操作 | 测量值 |
|---|---|
| 区域捕获,GDI,任意尺寸 | ~16.5 ms |
| 区域捕获,DXGI,1600x900 | ~70-83 ms |
| BGRA→RGBA 转换,400x300 区域 | ~206 µs |
| JSONLogic eq/var | 32.2 ns |
| 意图编译(3op) | 1.49 µs |
端到端捕获测量(release,crates/ghost-core/tests/capture_latency_probe.rs)
修正了 v0.10.0 的假设:DXGI 获取耗时占主导,并且在大窗口上会出现性能断崖,因此在 v0.11.0 中,区域捕获(操作-验证、截图、Set-of-Marks)通过耗时稳定在约 16.5ms 的 GDI BitBlt 执行;全屏捕获仍使用 DXGI。运行转换微基准:cargo bench -p ghost-core --bench convert。较早的基线:
docs/benches/v030-baseline.md。
要求
- Windows 10 build 19041 或更高版本
- Linux,需安装
at-spi2-core并运行桌面会话(X11 或 Wayland); Wayland 输入和捕获还需安装xdg-desktop-portal-gnome - Chromium 系浏览器(Chrome、Comet、Edge 或 Brave),仅供
ghost_browser_*/ghost_tab_*工具使用;桌面操作无需浏览器 - Rust stable(仅在从源代码构建时需要)
许可证
MIT - Copyright 2026 Northtek
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。