内容
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/logo-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="assets/logo.svg">
<img alt="ScreenRead" src="assets/logo-dark.svg" width="400">
</picture>
</p>
<p align="center">
无需截图,直接读取屏幕内容。
</p>
ScreenRead 为 AI 代理提供访问 macOS 无障碍树的能力 — 与 VoiceOver 和其他屏幕阅读器使用的相同结构化数据。与其捕获像素并将它们输入视觉模型,不如让您的代理直接获取屏幕上每个 UI 元素的即时结构化文本描述。
**~100ms** 而不是 1-3 秒。**零幻觉** — 它读取操作系统知道的内容,而不是模型认为看到的内容。
## 为什么
大多数 AI 代理工具使用截图来“看到”屏幕:
1. 捕获 PNG(~200ms)
2. Base64 编码和传输(~500KB-2MB)
3. 视觉模型处理像素(昂贵,缓慢)
4. 模型描述它认为看到的内容(有时是错误的)
但是,约 90% 的代理任务是基于文本的:“错误信息是什么?”,“这个按钮是否可见?”,“页面标题是什么?”。截图是多余的。
ScreenRead 跳过了所有这些。它直接询问 macOS:“当前窗口中存在哪些 UI 元素?”,并立即返回结构化文本。
| | 截图 | ScreenRead |
|---|---|---|
| **速度** | 1-3 秒 | ~100ms |
| **令牌成本** | 高(视觉模型) | 低(文本) |
| **准确性** | 可能产生幻觉文本 | 精确(从操作系统读取) |
| **范围** | 仅限网页(Playwright)或全屏 | 任意 macOS 应用程序 |
| **适用场景** | 视觉检查(布局,颜色) | 内容验证,UI 状态 |
对于 90% 的与内容和结构相关的任务,请使用 ScreenRead。对于需要像素的 10% 任务,请保留截图。
## 安装
### 从源代码构建
```bash
git clone https://github.com/Bambushu/screenread.git
cd screenread
swift build -c release
cp .build/release/screenread ~/.local/bin/
cp .build/release/screenread-mcp ~/.local/bin/
```
### 要求
- macOS 13+(Ventura 或更高版本)
- 无障碍权限(系统设置 > 隐私和安全 > 无障碍)
## 用法
### 命令行界面
```bash
# 读取当前最前面的应用程序
screenread
# 读取特定应用程序
screenread --app Safari
# 模糊匹配窗口标题
screenread --window "inbox"
# 仅文本(无结构)
screenread --app Warp --text-only
# 浅读取(深度 2)
screenread --app Finder --shallow
# 完整文本,无截断
screenread --app Terminal --full
# JSON 输出
screenread --app Safari --json
# 在所有打开的窗口中搜索文本
screenread --find "error"
screenread --find "Submit"
# 列出所有打开的窗口
screenread --list
# 按角色过滤
screenread --app Safari --role AXButton,AXLink
# 排除角色
screenread --app Safari --ignore AXGroup,AXScrollArea
# 列出具有点击坐标的交互式元素
screenread --clickable --app Safari
screenread --clickable --app Finder --json
# 监视 UI 更改(每 2 秒轮询,Ctrl+C 停止)
screenread --watch --app Safari
screenread --watch --app Safari --interval 5
# 流式传输 JSONL(每个节点一个 JSON 对象,每行一个)
screenread --stream --app Safari
screenread --stream --app Safari | jq 'select(.role == "AXButton")'
```
### MCP 服务器
将以下内容添加到您的 MCP 配置中:
**Claude Code**(项目范围内的 `.mcp.json` 文件,在您的项目根目录中):
```json
{
"mcpServers": {
"screenread": {
"command": "screenread-mcp"
}
}
}
```
**Claude Desktop**(`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"screenread": {
"command": "/path/to/screenread-mcp"
}
}
}
```
这为任何 MCP 兼容的客户端公开了五个工具:
#### `screenread_snapshot`
读取特定应用程序或窗口的可访问性树。没有参数时,读取当前最前面的(活动)应用程序。
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `app` | 字符串 | 应用程序名称(例如 `"Safari"`) |
| `window` | 字符串 | 窗口标题的模糊匹配 |
| `pid` | 整数 | 按进程 ID 定位 |
| `depth` | 整数 | 最大树深度(默认值:5)。使用 0 表示无限制 - 可能在大型应用程序上很慢。 |
| `textOnly` | 布尔值 | 仅文本,不带结构 |
| `roles` | 字符串 | 要包含的 AX 角色的逗号分隔列表(例如 `"AXButton,AXLink"`) |
| `ignore` | 字符串 | 要排除的 AX 角色的逗号分隔列表(例如 `"AXGroup,AXScrollArea"`) |
#### `screenread_list`
列出所有打开的窗口。以 `AppName [PID] — Window Title` 格式返回一行每窗口的信息。无参数。
#### `screenread_find_text`
在所有打开的窗口中搜索可见文本。纯字符串匹配(无正则表达式)。
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `query` | 字符串 | 要搜索的纯文本子字符串(必填) |
| `caseSensitive` | 布尔值 | 区分大小写(默认值:false) |
结果限制为 100 个匹配项。对于更针对性的结果,请使用 `screenread_snapshot` 和特定应用程序。
#### `screenread_clickable`
列出具有点击坐标的交互式元素(按钮、链接、文本字段)。
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `app` | 字符串 | 应用程序名称(例如 `"Safari"`) |
| `window` | 字符串 | 窗口标题的模糊匹配 |
| `pid` | 整数 | 按进程 ID 定位 |
| `roles` | 字符串 | 重写默认交互式角色(例如 `"AXButton,AXLink"`) |
返回一个表格,包含角色、标签、中心 x/y 坐标和状态(启用/禁用/聚焦/选中)。
#### `screenread_watch`
监视应用程序的 UI 更改一段时间。
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `app` | 字符串 | 应用程序名称(例如 `"Safari"`) |
| `window` | 字符串 | 窗口标题的模糊匹配 |
| `pid` | 整数 | 按进程 ID 定位 |
| `duration` | 整数 | 监视持续时间(秒)(默认值:10,最大值:60) |
| `interval` | 整数 | 轮询间隔(秒)(默认值:2,最小值:1) |
| `textOnly` | 布尔值 | 仅比较文本内容(默认值:false) |
按给定的间隔轮询可访问性树,并报告添加、删除和值/状态更改。
## 架构
```
screenread/
├── Sources/
│ ├── ScreenReadCore/ # 共享库
│ │ ├── AXHelpers.swift # 共享 AX 属性访问器
│ │ ├── AXTreeWalker.swift # 递归可访问性树遍历 + 流式回调
│ │ ├── Formatter.swift # 文本树、仅文本、JSON、可点击输出
│ │ ├── MCPProtocol.swift # JSON-RPC 类型、工具调度、参数验证
│ │ ├── StreamFormatter.swift # JSONL 单节点编码器
│ │ ├── TargetResolver.swift # 应用程序/窗口/PID 解析,模糊匹配
│ │ ├── TreeDiffer.swift # 比较两个树快照的更改
│ │ └── Types.swift # AXNode、WalkResult、WindowInfo、错误
│ ├── screenread/ # 命令行界面(使用 ArgumentParser)
│ └── screenread-mcp/ # MCP 服务器(内容长度帧标准输入输出)
└── Tests/
└── ScreenReadCoreTests/ # 4 个套件共 27 个测试
```
核心库(`ScreenReadCore`)完成所有工作。命令行界面和 MCP 服务器都是围绕它的薄包装。
## 平台
仅限 macOS。ScreenRead 使用苹果的 `AXUIElement` 无障碍 API,在其他平台上没有等效的 API。Linux 需要 AT-SPI,Windows 需要 UI 自动化 — 根本不同的 API。
## 许可证
MIT