
Inspecting Hermes Desktop DOM
FreeRead live DOM and CSS of your Hermes desktop app.
Free · Opens the source repo
What Inspecting Hermes Desktop DOM does
Inspecting the Hermes Desktop DOM skill allows developers to interact with the live rendered DOM of their applications running in the Hermes environment. By leveraging the Chrome DevTools Protocol (CDP), users can access real-time information about the DOM, including computed styles, geometry, and the specific CSS rules that apply to elements. This capability is particularly useful during the development of desktop applications, as it provides immediate feedback on changes made to the UI without relying on potentially inaccurate assumptions from the source code.
The skill is designed for developers working with the Hermes desktop application framework. It enables them to verify UI changes, troubleshoot style issues, and gather data about the rendered state of components. For instance, if a developer is unsure why a certain style isn't applying, they can use this skill to determine which CSS rule is taking precedence, thus streamlining the debugging process. Additionally, it allows for checking the computed values of design tokens directly on the live application, ensuring that what is coded matches what is rendered.
This skill is not a substitute for visual inspection; it focuses on providing factual answers about the DOM and styles. Developers still need to visually assess the aesthetics of the UI, as the skill cannot evaluate subjective aspects such as color balance or overall design appeal. Instead, it serves as a precise tool for answering specific questions about the DOM, helping to eliminate guesswork and improve development efficiency.
To use the skill, developers must ensure that their application is running with the appropriate CDP port open. The skill provides guidelines for setting up an isolated instance if necessary, ensuring that the developer's work does not interfere with the user's session. Overall, this skill is an essential tool for any developer working on Hermes desktop applications who needs accurate, real-time insights into their UI's behavior.
When to use it
Use this skill when you need to verify UI changes, troubleshoot CSS issues, or gather specific data about the live DOM.
When not to use it
Avoid using this skill for performance profiling or when the primary concern is aesthetic evaluation of the UI.
What you can build with it
Verify UI Changes
Use this skill to confirm that a recent UI change is reflected correctly in the running application.
Troubleshoot CSS Issues
Quickly identify which CSS rule is taking precedence when styles are not applying as expected.
Gather Live DOM Data
Access real-time information about the rendered state of components to ensure accurate development.
How to install Inspecting Hermes Desktop DOM
View source1. Install with the skills CLI
npx skills add nousresearch/hermes-agent/inspecting-hermes-desktop-dom --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by nousresearchInspecting the live Hermes desktop DOM
Overview
When you are developing apps/desktop and the user is running that same app
(hgui / npm run dev), you can read the live rendered DOM of the window
they are looking at — computed styles, geometry, which CSS rule actually won,
console output — instead of inferring it from .tsx and being wrong.
Dev-server runs open a Chrome DevTools Protocol port on 127.0.0.1:9222
automatically. The renderer is a Chromium page, so everything DevTools can read,
a script can read.
This does not replace looking at it. CDP answers factual questions ("what is the computed padding", "did this element render", "which selector matches"). It cannot tell you whether the result looks good. Colour balance, spacing feel, and "is this ugly" still need the user's eyes or a screenshot. Answer facts with CDP; hand aesthetics to the user.
When to Use
- Verifying a UI change actually took effect in the running app
- "Why is this element still X?" — find the winning rule before editing anything
- Locating a stable selector for a component you're about to change
- Checking a design token's computed value on a real node
- Reading renderer console errors the user mentions but can't copy out
Don't use for: perf profiling or heap work (node-inspect-debugger,
debugging-hermes-desktop), or anything where the real question is "does this
look right".
The port
Open on 127.0.0.1:9222 for any dev-server run. Closed in exactly two cases
(apps/desktop/electron/dev-cdp.ts):
- packaged builds — always, and no environment value overrides it;
- no
HERMES_DESKTOP_DEV_SERVER— an unpackagedelectron .againstdist/is how the packaged app gets smoke tested, so it behaves like one.
HERMES_DESKTOP_CDP_PORT moves the port (=9333) or disables it (=off).
Check before doing anything else:
curl -s --max-time 3 http://127.0.0.1:${HERMES_DESKTOP_CDP_PORT:-9222}/json/version
Empty → no port. Do not guess another port silently.
Never relaunch the user's app to get a port. That destroys their session and their state. Launch your own isolated instance instead (below).
Reading the DOM
apps/desktop/scripts/eval.mjs is the one-liner:
cd apps/desktop
node scripts/eval.mjs "document.querySelectorAll('[data-slot]').length"
For multi-step work use the shared client — it has target discovery and promise-aware 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()
SELECTORS in scripts/perf/lib/cdp.mjs holds the stable data-slot hooks
(composer, thread viewport, assistant message, turn pair, profile rail). Prefer
them over inventing a querySelector — they are updated as a unit when
components move.
The question this is best at: which rule won?
Editing every call site because a style "isn't applying" is the classic waste. Read the real node first:
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
})()
})
If the node carries no class of its own, the value is inherited — sweeping
call sites will not fix it, and you need the ancestor rule. A plugin stylesheet
(e.g. @tailwindcss/typography's prose a { font-weight: 500 }) routinely beats
a utility class; override on the shared class, not at each usage.
Your own isolated instance
When there is no port, or you must not disturb the user's window:
cd apps/desktop
HERMES_HOME=/tmp/cdp-probe-home \
HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 \
HERMES_DESKTOP_CDP_PORT=9333 \
npx electron . --user-data-dir=/tmp/cdp-probe-userdata
The separate --user-data-dir dodges Electron's single-instance lock, so it
cannot collide with a running hgui; the separate HERMES_HOME keeps it away
from real sessions. Pick a port other than 9222 for the same reason. Run it in
the background and kill it when done.
npm run perf:serve does the same with a temp HERMES_HOME baked in, if you
also want the perf harness.
Pitfalls
- Never kill the user's dev server or app to "free" anything. A mid-serve
kill nukes Chromium's socket pool, and the resulting
ERR_NETWORK_CHANGEDgets blamed on whatever you just changed. - A throwaway
HERMES_HOMEhas no backend. The app logsECONNREFUSEDforhermes:apiand may exit on its own. The renderer still mounts and the DOM is readable — read promptly, and don't mistake a self-exited probe for a broken port. Chromium logsDevTools listening on ws://127.0.0.1:<port>/…when it binds; that line is the proof the port opened. - Poll, don't probe once. A just-launched app needs a second or two before the port answers.
- Never dump the whole DOM. The desktop renders hundreds of nodes and
outerHTMLwill bury your context. Project down to a small JSON object inside the evaluated expression. - Pass
matchtoCDP.connect. Without it you may attach to the pet overlay, quick-entry window, or a devtools target instead of the main window. cdp.evalreturns the value; rawRuntime.evaluatedouble-nests it (.result.result.value). Use the wrapper.import.meta.env.DEVistrueundervite devin this repo. The note inapps/desktop/scripts/profile-typing-lag.mdclaiming otherwise is stale.
Frequently asked questions about Inspecting Hermes Desktop DOM
Similar skills
Agent Host Debug Logs
Analyze Agent Host debug logs for deeper insights.
Code OSS Dev - Launch + Debug
Launch and debug Code OSS with isolated profiles.
Phoenix CLI
Debug LLM applications with structured analysis tools.
Power Automate Debugging
Diagnose and fix Power Automate flow errors effectively.
Arize Trace
Inspect and export traces for LLM applications.
Runtime Behavior Probe
Investigate real runtime behavior with precision.
