CLI

@hover-dev/cli is the zero-install Hover CLI. Exposed as the hover bin once installed.

npx @hover-dev/cli setup

setup reads your package.json to pick the right Hover integration (Vite / Astro / Nuxt / Next / Webpack), sniffs your lockfile to pick the package manager (pnpm / yarn / bun / npm), spawns the install command, then uses magicast to AST-mutate your bundler config.

Commands

CommandWhat it does
setupInstall + wire the integration into your bundler (detailed below).
run "<prompt>"Drive the debug Chrome from the terminal — no widget. --save <slug> crystallizes a spec. See CLI mode.
optimize <spec>The optional AI optimization pass — propose an improved spec (candidate + diff, original kept).
extractLift flows repeated across specs into shared Page Objects + fixtures.
re-record <spec>Regenerate a spec against the current UI (replays its Original prompt:).

run is the CLI-only authoring path; the others post-process specs you've already saved — the same operations the widget's Save / Optimize / Re-record do.

hover run (CLI mode)

Drive Hover entirely from the terminal — no widget, no DOM injection. Useful when you'd rather not (or can't) inject the widget into a page: scripting, non-bundler projects, or terminal preference.

hover run "test the login flow" --url http://localhost:5173 --save login
  • --url <devUrl> — the page to open / drive (picks the matching tab).
  • --save <slug> — crystallize the verified run into __vibe_tests__/<slug>.spec.ts. Omit it to just watch the run.
  • --agent <id> / --model <m> — override the agent (default claude) / model (default sonnet); HOVER_AGENT / HOVER_MODEL env vars work too.

It needs only @hover-dev/coreno setup, no bundler config (setup exists to inject the widget; CLI mode doesn't use it):

npm i -D @hover-dev/core @hover-dev/cli

hover run auto-launches the isolated debug Chrome if one isn't already up (the same persistent profile the widget uses), then drives it over CDP. It is not headless — it's a real, visible Chrome you log into once; the first run on a flow that needs auth asks you to log in and re-run, later runs reuse the session. After --save, polish it with hover optimize <slug>; the spec runs in CI with no agent.

What CLI mode does not cover (these need the in-page widget): Record mode, the Fix prompt, and voice.

setup flags

--vite              Force the Vite integration (vite-plugin-hover)
--astro             Force the Astro integration (@hover-dev/astro)
--nuxt              Force the Nuxt integration (@hover-dev/nuxt)
--next              Force the Next integration (@hover-dev/next)
--webpack           Force the Webpack integration (webpack-plugin-hover)
--cwd <path>        Target a specific workspace (monorepos). Absolute or
                    relative to where you invoked the CLI. -C is the short form.
--dry-run           Preview the install + config edits without applying them

Monorepo support

Recognised shapes: pnpm-workspace (pnpm-workspace.yaml), npm/yarn workspaces (workspaces field), turbo (turbo.json).

Run the CLI from the repo root:

npx @hover-dev/cli setup

The CLI enumerates the declared workspaces and detects bundlers in each.

  • Exactly one match — dispatches automatically. The CLI installs the Hover package into that workspace and edits its config file (not the root).
  • Multiple matches in a TTY — an interactive picker appears. ↑/↓ (or j/k) to move, Enter to confirm, Esc / q / Ctrl-C to cancel.
  • Multiple matches in CI / piped invocation — the CLI prints the candidates and exits 1; re-run with --cwd apps/web (or whichever workspace path).
  • No match — the CLI tells you it's a monorepo root with no supported bundler in any declared workspace, and points you at --cwd.

You can always skip detection and target one app directly:

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

Run the CLI once per app you want to wire. There is no --all mode by design — each install gets independent install / mutate failure modes you can react to.

The package manager is detected by walking up from the target workspace until it finds a lockfile, so a pnpm-managed monorepo with a single root pnpm-lock.yaml works without surprise — sub-workspaces don't need their own lockfile.

Idempotency

Running npx @hover-dev/cli setup twice on the same project no-ops the second time. Safe to put in a setup script.

Detection priority

Frameworks are matched in this order so a project whose dep tree legitimately contains a lower-priority framework still routes to the right shim:

  1. astro
  2. nuxt
  3. next — checked before webpack so Next projects (Turbopack default since Next 16) route to @hover-dev/next, not webpack-plugin-hover.
  4. webpack — matches on webpack-cli (the user-facing dep), not a transitive webpack (every Vite project has webpack somewhere).
  5. vite — catch-all for Vite-based projects that aren't Astro / Nuxt / Svelte.

An explicit --<framework> flag overrides detection entirely.

Next.js: two-file mutator + one manual step

For Next, the CLI does two file edits:

  • Wraps the user's next.config.{mjs,js,ts} export in withHover(...).
  • Creates (or merges into) instrumentation.ts at the project root or under src/, calling Hover's register() from inside the user's own register() hook.

It deliberately does not auto-edit app/layout.tsx. The <HoverScript /> insertion is printed as a one-liner for you to paste — AST-mutating user JSX invites whitespace drift and Server Component shape surprises.