# Install

This page walks through getting Hover into a project you already have. For the absolute fastest path, the [Quick start](/docs/get-started/quick-start) is the shorter version of the same steps; come back here if anything goes sideways.

## Before you start

You need three things:

1. **Node 22+** on your `PATH`. `node --version` should print `v22.x` or higher.
2. **A supported bundler in your project** — Vite, Astro, Nuxt, Next.js 15 / 16, or Webpack 5 (incl. Rspack / Rsbuild / CRA / Vue CLI).
3. **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.

<Callout type="tip" title="Don't have an agent CLI yet?">

- **Claude Code** — `npm install -g @anthropic-ai/claude-code`, then `claude login`. Uses your Claude Pro / Max subscription.
- **OpenAI Codex** — `npm install -g @openai/codex`, then `codex login`. Uses your ChatGPT plan.

Either one works. You can switch between agents from the widget header any time.

</Callout>

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:

```bash
npx @hover-dev/cli setup
```

That single command:

1. Reads `package.json` and detects your bundler (Vite / Astro / Nuxt / Next / Webpack).
2. Sniffs your lockfile to pick the right package manager (pnpm / yarn / bun / npm).
3. Installs the matching Hover package as a **dev dependency** (`vite-plugin-hover`, `@hover-dev/astro`, `@hover-dev/nuxt`, `@hover-dev/next`, or `webpack-plugin-hover`).
4. Uses [magicast](https://github.com/unjs/magicast) to **AST-mutate your bundler config** so the plugin is registered.
5. Is **idempotent** — running it twice is a no-op.

### Preview without changing anything

```bash
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`):

```bash
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.

<Callout type="tip" title="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](/docs/reference/plugin-options#about-the-debug-chrome-faq).

</Callout>

### Vite

```bash
pnpm add -D vite-plugin-hover
```

```ts
// 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.

```bash
pnpm add -D @hover-dev/astro
```

```js
// 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.

```bash
pnpm add -D @hover-dev/nuxt
```

```ts
// 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}`.

```bash
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.

```ts
// 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).

```ts
// 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.

```tsx
// 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>
  );
}
```

<Callout type="tip" title="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.

</Callout>

### Webpack 5 (including Rspack / Rsbuild / CRA / Vue CLI)

```bash
pnpm add -D webpack-plugin-hover
```

```js
// webpack.config.js
const Hover = require('webpack-plugin-hover');

module.exports = {
  // ... your config
  plugins: [
    new Hover({ autoLaunchChrome: true }),
  ],
};
```

<Callout type="warning" title="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.

</Callout>

## Monorepos (turbo / pnpm-workspace / yarn workspaces)

Hover's CLI knows about workspace monorepos. **Run from the repo root**, not from inside `apps/*`:

```bash
npx @hover-dev/cli setup
```

The CLI:

- Detects the monorepo from `pnpm-workspace.yaml`, the `workspaces` field in `package.json`, or `turbo.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:

```bash
npx @hover-dev/cli setup --cwd apps/web
```

Path is absolute or relative to where you ran the command.

<Callout type="tip" title="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.

</Callout>

<Callout type="tip" title="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.

</Callout>

A worked, committed example lives at [`examples/turbo-monorepo/`](https://github.com/Hyperyond/Hover/tree/main/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:

```bash
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 dev` whose 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](/docs/get-started/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:

```bash
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-run` to confirm the config has the plugin / integration.
- You ran `pnpm build` instead of `pnpm dev` — Hover is **deliberately a no-op in production builds**.
- For Next.js: forgot to add `<HoverScript />` to `app/layout.tsx`. The CLI prints this snippet at the end of `add`; if you missed it, see [Option B → Next.js](#next-js-15-16).

### 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](/docs/features/security) (MITM proxy + replay) to the same widget.
- `@hover-dev/cli` — what `npx @hover-dev/cli setup` runs. You don't need to install it explicitly; `npx` runs the latest published version on demand.

See [Plugin options](/docs/reference/plugin-options) for the full configuration surface (port, agent, model, budget, source-attribution, …).
