Hover

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Uyari
  • process.env — Environment variable access in examples/basic-app/playwright.config.ts
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Local-first, open-source AI testing for the web. The widget rides on Claude Code or OpenAI Codex (your local CLI — no API key, no per-token billing) to drive your real Chrome via Playwright MCP. Verified sessions crystallize into plain @playwright/test specs that run in CI with zero AI deps. Support mainstream front-end projects

README.md

Hover

Hover — the local-first, open-source way to author end-to-end tests with AI

English · 简体中文

License @hover-dev/cli on npm Covers Vite, Astro, Nuxt, Webpack, RN Web @hover-dev/core on npm

Latest release Stars Forks Last commit Local CLI Agent First


Open the floating chat in your dev page, describe what you want to verify in plain English, watch AI operate your app for real. When the run is clean, click Save as spec — Hover writes a standard @playwright/test file you can run in CI without an agent in the loop, forever.

No API key, no per-token billing. Hover spawns the coding-agent CLI already on your PATH (claude / codex) and rides on the subscription you already pay for.

┌──────────────────────────────────────────────────────────┐
│  type natural language ── AI drives your Chrome via CDP  │
│              │                                           │
│              ▼                                           │
│       browser_click, browser_type, …  (Playwright MCP)   │
│              │                                           │
│              ▼                                           │
│   verified session ── Save as Playwright spec ──┐        │
│                                                 ▼        │
│                       __vibe_tests__/login-flow.spec.ts  │
│                       (plain @playwright/test, no agent) │
└──────────────────────────────────────────────────────────┘

See it in action

Hover demo — watch on YouTube
▶ Watch the demo on YouTube

Ten real example apps live under examples/. Four stress different testing surfaces (login, multi-step form, cart checkout, canvas + DOM mix) — the Hover widget is driving each one. The other six exercise bundler / framework coverage (Astro, Nuxt, Next, webpack, React Native Web, plus a deliberately-uninstrumented third-party origin used by the e-commerce popup flow).

Testing surfaces

01 · basic-app — login + counter + todos
01 · basic-app — the smoke baseline. Login → increment a counter → add a todo. The agent ran the full sequence in 11 turns at $0.16; the result card surfaces both Save as Skill (replayable from the next conversation) and Save as spec (a standard @playwright/test file).
02 · stock-registration — multi-step brokerage form
02 · stock-registration — ~50-field broker application with conditional reveals. The agent filled the text fields, then the form's own validator caught three required radio groups (Sex / Marital status / US tax residency). Hover pauses and surfaces a done card explaining why — the human can flip those three radios and re-run.
03 · e-commerce — cart and checkout
03 · e-commerce — Amazon-style storefront. "Buy two top-rated headphones, ship to my saved address, pay with card." The agent picked the right category, added two items, and walked the cart up to the payment step. Long action chain, real cart state, ready for Save as spec.
04 · canvas-paint — DOM toolbar amid canvas pixels
04 · canvas-paint — a drawing app where the artwork is an opaque <canvas>. Snapshots can't read pixel content, but the agent navigates the DOM toolbar (Tool · Color · Brush size · Save) end-to-end — proving Hover's semantic-selector preference holds up when the visual surface itself isn't introspectable.

Bundler coverage

Each of the six targets below pairs the same counter + todo smoke page with a different host bundler / framework, so each Hover integration package has a dedicated dogfood ground.

Example Bundler / framework Hover package Port
examples/astro-app Astro 5 (static, astro dev) @hover-dev/astro 5178
examples/nuxt-app Nuxt 4 (SSR, nuxt dev) @hover-dev/nuxt 5179
examples/next-app Next.js 16 App Router (Turbopack, next dev) @hover-dev/next 5182
examples/webpack-app vanilla webpack 5 + webpack-dev-server webpack-plugin-hover 5180
examples/rn-web-app React Native Web (Vite, react-nativereact-native-web alias) vite-plugin-hover 5181
examples/payment-provider Vite, no Hover plugin n/a 5177

