关于 inspecting-hermes-desktop-dom
用于开发 Hermes 桌面应用的技能,通过 Chrome DevTools Protocol 检查运行中的 DOM。开发者可查看渲染元素、计算样式、几何信息和控制台输出,而非仅依据源文件推断。
主要功能
- 01读取实时渲染器 DOM
- 02检查计算样式和几何信息
- 03定位匹配及生效的 CSS 规则
- 04读取渲染器控制台输出
- 05使用稳定的 data-slot 选择器
适用场景
- 01验证运行中应用的界面改动
- 02查明样式未生效的原因
- 03编辑组件前定位选择器
- 04检查用户反馈的渲染器错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nousresearch/ hermes-agent --skill inspecting-hermes-desktop-dom安装后在 Claude Code 中输入/inspecting-hermes-desktop-dom确认已加载。
详细介绍
检查实时 Hermes 桌面 DOM
概述
开发 apps/desktop 时,如果用户正在运行同一个应用
(hgui / npm run dev),你可以读取他们正在查看的窗口中的实时渲染 DOM,
包括计算后的样式、几何信息、实际生效的 CSS 规则、控制台输出,而不必根据 .tsx
推测后得出错误结论。
开发服务器运行时会自动在 127.0.0.1:9222 上开放 Chrome DevTools Protocol 端口。
渲染器是 Chromium 页面,因此 DevTools 能读取的内容,脚本也都能读取。
这不能替代亲自查看。 CDP 可以回答事实问题(“计算后的内边距是多少”、 “这个元素有没有渲染”、“哪个选择器匹配”),但无法判断结果看起来是否美观。 色彩平衡、间距观感,以及“这是不是很丑”,仍需用户亲自查看或查看截图。用 CDP 回答事实问题;审美判断交给用户。
适用场景
- 验证 UI 变更是否确实在运行中的应用里生效
- “为什么这个元素仍然是 X?”——修改前先找出实际生效的规则
- 为即将修改的组件找到稳定的选择器
- 检查真实节点上的设计令牌计算值
- 查看用户提到但无法复制出来的渲染器控制台错误
不要用于: 性能分析或堆内存相关工作(node-inspect-debugger、
debugging-hermes-desktop),或任何真正的问题是“这样看起来对吗”的场景。
端口
任何开发服务器运行时,都会在 127.0.0.1:9222 上开放端口。只有以下两种情况会关闭
端口(apps/desktop/electron/dev-cdp.ts):
- 打包构建——始终关闭,且任何环境变量值都无法覆盖此设置;
- 未设置
HERMES_DESKTOP_DEV_SERVER——使用未打包的electron .加载dist/来对打包应用进行冒烟测试,因此其行为与打包应用一致。
HERMES_DESKTOP_CDP_PORT 可以更改端口(=9333),也可以禁用端口(=off)。
开始其他操作前先检查:
curl -s --max-time 3 http://127.0.0.1:${HERMES_DESKTOP_CDP_PORT:-9222}/json/version
无输出 → 没有端口。不要擅自猜测其他端口。
绝不要为了获取端口而重启用户的应用。 这会破坏他们的会话和状态。 请改为启动你自己的隔离实例(见下文)。
读取 DOM
apps/desktop/scripts/eval.mjs 是用于单行操作的脚本:
cd apps/desktop
node scripts/eval.mjs "document.querySelectorAll('[data-slot]').length"
对于多步骤操作,请使用共享客户端——它支持目标发现和可处理 Promise 的求值:
import { CDP, SELECTORS } from './scripts/perf/lib/cdp.mjs'
const cdp = await CDP.connect({ port: 9222, match: '5174' })
const out = await cdp.eval(`JSON.stringify({
radius: getComputedStyle(document.documentElement).getPropertyValue('--radius-scalar').trim(),
composer: !!document.querySelector('[data-slot="composer-rich-input"]')
})`)
cdp.close()
scripts/perf/lib/cdp.mjs 中的 SELECTORS 保存了稳定的 data-slot 钩子
(composer、thread viewport、assistant message、turn pair、profile rail)。优先使用它们,
不要自行编造 querySelector——组件移动时,这些钩子会作为一个整体同步更新。
最适合用来回答的问题:哪条规则生效了?
因为样式“没有生效”就修改所有调用位置,是最常见的浪费。先读取真实节点:
const el = document.querySelector('[data-slot="aui_assistant-message-root"] a')
JSON.stringify({
ownClasses: el.className,
weight: getComputedStyle(el).fontWeight,
parents: (() => {
const out = []
let n = el
while ((n = n.parentElement) && out.length < 6) out.push(n.className)
return out
})()
})
如果节点本身没有 class 值,说明该值是继承的——逐个检查调用位置无法修复问题,
你需要检查祖先节点规则。插件样式表(例如 @tailwindcss/typography 中的
prose a { font-weight: 500 })通常会覆盖工具类;应在共享类上覆盖,而不是在每个使用位置分别覆盖。
你自己的隔离实例
没有端口,或必须避免干扰用户窗口时:
cd apps/desktop
HERMES_HOME=$HOME/.hermes/cache/scratch/cdp-probe-home \
HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 \
HERMES_DESKTOP_CDP_PORT=9333 \
npx electron . --user-data-dir=$HOME/.hermes/cache/scratch/cdp-probe-userdata
单独的 --user-data-dir 可以绕过 Electron 的单实例锁,因此不会与正在运行的
hgui 冲突;单独的 HERMES_HOME 则可使其与真实会话隔离。出于同样原因,请选择
9222 以外的端口。在后台运行,完成后将其终止。
如果还需要性能测试框架,npm run perf:serve 也会执行相同操作,并预先设置临时的 HERMES_HOME。
注意事项
- 绝不要为了“腾出”资源而终止用户的开发服务器或应用。 在服务运行期间将其终止会清空 Chromium 的套接字池,随后出现的
ERR_NETWORK_CHANGED会被归咎于你刚刚做的更改。 - 临时的
HERMES_HOME没有后端。 应用会针对hermes:api记录ECONNREFUSED,并可能自行退出。渲染器仍会挂载,DOM 也可读取——请尽快读取,不要把自行退出的探测应用误认为端口故障。Chromium 绑定端口时会记录DevTools listening on ws://127.0.0.1:<port>/…;这行日志证明端口已打开。 - 轮询,不要只探测一次。 应用刚启动时,需要一两秒端口才会响应。
- 绝不要转储整个 DOM。 桌面应用会渲染数百个节点,
outerHTML会淹没上下文。在求值表达式中将结果精简为一个小型 JSON 对象。 - 将
match传给CDP.connect。 不传的话,你可能会连接到宠物浮层、快速输入窗口或 devtools 目标,而不是主窗口。 cdp.eval会返回值;原始的Runtime.evaluate会多嵌套一层(.result.result.value)。请使用封装器。- 在此仓库中,
vite dev下的import.meta.env.DEV为true。apps/desktop/scripts/profile-typing-lag.md中声称并非如此的说明已过时。