uictl
Linux 桌面 UI 自动化控制 CLI,基于 dogtail / AT-SPI 无障碍树。搜索窗口、浏览控件树、点击控件、输入文本、等待/断言,一条命令搞定。
uictl apps # 列出所有应用
uictl windows gnome-text-editor # 列出应用的窗口
uictl tree gnome-text-editor --depth 4 # 打印窗口控件树
uictl find gnome-text-editor "role=button"
uictl inspect gnome-text-editor "name=保存"
uictl click gnome-text-editor "role=button[name=保存]"
uictl type gnome-text-editor "role=text" --text "hello"
uictl wait gnome-text-editor "name=保存" --visible
uictl expect gnome-text-editor "name=保存" --visible --sensitive
安装
# 轻量命令(不碰无障碍树):直接跑
uvx uictl --version
uvx uictl install-skill # 注入 agent 技能到 ~/.agents/skills/uictl/
# 完整 UI 命令:用系统 Python 跑(gi 无 PyPI wheel,只能来自系统包;
# uictl 在 gi 缺失时自动注入系统 site-packages 到 sys.path,无需 PYTHONPATH)
uvx --python /usr/bin/python3 uictl apps
# 或持久安装
uv tool install uictl --python /usr/bin/python3
依赖系统包(AT-SPI typelib,无法 pip 安装):
gir1.2-atspi-2.0 python3-gi python3-pyatspi
(Wayland 下如需输入注入:gnome-ponytail-daemon,GNOME 46+ 已封禁注入,见下)。
本地开发(本仓库):
cd ~/projects/uictl
uv venv .venv --python $(which python3) --system-site-packages
uv pip install -e .
子命令
| 子命令 | 作用 | Wayland 可用 |
|---|---|---|
apps |
列出应用(--json) |
✅ |
windows [APP] |
列出窗口 | ✅ |
tree APP |
控件树(--depth --path --json) |
✅ |
find APP SEL |
搜索控件,输出 path(--scope --json) |
✅ |
inspect APP SEL |
控件详情(状态/文本/坐标/Action 列表) | ✅ |
click APP SEL |
点击:AT-SPI Action 接口优先,无 Action 时回退注入(--action NAME) |
✅ Action / ⚠️ 注入 |
dblclick APP SEL |
双击 | ⚠️ 需注入 |
hover APP SEL |
悬停 | ⚠️ 需注入 |
type APP SEL --text X |
输入:默认 fill(EditableText 直接赋值)✅;--keystrokes 逐键 ⚠️ 需注入 |
✅ / ⚠️ |
key COMBO |
组合键,如 "<Control>a" |
⚠️ 需注入 |
wait APP SEL [--visible] [--sensitive] [--focused] [--gone] |
轮询等待条件成立 | ✅ |
expect APP SEL [--text S] [--role R] ... |
断言,失败 exit 1 | ✅ |
install-skill [--dir DIR] [--force] |
注入 agent 技能到 ~/.agents/skills/uictl/ |
✅ |
⚠️ 需注入 = 需要原始输入注入(X11 会话原生支持;Wayland 需 RemoteDesktop 后端)。在只读环境(GNOME 46+ Wayland)下这些命令会报清晰错误而不是 抛 traceback。
选择器语法(Playwright 风格)
role=button[name=保存] # 引擎 + [属性...]
name=保存 # 单属性
text=请输入 # 匹配 node.text 子串
path=0:2:3 # 从应用根开始的索引路径(find 输出的 path 可直接用)
保存 # 裸字符串 = name
支持属性:name role(role_name) desc(description) label id(accessible_id) text。
值含空格需加引号:name="保存 文档"。
strict 模式:inspect/click 等要求唯一匹配,命中多个会报错并列出全部匹配,
用 --index N 指定;--scope 限定在父节点内搜索;--win 指定多窗口应用的窗口。
平台限制说明(为什么有的命令报错)
- 读(apps/windows/tree/find/inspect/wait/expect)走 AT-SPI 总线,Wayland 全可用。
- 控(click/type-fill)走 AT-SPI 接口(Action/EditableText/Component), 应用自己实现,Wayland 全可用——这是 GNOME 给无障碍"控制"设计的官方通道。
- 原始输入注入(key/hover/dblclick/type-keystrokes)在 X11 走 XTEST;
在 Wayland 被设计成受控特权(需 RemoteDesktop portal 授权)。
另外 GNOME 46+ 移除了
org.gnome.Shell.Introspect.GetWindows, gnome-ponytail-daemon 依赖它做坐标换算,因此 dogtail 的注入在 GNOME 46+ Wayland 上整体不可用 → uictl 会报清晰错误。
退出码
0成功1未找到 / 断言失败 / strict 多匹配 / 平台不支持130用户中断
Roadmap
screenshot(GNOME 50 需走 XDG Desktop Portal,core.take_screenshot已预留)- RemoteDesktop portal 输入后端(Wayland 注入的官方通道,需用户授权)
发布到 PyPI
cd ~/projects/uictl
uv build # 构建 sdist + wheel(产出 dist/)
uv publish # 需要 PyPI API token 凭据
凭据(三选一):
~/.pypirc([pypi] username=__token__ password=pypi-xxx)——本机已配置- 环境变量:
UV_PUBLISH_TOKEN=pypi-xxx uv publish - 交互输入:
uv publish --username __token__(会提示输入密码)
⚠️ 版本一旦发布不可覆盖,改代码后记得 bump
pyproject.toml的version。 正式发布前可先试水 Test PyPI:uv publish --publish-url https://test.pypi.org/legacy/ --check-url https://test.pypi.org/simple/(需要 test.pypi.org 的 token,写到~/.pypirc的[testpypi]段)。
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uictl-0.1.1.tar.gz.
File metadata
- Download URL: uictl-0.1.1.tar.gz
- Upload date:
- Size: 33.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.6.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc0e714157596df400aa9475ddc32254ec2d7c475df921bbf37e93de7b154e51
|
|
| MD5 |
5b8c6860759d709781f0d43d8e29549b
|
|
| BLAKE2b-256 |
21065cdb8875855a91ac286848805eca528c84e15d8d3c461bddafa3f7be63ce
|
File details
Details for the file uictl-0.1.1-py3-none-any.whl.
File metadata
- Download URL: uictl-0.1.1-py3-none-any.whl
- Upload date:
- Size: 36.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.6.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64ad7ec57ec17b07ca92fc82eb31b984535b0dbcbe24e3c3dcdcaec6f0abefd6
|
|
| MD5 |
9c95ddf0a5e272b52349afe60eee531c
|
|
| BLAKE2b-256 |
9861302528df5abc9dd93385734967d494e68c7650f138c6d3bee4a2a90c964a
|