Browser Testing with Chrome DevTools
addyosmani/agent-skills
Connects an agent to a real Chrome instance through the Chrome DevTools MCP server, so it can inspect the DOM, read console errors and profile performance directly.
Verify UI/layout/styling changes are correct by computing occlusion, clipping, and alignment from the browser's resolved paint order via the chrome-devtools MCP evaluatescript tool — instead of…
$ npx skills add nubjs/nub --skill visual-review -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install nubjs/nub visual-review --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/nubjs/nub.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/visual-review .claude/skills/visual-review && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "visual-review" agent skill from https://github.com/nubjs/nub/tree/main/.claude/skills/visual-review into .claude/skills/visual-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "visual-review", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/nubjs/nub/tree/main/.claude/skills/visual-reviewType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add nubjs/nub --skill visual-review -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install nubjs/nub visual-review --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nubjs/nub.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/visual-review .agents/skills/visual-review && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "visual-review" agent skill from https://github.com/nubjs/nub/tree/main/.claude/skills/visual-review into .agents/skills/visual-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "visual-review", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add nubjs/nub --skill visual-review -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install nubjs/nub visual-review --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nubjs/nub.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/visual-review .cursor/skills/visual-review && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "visual-review" agent skill from https://github.com/nubjs/nub/tree/main/.claude/skills/visual-review into .cursor/skills/visual-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "visual-review", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/nubjs/nub.git --path .claude/skills/visual-review--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add nubjs/nub --skill visual-review -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install nubjs/nub visual-review --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nubjs/nub.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/visual-review .gemini/skills/visual-review && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "visual-review" agent skill from https://github.com/nubjs/nub/tree/main/.claude/skills/visual-review into .gemini/skills/visual-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "visual-review", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install nubjs/nub visual-reviewInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add nubjs/nub --skill visual-review -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/nubjs/nub.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/visual-review .github/skills/visual-review && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "visual-review" agent skill from https://github.com/nubjs/nub/tree/main/.claude/skills/visual-review into .github/skills/visual-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "visual-review", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add nubjs/nub --skill visual-review -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install nubjs/nub visual-review --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nubjs/nub.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/visual-review .opencode/skills/visual-review && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "visual-review" agent skill from https://github.com/nubjs/nub/tree/main/.claude/skills/visual-review into .opencode/skills/visual-review/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "visual-review", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
visual-reviewVerify UI/layout/styling changes are correct by computing occlusion, clipping, and alignment from the browser's resolved paint order via the chrome-devtools MCP evaluatescript tool — instead of…
Visual Review is an agent skill from nubjs/nub. Verify UI/layout/styling changes are correct by computing occlusion, clipping, and alignment from the browser's resolved paint order via the chrome-devtools MCP evaluatescript tool — instead of eyeballing a flat screenshot. Invoke BEFORE declaring any UI, site, or styling/layout change correct. Screenshots have no depth buffer, so z-index/occlusion/clip bugs are exactly where "just look at it" fails; the evaluatescript routines below turn those fuzzy visual judgments into deterministic measurements — including…
Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `optical-center.js`).
It sits in Testing & QA, covering Browser testing. It works with Model Context Protocol and Chrome DevTools. The repository describes itself as: The fast all-in-one Node.js toolkit. The licence is MIT.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 568e73a. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (JavaScript), which the agent can run.
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Visual Review loads about 3.4k tokens when it runs. Until then it costs about 168 tokens; SKILL.md has 1,083 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from nubjs/nub at commit 568e73a, republished under its MIT licence (© nubjs). 1,083 words, ~3,444 tokens.
.claude/skills/visual-review/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.A flat PNG has no depth buffer and no stacking-context model, so layering and clipping bugs (z-index, overflow: hidden, fixed/sticky overlays) are exactly where eyeballing fails. The browser already resolved the paint order; query it with evaluate_script (chrome-devtools MCP).
Run both passes. Geometry catches occlusion the eye misses; the eye catches font-metric and color issues geometry misses.
A layout can be geometrically consistent and still look wrong. Never declare a spacing/alignment/centering change correct from measurements alone — change it, screenshot it, look, and adjust by eye. Expect to nudge against the math when:
rounded-full) eat edge space — content at px-3.5 from a rounded end looks tighter than against a square edge, so a pill with symmetric padding and a leading icon looks lopsided; the text-adjacent cap needs more padding (keep symmetric px on the pill, add pr-*/pl-* per button on its text side).w-4 icon whose glyph is 14px and visually light leaves dead space, inflating the perceived gap beyond the measured flex gap.Geometry decides occlusion/clipping; the eye decides balance/scale/centering.
evaluate_script routinesReplace 'SELECTOR' with a real CSS selector before running.
Reports what fraction of the element is actually visible, and names anything covering it.
(selector => {
const el = document.querySelector(selector);
if (!el) return { error: 'not found' };
const r = el.getBoundingClientRect();
if (r.width === 0 || r.height === 0) return { error: 'zero-size box' };
const N = 5; // 5×5 = 25 sample points across the box
let visible = 0; const coveredBy = new Set();
for (let i = 0; i < N; i++) for (let j = 0; j < N; j++) {
const x = r.left + (i + 0.5) / N * r.width;
const y = r.top + (j + 0.5) / N * r.height;
const top = document.elementFromPoint(x, y); // topmost painted element here
if (top === el || el.contains(top)) visible++;
else if (top) coveredBy.add(top.tagName.toLowerCase() +
(top.id ? '#' + top.id : '') +
(top.className ? '.' + String(top.className).split(' ')[0] : ''));
}
return { coverage: visible / (N * N), coveredBy: [...coveredBy] };
})('SELECTOR')coverage === 1 → no occlusion. coverage < 1 with a coveredBy entry that is not an ancestor/descendant → occlusion bug; the array names the covering element. No z-index reasoning required — elementFromPoint returns the browser's resolved paint order.
(selector => {
const el = document.querySelector(selector);
const r = el.getBoundingClientRect();
for (let p = el.parentElement; p; p = p.parentElement) {
const o = getComputedStyle(p).overflow;
if (o === 'visible') continue;
const pr = p.getBoundingClientRect();
if (r.left < pr.left || r.top < pr.top || r.right > pr.right || r.bottom > pr.bottom)
return { clippedBy: p.tagName + (p.id ? '#' + p.id : ''),
overflow: o, target: r, clip: pr };
}
return { clipped: false };
})('SELECTOR')clipped: false is clean. Anything else → the element is cropped by that ancestor.
([a, b] => {
const A = document.querySelector(a).getBoundingClientRect();
const B = document.querySelector(b).getBoundingClientRect();
return {
leftAligned: Math.abs(A.left - B.left), // px delta; ~0 = aligned
centerXdelta: Math.abs((A.left+A.right)/2 - (B.left+B.right)/2),
gap: B.top - A.bottom, // vertical spacing between them
};
})(['SEL_A', 'SEL_B'])State verdicts in px: "left-edge delta 2px (clean)", "gap 28px vs expected 24px."
getBoundingClientRectcenters the line box, not the visible ink. Fine at the same font-size; for elements at different font-sizes that must look centered together, use §5.
(selector => {
const r = document.querySelector(selector).getBoundingClientRect();
return {
inViewport: r.top >= 0 && r.left >= 0 && r.bottom <= innerHeight && r.right <= innerWidth,
rect: r,
viewport: { w: innerWidth, h: innerHeight },
};
})('SELECTOR')Measures the alpha-weighted centroid of the actual glyph ink by rasterizing each label's computed font to a canvas. Implementation lives beside this skill in optical-center.js; inline it into one evaluate_script call.
// after inlining optical-center.js in the same evaluate_script:
opticalCenter(['.wordmark', 'a[href="/docs"]', 'a[href="/blog"]'])
// → results:[{selector, comY, deltaFromAnchor}], cssHint:[{selector, nudge}]
// deltaFromAnchor ~0 = optically aligned; cssHint gives the ready-to-paste translate.{ apply: true } nudges each non-anchor toward the anchor, re-measures the post-nudge DOM, and iterates until converged, returning { before, after, appliedTranslateY }. Don't hand-derive nudges — transcribe appliedTranslateY to CSS.{ overlay: true } paints the analysis onto the page (anchor solid-green, others dashed-red, px deltas labelled) so the next screenshot self-documents.vertical-align:baseline, which flex/grid ignore, so the tool descends from a flex <a> to the inline element hosting the text.text-shadow, -webkit-text-stroke, gradient text, and raster content aren't in the font render — screenshot the element's clip box and centroid the real pixels instead, or trust the eye.Keep it to ONE tool call. To avoid re-inlining ~6KB, define it once via navigate_page's initScript so window.opticalCenter exists in every later evaluate_script.
optical-center.js is dependency-free, JSON-in/JSON-out, no closure over outer scope, so it rides on any evaluate primitive. Pattern is always: inject once (defines window.opticalCenter) → call it.
// chrome-devtools MCP — inline in one evaluate_script, or persist via initScript:
navigate_page({ url, initScript: <contents of optical-center.js> })
evaluate_script(`() => window.opticalCenter(['.wm','a[href="/docs"]'], { overlay:true })`)
// Playwright (Node):
await page.addInitScript({ path: 'optical-center.js' }); // window.opticalCenter on every doc
const r = await page.evaluate(([t,o]) => window.opticalCenter(t,o),
[['.wm','a[href="/docs"]'], { apply:true }]);
// Puppeteer:
await page.evaluateOnNewDocument(fs.readFileSync('optical-center.js','utf8'));
const r = await page.evaluate((t,o) => window.opticalCenter(t,o),
['.wm','a[href="/docs"]'], { overlay:true });
// Selenium / WebDriver (any language):
driver.execute_script(open('optical-center.js').read()) // define it once
r = driver.execute_script("return window.opticalCenter(arguments[0], arguments[1])",
['.wm', 'a[href="/docs"]'], { 'apply': True })
// DevTools console / bookmarklet: paste the file, then call opticalCenter([...]).Don't break these invariants when editing the file: no import/export/require in the injected source, args stay plain JSON, the return stays JSON-serializable (never a DOM node), and it keeps defining a single global.
The most-repeated visual defect: an icon, glyph, emoji, badge, or counter beside text, riding high or low. items-center centers the glyph's BOX on the flex line; the eye aligns INK, and those never coincide — a digit has no descender so its ink rides high, an SVG's ink sits wherever its path falls in its viewBox, and an emoji is a bitmap whose metrics ignore your font size.
One shared nudge cannot fix a cluster. Measure each glyph, correct each glyph. Illustrative divergence for a real count-badge cluster (11.5px text, 12px icons):
| glyph | ink height | offset from the digit's ink center | correction |
|---|---|---|---|
| filled octicon | 10.8px | 1.16px low | translateY(-0.1em) |
| lucide stroke glyph | 9.0px | 1.29px low | translateY(-0.112em) |
| emoji | 16.0px | 0.26px — sub-pixel | none; a nudge only blurs the bitmap |
em, never px, then prove it by doubling the cluster's font size and re-measuring; the residual must stay near zero.// Baseline: an empty zero-size inline-block's bottom margin edge IS the baseline of the INLINE context
// it sits in. THE TRAP: a badge holder is usually inline-FLEX, so a probe appended there becomes a FLEX
// ITEM and reports the flex line's center — inflating a real 1.2px error into a plausible 3.5px one.
// Wrap the text node in its OWN inline span, probe INSIDE.
const baselineOfTextNode = (node) => {
const span = document.createElement("span")
node.parentNode.insertBefore(span, node); span.appendChild(node)
const probe = document.createElement("span")
probe.style.cssText = "display:inline-block;width:0;height:0;padding:0;margin:0;border:0"
span.appendChild(probe)
const baseline = probe.getBoundingClientRect().bottom
const cs = getComputedStyle(span)
const font = `${cs.fontStyle} ${cs.fontWeight} ${cs.fontSize} / ${cs.lineHeight} ${cs.fontFamily}`
probe.remove(); span.parentNode.insertBefore(node, span); span.remove()
return { baseline, font }
}
const inkOfText = (text, font, baseline) => {
const c = document.createElement("canvas").getContext("2d"); c.font = font
const m = c.measureText(text)
return { top: baseline - m.actualBoundingBoxAscent, bottom: baseline + m.actualBoundingBoxDescent }
}
// An SVG geometry element's getBoundingClientRect IS its ink box (stroke included). Union EVERY child —
// a multi-path icon's ink is all of it, not the first path.
const inkOfSvg = (svg) => {
const rects = [...svg.querySelectorAll("path,rect,circle,ellipse,polyline,polygon,line")]
.map((g) => g.getBoundingClientRect())
return { top: Math.min(...rects.map((r) => r.top)), bottom: Math.max(...rects.map((r) => r.bottom)) }
}
// → returns textInkCenter - glyphInkCenter. NEGATIVE = glyph sits BELOW the text and must be LIFTED.Distrust a suspiciously large reading. A 3.5px error on an 11.5px font is ~30% — a broken instrument, not a misalignment. If the number claims a gross error and the picture shows a subtle one, fix the instrument.
Mirror the real product before inventing a treatment. If the thing exists in a product the user knows (GitHub, Linear, an existing component), drive the real one headless and read its computed values rather than designing from taste. Corollary: color belongs to an item's own state, not to its links.
Run for any change to site/ or other rendered UI. Steps 3–4 are what a screenshot review cannot do.
take_screenshot, full page + tight crop around the changed element.list_console_messages. A 200 alongside a thrown error is still a broken page.coverage < 1 with a non-ancestor cover → flag it.Say so explicitly. Reason about stacking from the CSS (position, z-index, overflow, paint order), but label it inference, not measurement. Do not silently claim visual verification you couldn't do.
© nubjs, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in .claude/skills/visual-review of nubjs/nub.
Open the folder on GitHubat commit 568e73a
Visual Review next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Visual Review this skillnubjs/nub | 4.4k | — | ~3.4k | Automated safety check: Pass | MIT | |
| Browser Testing with Chrome DevToolsaddyosmani/agent-skills | 103k | 4 repos | ~3.5k | Automated safety check: Warn | MIT | |
| Diff-Driven Smoke TestsSkyvern-AI/skyvern | 23k | — | ~5.2k | Automated safety check: Pass | AGPL-3.0 | |
| System Bridge Testing Workflowtimmo001/system-bridge | 356 | — | ~843 | Automated safety check: Pass | Apache-2.0 | |
| Mirroir Onboardjfarcand/mirroir-mcp | 245 | — | ~4.4k | Automated safety check: Notes | Apache-2.0 | |
| Capture Bannersnguyenyou/scalex | 109 | — | ~586 | Automated safety check: Pass | MIT |
addyosmani/agent-skills
Connects an agent to a real Chrome instance through the Chrome DevTools MCP server, so it can inspect the DOM, read console errors and profile performance directly.
Skyvern-AI/skyvern
Reads your git diff, writes a handful of happy-path browser smoke tests, runs them with Skyvern or Chrome DevTools MCP and posts screenshot evidence to the PR.
timmo001/system-bridge
How to test System Bridge - Go table-driven tests and commands, web-client quality checks (lint/typecheck/format, no unit tests), the Chrome DevTools MCP interactive test loop for UI and WebSocket…
jfarcand/mirroir-mcp
Onboard a consumer web app to mirroir's .mirroir/ dotfile by EXPLORING the running app (chrome-devtools-mcp) — derive real selectors from the accessibility tree, exercise each surface's primary…
nguyenyou/scalex
Re-render Scalex banner and OG image PNGs from their HTML source files using Chrome DevTools MCP.
bgauryy/octocode
A skill your agent uses when a live page needs Chrome DevTools/CDP evidence: network failures, console errors, performance, DOM/CSS actionability, screenshots/PDF, cookies/storage…
nubjs/nub
Diagnose and clear CPU, memory, and disk contention on the maintainer's dev host.
nubjs/nub
Reclaim disk on the maintainer's Mac when the volume is full or filling — ENOSPC, "no space left on device", a failed build or agent harness, or a routine sweep of Rust build residue.
nubjs/nub
Build a performance chart for nubjs.com — the SVG bar figures in blog posts, docs pages and social posts (a runtime augmentation against plain node, an install or dispatch comparison, a cross-tool…
nubjs/nub
A skill your agent uses when running a compatibility/parity AUDIT — enumerating where nub diverges from a reference it claims parity with (pnpm CLI grammar, a lockfile format, a Node behavior, a…
nubjs/nub
Run ad-hoc Nub tests and debugging probes on real local Linux guests.
nubjs/nub
Performance-trace Nub package-manager installs using the existing phase timings, structured diagnostics, and sampling-profiler workflow.
Works with
Categories
Verify UI/layout/styling changes are correct by computing occlusion, clipping, and alignment from the browser's resolved paint order via the chrome-devtools MCP evaluatescript tool — instead of…. Visual Review is an agent skill from nubjs/nub. Verify UI/layout/styling changes are correct by computing occlusion, clipping, and alignment from the browser's resolved paint order via the chrome-devtools MCP evaluatescript tool — instead of eyeballing a flat screenshot.
Visual Review fits situations like: tasks that involve Browser testing.
Run `npx skills add nubjs/nub --skill visual-review -a claude-code`. Or copy the skill folder (.claude/skills/visual-review in nubjs/nub) into .claude/skills/visual-review in your project. Claude Code loads it when a task matches its description.
Run `npx skills add nubjs/nub --skill visual-review -a codex`. Or copy the skill folder (.claude/skills/visual-review in nubjs/nub) into .agents/skills/visual-review in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add nubjs/nub --skill visual-review -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/visual-review, .gemini/skills/visual-review, .github/skills/visual-review and .opencode/skills/visual-review in your project.
Going by SKILL.md and its folder, Visual Review needs JavaScript for the scripts in its folder. Our summary lists: Node.js.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Visual Review is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.4k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Visual Review: Browser Testing with Chrome DevTools (addyosmani/agent-skills, 103k stars), Diff-Driven Smoke Tests (Skyvern-AI/skyvern, 23k stars), System Bridge Testing Workflow (timmo001/system-bridge, 356 stars) and Mirroir Onboard (jfarcand/mirroir-mcp, 245 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
nubjs (a GitHub organization) maintains it in nubjs/nub, which has 4,372 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on October 7, 2026.
Source: nubjs/nub on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.