Install
This page walks through getting Hover into a project you already have. For the absolute fastest path, the Quick start is the shorter version of the same steps; come back here if anything goes sideways.
Before you start
You need three things:
- Node 22+ on your
PATH.node --versionshould printv22.xor higher. - A supported bundler in your project — Vite, Astro, Nuxt, Next.js 15 / 16, or Webpack 5 (incl. Rspack / Rsbuild / CRA / Vue CLI).
- One coding-agent CLI installed and logged in. Hover spawns whichever you have on
PATH; it doesn't bundle an LLM and doesn't take API keys.
Don't have an agent CLI yet?
- Claude Code —
npm install -g @anthropic-ai/claude-code, thenclaude login. Uses your Claude Pro / Max subscription. - OpenAI Codex —
npm install -g @openai/codex, thencodex login. Uses your ChatGPT plan.
Either one works. You can switch between agents from the widget header any time.
No .env file, no .npmrc for npm auth — every Hover package is public on npmjs.com.
Option A — the zero-config CLI (recommended)
Run inside your project root:
npx @hover-dev/cli setup
That single command:
- Reads
package.jsonand detects your bundler (Vite / Astro / Nuxt / Next / Webpack). - Sniffs your lockfile to pick the right package manager (pnpm / yarn / bun / npm).
- Installs the matching Hover package as a dev dependency (
vite-plugin-hover,@hover-dev/astro,@hover-dev/nuxt,@hover-dev/next, orwebpack-plugin-hover). - Uses magicast to AST-mutate your bundler config so the plugin is registered.
- Is idempotent — running it twice is a no-op.
Preview without changing anything
npx @hover-dev/cli setup --dry-run
Prints what would be installed + which file would be edited, then exits clean. Useful when you're not sure what the CLI will pick.
Force a specific bundler
If auto-detect picks the wrong one (rare, but happens in projects with multiple bundlers in devDependencies):
npx @hover-dev/cli setup --vite
npx @hover-dev/cli setup --astro
npx @hover-dev/cli setup --nuxt
npx @hover-dev/cli setup --next
npx @hover-dev/cli setup --webpack
Option B — manual install
Skip the CLI entirely. You'll do exactly what the CLI does, by hand.
About `autoLaunchChrome: true` in the snippets below
autoLaunchChrome spawns Hover's isolated debug Chrome at dev-server boot — --remote-debugging-port=9222 with a clean profile under <tmpdir>/hover-chrome. Not your everyday browser. Hover never relaunches or touches your normal Chrome session.
Leave it false (the default) and the first ✨ widget click will prompt you to launch on demand instead. See Plugin options → autoLaunchChrome.
Vite
pnpm add -D vite-plugin-hover
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import hover from 'vite-plugin-hover';
export default defineConfig({
plugins: [
react(), // or vue() / svelte() / solid() / qwik()…
hover({ autoLaunchChrome: true }),
],
});
Astro 5+
Astro's HTML pipeline bypasses Vite's transformIndexHtml, so it needs its own integration shim.
pnpm add -D @hover-dev/astro
// astro.config.mjs
import { defineConfig } from 'astro/config';
import hover from '@hover-dev/astro';
export default defineConfig({
integrations: [hover({ autoLaunchChrome: true })],
});
Nuxt 4+
Nuxt renders HTML through Nitro (not Vite), so it needs a Nitro module.
pnpm add -D @hover-dev/nuxt
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@hover-dev/nuxt'],
hover: { autoLaunchChrome: true },
});
Next.js (15 / 16)
Three pieces because Next splits its dev-server lifecycle. Verified end-to-end on Next 15 + webpack, Next 15 + Turbopack, Next 16 + Turbopack, Next 16 + webpack — with any of next.config.{ts,mjs,js}.
pnpm add -D @hover-dev/next
1. Wrap your Next config — adds Hover's options-to-env serialisation. Pure config wrapper, no side effects, safe to run at next build too.
// next.config.ts
import { withHover } from '@hover-dev/next';
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
// your existing Next config
};
export default withHover(nextConfig, { autoLaunchChrome: true });
2. Register the runtime hook — Next's blessed init point. Fires on next dev / next start, NOT on next build (so no orphan service from CI).
// instrumentation.ts ← project root, OR under src/ if your app uses src/
import { register as registerHover } from '@hover-dev/next/instrumentation';
export async function register() {
await registerHover();
}
3. Render the widget script — add <HoverScript /> to your root layout. The CLI prints this exact snippet for you to paste because AST-editing user JSX is fragile.
// app/layout.tsx
import { HoverScript } from '@hover-dev/next';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<HoverScript />
</body>
</html>
);
}
Async server component
HoverScript is an async Server Component (React 19 / App Router renders these natively). It's a no-op in production builds — process.env.NODE_ENV !== 'development' returns null so nothing ships to your end users.
Webpack 5 (including Rspack / Rsbuild / CRA / Vue CLI)
pnpm add -D webpack-plugin-hover
// webpack.config.js
const Hover = require('webpack-plugin-hover');
module.exports = {
// ... your config
plugins: [
new Hover({ autoLaunchChrome: true }),
],
};
Next.js with `--webpack`?
If you're on Next and want the webpack code path (next dev --webpack), still use @hover-dev/next, not webpack-plugin-hover. @hover-dev/next covers both bundlers; the webpack plugin only covers vanilla webpack / Rspack setups.
Monorepos (turbo / pnpm-workspace / yarn workspaces)
Hover's CLI knows about workspace monorepos. Run from the repo root, not from inside apps/*:
npx @hover-dev/cli setup
The CLI:
- Detects the monorepo from
pnpm-workspace.yaml, theworkspacesfield inpackage.json, orturbo.json. - Enumerates declared workspaces (
apps/*,packages/*, explicit paths). - Looks for a supported bundler in each.
What happens next depends on how many apps matched:
| Match count | Behaviour |
|---|---|
| 0 | "No supported bundler" — you're at a monorepo root with only tooling; point the CLI at an app: --cwd apps/web |
| 1 | Installs into that workspace automatically. Tells you which one it picked. |
| 2+ in a TTY | Interactive picker (↑/↓ or j/k to move, Enter to select, Esc to cancel) |
| 2+ in CI / piped | Lists candidates and exits 1, asks you to re-run with --cwd <path> |
Skip auto-detect entirely and target a specific workspace:
npx @hover-dev/cli setup --cwd apps/web
Path is absolute or relative to where you ran the command.
Single root lockfile
Sub-workspaces under a turbo / pnpm-workspace setup almost never carry their own lockfile. Hover's CLI walks up the directory tree until it finds one, so a single root pnpm-lock.yaml correctly picks pnpm — not a fallback to npm.
Run dev however you already run it
After install, pnpm dev from the monorepo root (turbo run dev), pnpm --filter web dev, or cd apps/web && pnpm dev all behave the same — Next sees its app, the Hover service boots once per app, the widget injects into the served HTML. There's nothing turbo-specific to configure.
A worked, committed example lives at examples/turbo-monorepo/ — turbo + pnpm-workspace + two Next.js 15 apps + next.config.ts, exactly the shape that surfaced the v0.7.3 / v0.7.4 install bugs.
Verify the install worked
Start your dev server the way you already do:
pnpm dev # or npm run dev / yarn dev / bun dev / turbo run dev
You should see one or two new log lines from Hover. The first one always appears:
[@hover-dev/<bundler>] service ready · ws://127.0.0.1:51789 · agent=claude model=sonnet
If you set autoLaunchChrome: true, a second line appears as Hover pre-warms the isolated debug Chrome:
[hover] launching debug Chrome on :9222
Hover's debug Chrome is a separate, temp-profile Chrome — not your everyday browser. Different cookies, different sessions, no shared extensions. If 9222 already has a debug Chrome (e.g. from a previous
pnpm devwhose window you didn't close), Hover reuses it and skips the launch, which is why you'll only see the launch log once per Chrome lifetime.
If those are present, open your dev URL. The floating ✨ launcher appears in the bottom-right corner of every page. Click it; the panel slides up. That's it — install is done.
What the ✨ colour tells you on first click:
| Colour | Means | What to do |
|---|---|---|
| 🔵 Blue | You're already in a debug Chrome. | Click and start chatting. |
| 🟠 Amber | No debug Chrome yet. | Click; the widget spawns one (isolated profile under <tmpdir>/hover-chrome, port 9222), navigates it to your dev URL. Switch over. |
| ⚪ Gray | A debug Chrome is running but you're not in it. | Click to bring the right window to the front. |
The debug Chrome is completely separate from your everyday browser. Different profile dir, no shared cookies, no shared extensions. Hover never touches your normal Chrome session.
Skip ahead to First session to send your first prompt.
Troubleshooting
Couldn't detect a supported bundler in package.json
You ran the CLI from a directory whose package.json declares no bundler dep. Either:
- You're at a monorepo root and the actual app is in
apps/web— re-run with--cwd apps/web, or just run from the monorepo root (Hover will detect the workspaces). - Your project's bundler isn't in our list — open an issue, or pass an explicit
--vite/--next/ etc. if you're using one of the supported bundlers but have an unusual dep graph.
EADDRINUSE: address already in use :::5173 (or 5183, etc.)
Something else is on the port. Most often: a prior next dev / vite that didn't shut down cleanly. Kill it:
lsof -i :5173 -t | xargs kill # replace 5173 with your dev port
If lsof shows a stale Hover service on 51789–51798 too, kill those: lsof -i :51789 -t | xargs kill.
Widget doesn't appear in the page
Open browser devtools → Console. If you see a WebSocket connection error to ws://127.0.0.1:51789, the Hover service didn't boot. Common causes:
- The bundler integration wasn't registered. Re-run
npx @hover-dev/cli setup --dry-runto confirm the config has the plugin / integration. - You ran
pnpm buildinstead ofpnpm dev— Hover is deliberately a no-op in production builds. - For Next.js: forgot to add
<HoverScript />toapp/layout.tsx. The CLI prints this snippet at the end ofadd; if you missed it, see Option B → Next.js.
Next 15 + next.config.ts previously errored with ERR_PACKAGE_PATH_NOT_EXPORTED
Fixed in v0.7.3 (dual ESM + CJS build). Make sure you're on @hover-dev/next@>=0.7.3.
Next 15 instrumentation errored with Cannot find module './register-node.js'
Fixed in v0.7.4 (package-subpath specifier + opaque dynamic import that webpack can't stub). Upgrade to @hover-dev/next@>=0.7.4.
What gets installed
Whichever bundler shim you pick pulls these as transitive deps:
| Package | Purpose |
|---|---|
@hover-dev/core | Node service — agent invocation, Playwright CDP preflight, WebSocket bridge between the widget and the agent. |
@hover-dev/widget-bootstrap | Shared widget assets — every bundler emits a byte-identical widget bundle so behaviour stays uniform across Vite / Astro / Nuxt / Next / Webpack. |
vite-plugin-hover (or your bundler's shim — @hover-dev/astro, @hover-dev/nuxt, @hover-dev/next, webpack-plugin-hover) | Wires the service + widget into your dev server. |
Optional extras:
@hover-dev/security— adds Security testing mode (MITM proxy + replay) to the same widget.@hover-dev/cli— whatnpx @hover-dev/cli setupruns. You don't need to install it explicitly;npxruns the latest published version on demand.
See Plugin options for the full configuration surface (port, agent, model, budget, source-attribution, …).