{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}

Inspecting Hermes Desktop Dom

经 CDP 读取实时 Hermes 桌面 DOM/CSS。

Skill 元数据

来源内置(默认安装)
路径skills/software-development/inspecting-hermes-desktop-dom
版本1.0.0
作者Hermes Agent
许可证MIT
平台linux, macos, windows
标签desktop, electron, cdp, dom, ui-verification, self-inspection
相关 skillnode-inspect-debugger、systematic-debugging、dogfood

参考:完整 SKILL.md

INFO

以下是 Hermes 在触发该 skill 时加载的完整 skill 定义。这是 agent 在 skill 激活时所看到的指令内容。

检视实时 Hermes 桌面 DOM

概览

当你在开发 apps/desktop、且用户正运行同一应用(hgui / npm run dev)时,你可以读取他们正看着的窗口的实时渲染 DOM——计算样式、几何、哪条 CSS 规则实际胜出、控制台输出——而不是从 .tsx 推断然后出错。

dev-server 运行会自动在 127.0.0.1:9222 打开一个 Chrome DevTools Protocol 端口。渲染器是 Chromium 页面,因此 DevTools 能读的一切,脚本都能读。

这不替代亲眼查看。 CDP 回答事实性问题("计算 padding 是多少"、"这个元素渲染了吗"、"哪个选择器匹配")。它不能告诉你结果好不好看。色彩平衡、间距手感、"这丑不丑"仍需用户的眼睛或截图。用 CDP 回答事实;把美学交给用户。

何时使用

  • 验证 UI 变更在运行中的应用里确实生效
  • "为什么这个元素还是 X?"——在改任何东西前找出胜出规则
  • 为你即将改的组件定位稳定选择器
  • 在真实节点上检查设计 token 的计算值
  • 读用户提到但复制不出来的渲染器控制台错误

不要用于: 性能 profiling 或堆工作(node-inspect-debugger、debugging-hermes-desktop),或真实问题是"这看着对不对"的任何事。

端口

任何 dev-server 运行都在 127.0.0.1:9222 打开。恰好两种情况关闭(apps/desktop/electron/dev-cdp.ts):

  • 打包构建——总是关闭,无环境值可覆盖;
  • 无 HERMES_DESKTOP_DEV_SERVER——针对 dist/ 的未打包 electron . 是冒烟测试打包应用的方式,因此它表现得像打包应用。

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 感知的 eval:

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、线程视口、助手消息、轮次对、profile 侧栏)。优先用它们,而非自造 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
  })()
})

若节点自身不带类,该值是继承的——横扫调用点修不好它,你需要祖先规则。插件样式表(如 @tailwindcss/typography 的 prose a { font-weight: 500 }) routinely 压过工具类;在共享类上覆盖,而非每处用法。

你自己的隔离实例

当无端口、或你不得打扰用户窗口时:

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 做同样的事,若你还想要 perf harness。

常见陷阱

  • 绝不要为"释放"任何东西而杀掉用户的 dev server 或应用。 服务中途杀掉会炸毁 Chromium 的 socket 池,导致的 ERR_NETWORK_CHANGED 会被怪到你刚改的东西上。
  • 一次性 HERMES_HOME 没有后端。 应用会为 hermes:api 记 ECONNREFUSED 并可能自行退出。渲染器仍挂载、DOM 仍可读——及时读,别把自退的探针误认为坏端口。Chromium 绑定时记 DevTools listening on ws://127.0.0.1:<port>/…;那行就是端口打开的证明。
  • 轮询,而非探一次。 刚启动的应用需要一两秒端口才应答。
  • 绝不要 dump 整个 DOM。 桌面渲染数百节点,outerHTML 会淹没你的上下文。在求值表达式内投影成小 JSON 对象。
  • 给 CDP.connect 传 match。 不传,你可能附到宠物浮层、快捷输入窗或 devtools 目标,而非主窗口。
  • cdp.eval 返回值;裸 Runtime.evaluate 会双层嵌套(.result.result.value)。用包装器。
  • 本仓库 vite dev 下 import.meta.env.DEV 为 true。 apps/desktop/scripts/profile-typing-lag.md 中相反说法已过时。