
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
@vexralabs/zerodom
Advanced tools
DOM-to-Interaction-Graph middleware for AI web agents (TypeScript port)
The visual action layer for AI web agents — TypeScript edition.
See the page. Know exactly what to click.
TypeScript port of ZeroDOM's core engine — same interaction graph, same selector guarantees, for the Node/TS agent stack (LangChain.js, the Vercel AI SDK, Playwright for Node).
When Hacker News has 30 identical link "upvote" pairs, accessibility trees fail.
ZeroDOM assigns 1:1 deterministic handles, resolving [45] to the exact DOM
element while keeping CSS selectors entirely out of the context window.
npm install @vexralabs/zerodom
import { ZeroDOM } from "@vexralabs/zerodom";
const graph = await ZeroDOM.fromPage(page); // any Playwright Page
console.log(graph.toCompactText()); // what you send the model
const selectors = graph.selectorMap(); // { node_01: "#email-input", ... } — stays your side
import { parseHtml } from "@vexralabs/zerodom";
const graph = parseHtml(html, url); // parse HTML you already have, no browser needed
Real output, 11,882 tokens of Hacker News → 2,326:
PAGE: Hacker News | https://news.ycombinator.com
[01] a 'Show HN: ZeroDOM — agents only need to know what they can click'
[02] a 'dev'
[03] a '214 comments'
[03]; the CSS path
stays in selectorMap() on your side.:light(…). Pages with no shadow root pay nothing.+ appeared, - gone, ~ value changed — agents
stop re-reading entire pages.{ frames: true } to read same- and cross-origin frames.import { ZeroDOM, parseHtml } from "@vexralabs/zerodom";
// From a Playwright page (any object with content()/url()):
const graph = await ZeroDOM.fromPage(page);
// From raw HTML:
const graph = parseHtml(html, url);
// What to send the model:
graph.toCompactText(); // "[01] a 'Sign In'\n[02] input 'Email'..."
graph.toCompactText({ selectors: true }); // includes CSS selectors
graph.toCompactText({ hrefs: true }); // includes link destinations
// What stays on your side:
graph.selectorMap(); // { node_01: "#email-input", ... }
// Metadata:
graph.metadata; // { page_title, url, total_interactive_nodes, parsing_latency_ms, warning? }
linkedom gives a real querySelector/getElementById DOM — needed so every
generated selector can be self-verified, the same guarantee the Python version
makes against a real browser — at a fraction of jsdom's footprint. One caveat this
port works around: unlike jsdom or a real browser, linkedom's parser doesn't
normalize a bare HTML fragment into a full <html><body> document, so
ZeroDOMParser wraps non-document input itself before handing it to linkedom
(page.content() output is unaffected — it's always a full document already).
npm install
npm run build # tsc -> dist/
npm test # node's built-in test runner, against the built dist
Apache 2.0 — see LICENSE.
FAQs
DOM-to-Interaction-Graph middleware for AI web agents (TypeScript port)
The npm package @vexralabs/zerodom receives a total of 0 weekly downloads. As such, @vexralabs/zerodom popularity was classified as not popular.
We found that @vexralabs/zerodom demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.