cd /news/ai-agents/show-hn-divorce-an-agent-skill-for-n… · home › topics › ai-agents › article
[ARTICLE · art-166370] src=github.com ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Show HN: Divorce – an agent skill for native HTML, verified with Nu and axe

A developer released divorce, an open-source agent skill that directs coding agents to choose native HTML elements over div-based markup and then verifies the output with the Nu HTML Checker and the axe accessibility engine. Across 5 runs of 8 tasks, the same agent using divorce produced 29% less HTML, 41% less JavaScript, 33% less ARIA and 76% fewer axe violations, though Nu errors rose to 3 of 40 pages with divorce versus 0 of 40 without. The skill installs via `npx skills add ElRaxy/divorce` for Claude Code, Codex, Gemini CLI, GitHub Copilot and OpenCode, and its gate returns pass, fail or not_measured from code rather than the model, with missing evidence never counted as a pass.

read5 min views1 publishedNov 9, 2026
Show HN: Divorce – an agent skill for native HTML, verified with Nu and axe
Image: Michielbdejong (auto-discovered)

End your agent's toxic relationship with div soup.

5 of 9 accessibility bugs pass both Nu and axe. divorce stops your agent from writing them.

−29% HTML · −41% JavaScript · −76% axe violations, same agent with and without divorce. Numbers.

Watch with sound (MP4) · music: Bach, Prelude in C major BWV 846, Kimiko Ishizaka, CC0

Your agent writes <div onclick>. Every validator says it's fine. Someone using a keyboard can't reach it.

divorce makes the agent pick the native element first, then proves it with Nu and axe.

npx skills add ElRaxy/divorce

One line for Claude Code, Codex, Gemini CLI, GitHub Copilot, OpenCode and more agents, via skills.sh. As a Claude Code plugin:

/plugin marketplace add ElRaxy/divorce
/plugin install divorce@divorce

Other agents and install routes: Details.

HTML JavaScript ARIA axe violations
With divorce −29% −41% −33% −76%

Over 5 runs of 8 tasks. Nu errors: 3 of 40 pages with divorce, 0 of 40 without. Method and limits in evals.

Both of these pass the Nu HTML Checker and axe. Only one can be reached with Tab.

Without divorce:

<div onclick="document.getElementById('result').textContent = 'Saved'">Save</div>

With divorce:

<button type="button" onclick="document.getElementById('result').textContent = 'Saved'">Save</button>
Case Nu axe
Use a link for navigation — —
Use details for a disclosure — —
Use dialog for a modal task — —
Use a button for an action — —
Represent a list with ul and li — —
Keep heading levels in order flags it flags it (moderate)
Provide an image text alternative flags it flags it (critical)
Associate a label with its control — flags it (critical)
Follow document order for focus — flags it (serious)

5 of 9 pass both checkers. divorce picks the element before anything is checked.

  1. Does it need to exist? If not, omit it.
  2. Does the project already have it? Reuse it.
  3. Is there a native HTML element for it? Use it.
  4. Can CSS do it without JavaScript?
  5. Does an installed dependency cover it?
  6. Only then: the smallest code that works, plus a small test for logic.

Then the gate checks the result: Nu on the HTML, axe on the rendered page. Code, not the model, delivers the verdict: pass, fail or not_measured (exit codes).

All agents, installation routes and gate commands #

Use the plugin commands above in Claude Code, or run one standalone route from an existing checkout's root; validator setup is separate.

  • Claude, user-wide: sh install.sh --claude — Copies the skill and scripts to~/.claude/skills/divorce/ , recording the installation.
  • Claude, one project: sh install.sh --claude --project DIR — Copies toDIR/.claude/skills/divorce/ .
  • Codex: sh install.sh --codex — Copies to~/.codex/skills/divorce/ ;--project is Claude-only.
  • Other agents: sh install.sh --agents-md AGENTS.md — Appends or replaces a marked block in the instruction file.

For a manual copy, copy the entire skills/divorce/ directory, including scripts, to ~/.claude/skills/divorce/. Instruction blocks point to the gate's absolute path: keep the checkout in place. The standalone installer does not register a plugin, install validators or add an automatic gate hook; copies do not update themselves (maintenance).

With the served version of examples/div-button/after.html already loaded in your verification browser session:

python3 skills/divorce/scripts/gate.py html examples/div-button/after.html
agent-browser eval "$(python3 skills/divorce/scripts/gate.py axe-snippet)" > axe.json
python3 skills/divorce/scripts/gate.py axe axe.json
python3 skills/divorce/scripts/gate.py check --html examples/div-button/after.html --axe axe.json --axe-max-impact serious

Replace the HTML input with your served URL or built file and capture genuine axe evidence from that same page and state. Outside the checkout, use the installed script path. The gate does not open a browser, run axe or refresh a capture; see all commands and flags.

Coverage, frameworks and maintenance

A passing gate is not full WCAG conformance, a CSS or JavaScript correctness check, a performance audit or a design review. Manual keyboard, focus, interaction and visual checks remain necessary; accessibility, boundary validation and data-loss handling stay in scope.

What the verdict covers

  • 0: pass — The invoked check passed its configured policy.
  • 1: fail — HTML errors or axe violations at or above the impact threshold.
  • 2: not_measured — Missing tools, unavailable input or unusable evidence; never a pass.

Missing or invalid measurement takes priority over observed failures. Otherwise, blocking findings fail; with neither condition, the check passes. Serious and critical axe violations fail by default; lower impacts remain visible. HTML warnings do not fail. axe totals count violated rules and each rule records affected nodes.

A complete gate needs HTML and axe evidence; an HTML-only pass says nothing about axe. The caller supplies evidence for the intended page: the gate does not authenticate it or prove it is current (exact reasons and limits).

Runtime and validator setup

  • Python 3.9+ for the standalone installer; Python 3 for the gate; a shell for installation scripts.
  • Nu HTML Checker: VNU ,vnu onPATH , orVNU_JAR with Java.
  • Nu setup needs network access, curl , andshasum orsha1sum ; native archives also needunzip , while--jar needs Java.
  • A rendered page and a way to evaluate the axe snippet; it loads axe-core 4.10.2 unless that version is already present, so script must be allowed.
sh skills/divorce/scripts/install-vnu.sh

The installer verifies the download's SHA-1 and the validator's version command. Set VNU to its printed binary path or add vnu to PATH; for --jar, set VNU_JAR to the printed JAR path. The axe snippet selects WCAG 2.2 A/AA, including earlier versions, and best-practice rules.

MIT; see NOTICE for third-party licenses: the decision ladder is adapted from ponytail (MIT), semantic HTML and modern CSS guidance from kemiljk/skills (MIT); Nu is MIT and axe-core is MPL-2.0, and neither validator is bundled.

── more in #ai-agents 4 stories · sorted by recency
── more on @divorce 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-divorce-an-a…] indexed:0 read:5min 2026-11-09 · —