Install
$ agentstack add skill-atlasomnia-hermes-custom-pack-inspecting-hermes-desktop-dom Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Dangerous shell/eval execution.
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ● Dynamic code execution Used
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Inspecting 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 .against
dist/ 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 /…` 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
`outerHTML` will bury your context. Project down to a small JSON object inside
the evaluated expression.
- **Pass `match` to `CDP.connect`.** Without it you may attach to the pet
overlay, quick-entry window, or a devtools target instead of the main window.
- **`cdp.eval` returns the value; raw `Runtime.evaluate` double-nests it**
(`.result.result.value`). Use the wrapper.
- **`import.meta.env.DEV` is `true` under `vite dev`** in this repo. The note in
`apps/desktop/scripts/profile-typing-lag.md` claiming otherwise is stale.
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [AtlasOmnia](https://github.com/AtlasOmnia)
- **Source:** [AtlasOmnia/hermes-custom-pack](https://github.com/AtlasOmnia/hermes-custom-pack)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.