The payment-provider target is deliberately uninstrumented — examples/e-commerce's "Pay with PayHover" button opens it in a new tab, and the agent has to discover, switch to, drive, and confirm callback into the original tab without a widget present.

React Native — only the Web target is supported

Hover targets browser-runnable frontends. React Native (native iOS / Android) is not supported and not on the roadmap — Hover's stack (Chrome DevTools Protocol + Playwright + Shadow-DOM widget) doesn't translate to native mobile, and that space is well served by Maestro, Detox, and Appium. React Native Web projects compile to plain DOM and are fully covered — see examples/rn-web-app for the wire-up (a one-line react-nativereact-native-web Vite alias).

Why Hover

Several good tools already exist in this space; Hover is what falls out when you optimise for a different axis — artifact portability.

Tool What it does The trade-off
Playwright Codegen Records your clicks → .spec.ts. No AI, no auth Can't think — just replays what you did literally
Stagehand / Midscene AI-augmented tests; both ship caches so steady-state CI runs skip the LLM on cache hits. Configure an OpenAI / Anthropic API key — per-token billing on cache misses Tests still run inside the vendor SDK + a cache file in your repo. Not portable to a plain Playwright runner
Hover AI drives the browser once to explore; saves a deterministic spec, a replayable skill, and a Jira-importable case from the same click. No API key — Hover spawns the coding-agent CLI already on your PATH (claude / codex), so your existing Claude Pro/Max or ChatGPT subscription covers it Crystallised spec is brittle to UI changes — when it breaks, re-run the agent (it doesn't self-heal at CI time)

What Hover is not trying to do: be the better test-time AI runtime. Stagehand's caching + self-healing is more sophisticated than anything we'd build, and Midscene's vision fallback handles canvas / iOS / Android targets we can't touch.

What Hover IS trying to do: make the saved artifact be plain @playwright/test code that runs with npx playwright test on a fresh machine, zero AI deps. The agent's job ends at "save"; CI is pure Playwright. That's the handoff.

One exploration, three audiences

A verified Hover session can crystallize three different ways. A single 💾 Save as ▾ dropdown on the done card opens a menu listing all three; pick one, two, or all three.

  • 📜 Save as spec__vibe_tests__/<slug>.spec.ts — standard @playwright/test code with getByRole / getByLabel / getByTestId semantic selectors. Runs in CI, in pre-commit, on a fresh machine. No agent, no claude binary, no API key. Ground truth for the flow. The JSDoc header now carries a numbered plain-English Steps: block plus an Expected: block, so QA / PMs can read what the test does without opening Playwright docs.
  • 💾 Save as Skill.claude/skills/<slug>/SKILL.md — a replayable instruction set the agent auto-discovers next time. Type "execute login-as-claude" in any future conversation and the recorded steps run again, in your real browser, using the same Playwright MCP sandbox. Skills are plain Markdown checked into your repo.
  • 📋 Save as Jira case__vibe_tests__/<slug>.case.csv — a multi-row CSV in the Xray Test Case Importer format (Manual Test type, one Action per row, Expected Result on the last row). Drag it into Xray, Zephyr Scale, or the native Jira issue importer and the agent's flow shows up as a real, trackable test case — instantly assignable, linkable to a story / sprint, runnable as a Manual Test session. No copy-pasting steps from a code editor into Jira ever again.
📜 .spec.ts 💾 SKILL.md 📋 .case.csv
Lands in __vibe_tests__/ .claude/skills/ __vibe_tests__/
Read by Node + Playwright (CI) Claude Code / agent Xray · Zephyr Scale · Jira issue importer
Audience CI, devs writing code Future you, exploring QA reviewing · PM tracking · auditor signing off
Determinism Hard contract Best-effort replay Manual review — human runs and ticks
Edit with Code editor Markdown editor Spreadsheet, or the test-mgmt UI after import

Pick one or pick all three. Spec for CI, Skill for the next exploration, Case for the test team / sprint board — same session, same Save card.

Save dropdown — Playwright spec, Claude Code Skill, Jira test case (CSV) Save as Jira case modal

Shareable across the team, not locked into a tool

All three files check into the same git repo as the rest of your code. The moment a frontend developer saves a flow, everyone else can use it — no Hover required, no agent, no token:

  • QA / dedicated testers clone the repo and run pnpm test:e2e for the deterministic specs, or drag the matching .case.csv into Xray / Zephyr Scale / Jira and run the same flow as a tracked Manual Test session. They don't need to install Hover, configure Chrome, or know what an "agent" is.
  • Other frontends invoke a saved skill from their own Hover widget — "execute login-as-claude" replays the recorded steps in their own browser session. Skills work best for flows that don't depend on user-specific data or dynamic element IDs — think navigation sequences, form patterns, and UI explorations rather than session-bound state.
  • PR review treats every saved spec as plain code — diff-able, blame-able, requestChanges-able. There's no proprietary file format, no SaaS dashboard, no "the test passed but we can't see how it got there".
  • Sprint planning / PM tracking.case.csv imports into Jira as a real test issue, linkable to a story, assignable to a tester, runnable as a Manual Test session. The Jira board now reflects what your app can do, not just what's planned.
  • Onboarding is git clone && pnpm install && pnpm test:e2e. The test suite doubles as living documentation of how every important flow in the app works — new hires watch real browsers walk through real scenarios.

Everything checks into git. Nothing lives in a vendor's database. A spec written on a developer's laptop on Monday is reviewed by QA on Tuesday and runs in CI from Wednesday — same file, no export step.

What you get today

  • Vite plugin that injects a Shadow-DOM widget into your dev page. No-op in production. Marked data-hover="true" so your own Playwright runs can skip it.
  • No API key, no .env, no per-token billing. Hover spawns whichever coding-agent CLI is on your PATH and reuses the subscription you already pay for (Claude Pro / Max, ChatGPT Pro). The @hover-dev/core package contains zero LLM SDK code — there's nothing to authenticate against. Get the most out of the agent quota you've already bought.
  • Multi-agent. claude (hard sandbox, recommended) and codex (soft sandbox) are both wired. Service auto-detects which one you have on PATH; the widget header shows the active agent as a pill (claude ▾) with a dropdown to switch on the fly. cursor-agent / aider / gemini-cli are one-file additions to the registry.
  • Per-agent sandbox policy. Hard-sandbox agents (claude) get an explicit allow/deny list so only Playwright MCP is callable; Bash, Edit, Write, Read, WebFetch, etc. all explicitly denied; --max-budget-usd ceiling supported. Soft-sandbox agents (codex) can't disable their built-in tools at the CLI level, so we use --sandbox read-only + a strict developer_instructions system prompt; the widget marks these with a ⚠ badge so you know the surface is broader.
  • Widget v2 — info hierarchy that scales. Conversation reads as one row per natural-language intent, not a flood of raw browser_click events. Tool-call detail is folded behind a chevron; the running step gets a mint left bar + spinner. Dark panel, single mint accent, custom inline-SVG icons + theme-matched tooltip — designed to sit unobtrusively over your dev page.
  • Result & Findings cards. At the end of a run the widget renders the agent's verification report as a dedicated Result card (markdown-stripped, plain text) with the Save-as dropdown attached. If the agent's summary contained a ## Findings block — bugs, minor issues, observations — those land in a separate Findings card with severity-coded rows. Bug discovery is a first-class output, not buried in narration.
  • CDP-attached browser driving. Hover drives a debug Chrome it launches under an isolated profile at <tmpdir>/hover-chrome, never a fresh headless Chromium. Your main Chrome profile is untouched — log in once inside the debug Chrome and that session persists across Hover commands and dev-server restarts, because the profile dir is reused.
  • Three crystallisation formats.
    • Save as Playwright spec__vibe_tests__/<slug>.spec.ts, uses getByRole / getByLabel / getByTestId semantic selectors. JSDoc header carries plain-English Steps + Expected blocks so non-coders can review.
    • Save as Skill.claude/skills/<slug>/SKILL.md, replayable by saying "execute login-as-claude" in a future conversation.
    • Save as Jira case__vibe_tests__/<slug>.case.csv, an Xray-compatible multi-row CSV that imports straight into Jira / Xray / Zephyr Scale as a Manual Test issue.
  • Record mode with built-in checks — Toggle Record in the footer, do the flow manually, get the same step sequence as if the agent had driven it. While recording, the sub-toolbar lets you switch what the next click captures:
    • ● Record — record the click / fill / select as a Playwright step (default)
    • ✓ Exists — check the element appears: expect(SEL).toBeVisible()
    • ¶ Says — check the element's text matches: expect(SEL).toHaveText("…")
    • = Equals — check an input / select / checkbox's current value
      Check modes are one-shot — after the click commits the assertion, you snap back to Record. The same Save card downstream takes everything: actions and checks bake into the same .spec.ts. The downstream save path doesn't care whether the steps came from a human or from Claude.
  • Fix prompt button — A separate ⌖ Fix button next to Record. Click it, click any element on the page, type what you'd like to change, and Hover assembles a precise prompt — source file:line:col, ancestor source chain, React component chain, Playwright selector, outer HTML — onto your clipboard. Paste into Cursor / Claude Code / Windsurf and the agent has exact context. See Fix prompt below.
  • Voice mode (push-to-talk + spoken progress). Hold the round 🎙 button next to Send, speak your instruction (中文 or English — Hover detects), release to fire. While the agent works, key step events (Opening page / Clicking … / Done in N steps) get read aloud in the same language you used, so you can keep your eyes on the page under test. Pure browser-native Web Speech API — zero extra API keys, zero service-side changes. Chrome 139+ runs the recogniser on-device (SODA pack). Toggle TTS off from the new ⚙ settings panel. See Voice mode below.
  • Session persistence + resume. Widget state survives page reload via localStorage; the next prompt resumes the same claude --session-id.

Bug discovery as a first-class output

The agent's verification report and any bugs it finds get their own cards at the end of the run — separate from the step-by-step timeline. The Result card holds the narrative summary (PASS / FAIL + steps the agent took); the Findings card lists every ## Bug / ## Minor / ## Note the agent flagged, severity-coloured.

Findings card — bugs and minor issues the agent flagged

The system prompt teaches the agent to emit this structured block at the end of every run, so QA reading the saved spec can scan the bug list without scrolling through tool calls.

Voice mode

Speak your prompt; hear the agent's progress. Hold the round 🎙 button next to Send (push-to-talk) — the icon switches to a live elapsed-seconds counter and the mint glow pulses while listening. Mid-sentence pauses don't cut you off; the recogniser stays open until you release. Speak Chinese or English — Hover detects the language from your prompt and routes both the TTS playback voice (prefers Siri / Premium / Google over legacy system voices) and the spoken step phrasing to match (打开页面 / 点击登录按钮 / 完成,共 5 步 vs. Opening page / Clicking Submit / Done in 5 steps).

Three knobs worth knowing:

  • Push-to-talk only. No always-listening mode — privacy by default, no hot-mic in your dev environment.
  • TTS on by default, one click to mute. Open the ⚙ settings panel in the header, flip Speech narration off. In-flight utterances cut immediately. State persists across reloads.
  • No cloud round-trip. Both STT and TTS use the browser's built-in Web Speech API. On Chrome 139+ the recogniser installs SODA language packs and runs on-device — audio never leaves your machine. No new API keys, no .env entries, no service-side changes. Firefox (no SpeechRecognition) sees a disabled mic button with a "use Chrome" tooltip.

Voice playback is filtered, not a fire-hose: only tool_use events that map to a humanised verb (Clicking, Filling form, Switching tab, …) get spoken; browser_snapshot / browser_take_screenshot / read-only diagnostics are deliberately silent so the ear isn't drowned in noise. The Stop button cancels any in-flight utterance the moment you press it.

Pick your agent — claude, codex, or roll your own

The widget header shows the active agent as a pill. Click it for a dropdown of every agent in the registry, marked with what's installed on your PATH and what isn't (with copy-pasteable install hints). Switch on the fly without restarting the dev server.

Agent picker dropdown — Claude Code installed, OpenAI Codex available

claude is the recommended default (hard sandbox, MCP-only tool surface). codex is wired as the second-class citizen (soft sandbox — codex doesn't expose a built-in-tool deny list at the CLI level, so we lean on its --sandbox read-only flag + a strict developer_instructions prompt). The widget marks soft-sandbox agents with a ⚠ badge so you know the surface is broader.

Adding cursor-agent / aider / gemini-cli / your own coding-agent CLI is one file in packages/core/src/agents/registry.ts.

Fix prompt

Vibe coding prompt comparison — vague natural-language ask vs. a structured, source-attributed Fix prompt

The widget knows the source location of every host element on your page — a Vite transform stamps data-hover-source="file:line:col" onto every <button> / <div> / <input> you authored in JSX. Click the ⌖ Fix button next to Record, click any element, type what you'd like to change, hit ⌘↵, and Hover assembles a precise prompt into your clipboard. Paste it into Cursor / Claude Code / Windsurf and your agent has exact context.

The prompt is fact-only — no leading instructions for the agent to echo back, no "please open the right file" boilerplate. Just your intent (as a markdown blockquote) followed by what Hover observed:

Change this element in my app:

> Make this button red and add a loading spinner on click

Element: <button> — "Add to cart"
Source of likely target: src/components/ShadcnButton.tsx:42:11
Ancestor sources (closer ancestors first):
  • <div> @ src/routes/Cart.tsx:71:6
  • <section> @ src/routes/Cart.tsx:64:4
  • <main> @ src/App.tsx:11:6
React component chain (innermost first): ShadcnButton → CartLineItem → Cart → App
Playwright selector: page.getByRole("button", { name: "Add to cart" })
Outer HTML:
  <button data-hover-source="src/components/ShadcnButton.tsx:42:11" class="btn-primary">Add to cart</button>

Two parts of this matter:

  • Likely-target descent — if you click a <div> wrapping a button, Hover auto-points the prompt at the inner button (it's almost always what you meant). The <div> itself appears as "Clicked" in the prompt so the agent has both anchors.
  • Ancestor chain catches wrapper-rendered hosts<StyledButton> renders a <button> from inside styled-components' source; Hover's transform can't reach into a library, so the element's own source stamp would point to library internals. But the DOM ancestor chain still carries the user's call site — typically the <div> that wraps <StyledButton> in your component. The agent reads the chain and lands on the right file. examples/basic-app/src/wrapper-lab.tsx exercises five wrapper shapes (bare host, styled-components, className-forwarding, multi-layer nested, Radix Slot/asChild) with measured findings recorded in the file header.

Clicking Fix mid-recording is allowed — Record pauses while the popover is open and resumes automatically when you close it (Submit or Cancel). The Record button is disabled during Fix so you can't accidentally end the paused session; Fix's Submit / Cancel is the only path back.

Quick start

You need two terminals on first run. Once Chrome and Vite are up, they stay running across many loops.

git clone https://github.com/Hyperyond/Hover.git
cd Hover
pnpm install
pnpm --filter basic-app exec playwright install chromium   # for `pnpm test:e2e` only
# Terminal 1 — basic-app on http://localhost:5173. Examples pass
# `autoLaunchChrome: true`, so this ALSO spawns a debug Chrome on port 9222
# (isolated profile under <tmpdir>/hover-chrome) navigated to the dev URL.
pnpm dev:example:basic-app
# Terminal 2 — run the AI smoke loop (CDP preflight → invoke claude → stream events)
pnpm smoke
# or with custom target + prompt:
pnpm smoke http://localhost:5173/ "log in then add a todo named 'verify hover'"

Or just open http://localhost:5173/ in the debug Chrome, click the ✨ floating button, and type into the widget.

Install

One command, zero global installs:

npx @hover-dev/cli add

The CLI detects your bundler (Vite / Astro / Nuxt / Webpack), reads your lockfile to pick the right package manager (pnpm / yarn / bun / npm), installs the matching Hover package as a dev dep, and AST-edits your config file. Idempotent — safe to re-run.

Force a specific bundler if detection picks wrong:

npx @hover-dev/cli add --vite      # vite-plugin-hover
npx @hover-dev/cli add --astro     # @hover-dev/astro
npx @hover-dev/cli add --nuxt      # @hover-dev/nuxt
npx @hover-dev/cli add --webpack   # webpack-plugin-hover

Preview without changing anything: npx @hover-dev/cli add --dry-run.

Or install the package manually
pnpm add -D vite-plugin-hover     # for Vite projects
# or `@hover-dev/astro`, `@hover-dev/nuxt`, `webpack-plugin-hover`

Then add the plugin/integration to your bundler config — see the per-package READMEs under packages/.

No .npmrc, no auth tokens. All packages are public on npmjs.com.

No .env to fill out either. Hover doesn't ship an LLM SDK; it shells out to whichever coding-agent CLI is on your PATHclaude (install) or codex (install). Whatever you're already logged into covers it.

Then just run your dev server:

pnpm dev

Open your dev URL in any Chrome. The ✨ launcher appears bottom-right and tells you what to do via its colour:

  • Blue — you're already in a debug Chrome. Click and chat.
  • Amber — no debug Chrome yet. Click and the widget launches one for you (isolated profile under <tmpdir>/hover-chrome, navigated to your dev URL), then prompts you to switch over.
  • Gray — a debug Chrome is running, but this window isn't it. Click to bring the right window to the front.

Prefer it to pre-warm Chrome at vite dev? hover({ autoLaunchChrome: true }). Prefer to start Chrome yourself? pnpm exec hover-chrome (or npx hover-chrome).

Use it in a React (Vite) project

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { hover } from 'vite-plugin-hover';

export default defineConfig({
  plugins: [
    react(),
    hover(),                 // 👈 add this line
  ],
});

That's the whole integration. vite dev as usual; open your app; click ✨. The launcher colour tells you what (if anything) it needs from you.

Verified specs that you save via the widget land in __vibe_tests__/ at your project root. Run them with npx playwright test. They import only @playwright/test and have no runtime dependency on Hover — so CI can run them with the widget completely disabled.

Use it in a Vue (Vite) project

// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { hover } from 'vite-plugin-hover';

export default defineConfig({
  plugins: [
    vue(),
    hover(),                 // 👈 add this line
  ],
});

Same flow. Vite dev server → debug Chrome → ✨.

Works the same in Svelte / Solid / Qwik / vanilla — anything whose Vite dev server actually runs user Vite plugins' transformIndexHtml. The plugin is framework-agnostic at that layer.

Astro has its own HTML pipeline that bypasses transformIndexHtml on .astro pages — use the @hover-dev/astro integration instead, which wraps the same service + widget bundle behind Astro's injectScript API.

Nuxt renders HTML through Nitro, not Vite, so transformIndexHtml is a no-op for Nuxt's SSR responses — use the @hover-dev/nuxt module, which pushes the widget into nuxt.options.app.head.script (Nitro inlines it into the SSR'd HTML).

Webpack-based projects (vanilla webpack-dev-server, Rspack, Rsbuild, legacy CRA via craco, legacy Vue CLI via configureWebpack) — use webpack-plugin-hover, which taps HtmlWebpackPlugin's alterAssetTagGroups hook.

Next.js ships Turbopack as the default bundler since Next 16 and Turbopack does not load webpack plugins. Users on next dev --webpack can wire webpack-plugin-hover manually (see the package README). A Turbopack-native @hover-dev/next is on the roadmap.

Plugin options

hover({
  port: 51789,             // local WebSocket port; auto-bumps if taken
  enabled: true,           // false to disable (default: only in dev mode)
  chromeDebugPort: 9222,
  agentId: 'claude',       // matches @hover-dev/core's agent registry
  model: 'sonnet',         // 'opus' costs ~5× — use sonnet for browser driving
  maxBudgetUsd: undefined, // hard $ ceiling per agent invocation; no default — use Stop in the widget
  sourceAttribution: true, // stamps data-hover-source="file:line:col" on host JSX elements;
                           // dev-only — set false to disable if another tool conflicts
});

The ten example apps

Each one is a real, runnable app under examples/ — together they cover both testing surfaces and bundler/framework integrations:

App Port Stresses
basic-app 5173 Login + counter + todos. Baseline smoke · Vite + React
e-commerce 5174 Long action chains: product list → cart → checkout, cross-tab payment popup · Vite + React
stock-registration 5175 ~50-field brokerage form with conditional reveals — AI form-fill on rich controls · Vite + React
canvas-paint 5176 DOM toolbar amidst <canvas> pixels — semantic selectors when snapshots are opaque · Vite + React
payment-provider 5177 Deliberately no Hover plugin — simulates a third-party origin in cross-tab flows · Vite
astro-app 5178 Astro 5 static smoke page — verifies @hover-dev/astro via injectScript
nuxt-app 5179 Nuxt 4 SSR smoke page — verifies @hover-dev/nuxt via app.head.script
next-app 5182 Next.js 16 App Router smoke page (Turbopack default) — verifies @hover-dev/next via withHover + instrumentation.ts + <HoverScript />
webpack-app 5180 Vanilla webpack 5 + webpack-dev-server, plain JS no React — verifies webpack-plugin-hover via alterAssetTagGroups
rn-web-app 5181 React Native Web — react-native imports aliased to react-native-web, compiled to DOM via Vite. Demonstrates RN Web is in scope (RN native is not)

Run any of them with pnpm dev:example:<name>.

How it works

┌────────────────┐   chat (WebSocket)   ┌──────────────────┐
│  Widget        │ ───────────────────▶ │  @hover/core     │
│  (Shadow DOM,  │ ◀─────────────────── │  Node service    │
│   in dev page) │   step events        │  (127.0.0.1)     │
└────────────────┘                      └────────┬─────────┘
                                                 │ spawn
                                                 ▼
                                        ┌──────────────────┐
                                        │  claude (CLI)    │
                                        │  --strict-mcp,   │
                                        │  --allowedTools  │
                                        │  mcp__playwright │
                                        └────────┬─────────┘
                                                 │ MCP
                                                 ▼
                                        ┌──────────────────┐
                                        │  Playwright MCP  │
                                        └────────┬─────────┘
                                                 │ CDP (port 9222)
                                                 ▼
                                        ┌──────────────────┐
                                        │  Your Chrome     │
                                        │  (existing tab)  │
                                        └──────────────────┘

Architecture and boundary constraints live in CLAUDE.md. Per-package internals in packages/core/README.md.

Built on the shoulders of

  • nexu-io/open-design — the Local CLI Agent First architecture. Hover doesn't bundle any AI runtime; it PATH-scans for whatever coding-agent CLI the developer already has installed (claude, today) and treats it as a sidecar. The "local daemon as the only privileged process, agent-as-teammate" worldview, the strict-sandbox-by-default posture, and the per-invocation USD budget cap are all direct inspirations. Open Design proved the loop end-to-end for a design surface; Hover applies it to a testing surface, with the deterministic Playwright spec as the artifact instead of an HTML/PDF.
  • Playwright Codegen — the deterministic spec is the artifact posture. AI authors are fashionable; AI runtime in CI is a recurring mistake. Hover keeps the artifact deterministic so CI never has to talk to a model.
  • Stagehand and Midscene — proved that an LLM can usefully drive a real browser at test time. Hover takes the same loop and shortens it: agent drives the browser once during authoring, then steps out.

If your favourite agent (codex, cursor-agent, aider, gemini, qwen-code, …) isn't yet supported, it's a one-file addition in packages/core/src/agents/registry.ts — PRs warmly welcome.

Roadmap

  • v0.0.1-poc — Phase 0 — end-to-end feasibility (claude -p drives Chrome via CDP) ✓
  • v0.1.x — Phase 1 — Vite plugin + chat UI + persistent service + Save as Spec ✓
  • v0.2.x — Phase 2 — multi-agent (claude + codex), dark widget v2, Result + Findings cards, custom tooltip, code-quality pass ✓
  • v0.3.x@hover-dev/next — Next.js 16+ Turbopack-native integration ✓. Three pieces — withHover(nextConfig, opts) wrapper for next.config.mjs, a <HoverScript /> Server Component for app/layout.tsx, and a register() helper for instrumentation.ts. The existing webpack-plugin-hover only covers next dev --webpack; this package is the Turbopack-native path. npx @hover-dev/cli add routes Next projects here automatically.
  • v0.4.xClick → Suggest fix prompt. ✓ Independent footer Fix button + element picker + intent popover + clipboard handoff. A Vite transform stamps data-hover-source="file:line:col" on every host JSX element (React 19 compatible — runs enforce: 'pre' so it sees JSX before @vitejs/plugin-react collapses it). The picker walks the DOM ancestor chain to catch wrapper-rendered hosts (styled-components, className-forwarding, multi-layer nested, Radix Slot/asChild — all five shapes verified against examples/basic-app/src/wrapper-lab.tsx). React component chain comes from _debugOwner. Vue / Svelte source-attribution is planned but not yet shipped.
  • v0.5.xMerged Record + Assert workflow + AI-compiled spec output. Three stages:
    • A ✓ — Record mode now contains a sub-toolbar with four modes: ● Record / ✓ Exists / ¶ Says / = Equals. Check sub-modes are one-shot and follow Playwright codegen's pattern. The hidden ⌥click=assert chord is gone — Record and Fix coexist via pause-insert-resume: clicking Fix mid-recording pauses capture, and recording resumes automatically when the Fix popover closes.
    • B planned — Record steps will carry the same source-attribution metadata as the Fix prompt (own data-hover-source + ancestor chain + _debugOwner chain), feeding C.
    • C planned — writeSpec.ts rewritten to call your local CLI agent (claude / codex) to AI-compile state.messages + state.assertions into a polished .spec.ts, falling back to the existing deterministic translateStep codegen on failure. Outputs are still standard @playwright/test files; the AI is an authoring-time aid, not a CI dependency.
  • v0.6.xVoice mode ✓. Push-to-talk speech input + spoken progress narration, fully browser-native (Web Speech API). 中文 / English autodetect across STT, TTS phrasing, and voice picker (prefers Siri / Premium / Google over legacy system voices). Chrome 139+ runs the recogniser on-device via SODA. Settings panel (⚙ in the header) lets the user mute narration; state persists across reloads. Zero service-side change — STT text feeds the existing {type:'command'} WS message, TTS reads off the existing {type:'event'} downstream. (you are here)
  • v0.7.xmulti-tab / cross-origin + more agents + Chrome extension.
    • Multi-tab / cross-origin flows (Stripe, OAuth, "Pay with PayHover") — examples/payment-provider already stresses the window.openpostMessage path, but the agent's handling of browser_tabs(list/select) is brittle in the wild.
    • More agents wired into the registrycursor-agent / aider / gemini-cli / qwen-code.
    • Chrome extension (drops the Vite-plugin dependency for non-Vite stacks).

v0.6.x is what you can use today.

Project status

🟢 v0.6.0 shipped. Dogfood-ready across all six host bundlers: Vite, Astro, Nuxt, Next.js (Turbopack), webpack 5, and React Native Web. v0.4–0.5 brought the Playwright-codegen-style sub-toolbar (Record / Exists / Says / Equals), a dedicated Fix prompt button (Fix enterable mid-recording — pauses capture, auto-resumes on close), and the Vite source-attribution transform. v0.6 adds Voice mode: push-to-talk STT + spoken step narration via the browser-native Web Speech API, 中文 / English autodetect, on-device on Chrome 139+, with a new ⚙ settings panel to mute.

Tracking issues at github.com/Hyperyond/Hover/issues.

Contributing

See CONTRIBUTING.md. TL;DR:

  • Node 22+ / pnpm 10+
  • Conventional Commits (enforced by commit-msg hook)
  • pnpm typecheck && pnpm test before pushing
  • Keep main runnable — speculative work on experiment/<name> branches

License

Apache-2.0 © Hyperyond

Yorumlar (0)

Sonuc bulunamadi