Development

Setup, WXT dev mode, load unpacked, four debugging entry points (popup / options / background / content), common commands, and distribution workflow

Prerequisites

  • pnpm ≥ 10.32 (root packageManager is locked)
  • Node.js ≥ 20
  • Chrome / Edge / Brave — any Chromium-based browser
  • Running backend: either pnpm dev:server (web flow, ws://localhost:8001/ws/browser) or pnpm dev:desktop (desktop flow, ws://127.0.0.1:48123)

Two ways to run the extension

pnpm dev:ext

WXT launches a dedicated Chrome profile, preinstalls the extension, and reloads on file changes:

  • Popup and options HTML pages get hot module replacement
  • Background service worker and content scripts auto-reload
  • The terminal logs each rebuild

First run may prompt for the Chrome binary path; persist it via a web-ext.config.ts if needed.

B — Load unpacked (real profile)

Use this path when you need real logins (Gmail, etc.) or to verify store-upload behavior.

pnpm build:ext
  1. Open chrome://extensions
  2. Enable Developer mode (top-right)
  3. Click Load unpacked and select apps/bua/.output/chrome-mv3/
  4. Pin the extension to the toolbar

After code changes: pnpm build:ext🔄 Reload on the extension card.

Pairing the extension

Run one backend and copy credentials into the extension’s Options.

BackendWhere to get serverUrl + pairingToken
Web (pnpm dev:server + pnpm dev:web)Log in, then visit /settings/browser-extension in the app
Desktop (pnpm dev:desktop)Same route, fetched via IPC from <userData>/browser-bridge-token

In the extension: Options → paste Server URL + Pairing token → Save. Popup should switch to Connected within a second.

Four debugging entry points

EntryHow to openWhat you see
PopupClick toolbar icon → right-click the popup → InspectReact render of session panel; kill switch events
Optionschrome://extensionsExtension options → F12Allowlist CRUD, config read / save / clear
Background SWchrome://extensions → find Zapvol → click the service worker linkWS connection state, CDP attach / detach, session state machine, agent logs
Content scriptOpen any page → F12 → Console → filter [zapvol]DOM helper logs, injected element lookups

The service worker may show inactive — this is normal MV3 behavior. Click the link to wake it and surface latest logs. Any inbound message to the extension also wakes it.

Common commands

CommandPurpose
pnpm dev:extWXT dev mode with HMR
pnpm build:extBuild .output/chrome-mv3/ (production, minified)
pnpm --filter @zapvol/bua build:firefoxBuild Firefox variant
pnpm --filter @zapvol/bua zipPackage .output/*.zip for distribution
pnpm --filter @zapvol/bua compileType check only (tsc --noEmit)
pnpm --filter @zapvol/bua lintESLint

Troubleshooting

SymptomLikely causeFix
Toolbar shows puzzle icon instead of Zapvol boltauto-icons didn’t run / stale buildRe-run pnpm build:ext; confirm .output/chrome-mv3/icons/ has 16/32/48/128
Popup shows “Connecting…” foreverServer URL or pairing token wrongDouble-check /settings/browser-extension; re-copy both values
chrome.debugger.attach failsDevTools open on same tab, or another debugger attachedClose DevTools; or target a different tab
Yellow debugger bar cannot be dismissedChrome enforced — feature, not bugWait for session to end or click Cancel in the bar
Agent tool returns domain_blocked unexpectedlyTarget domain is on the user’s blocklistRemove the domain from Options → Blocklist, or pick a different target (terminal — agent must not retry)
Chrome yellow-bar Cancel leaves actions stuckPre-v4 bug: attached set not cleared on onDetachFixed in v4: handleDebuggerDetached now calls debuggerController.detach(tabId) before ending the session
Service worker stays inactiveMV3 idle terminationClick the link in chrome://extensions to wake; verify via console logs
Tailwind classes not applyingMissing import "../../globals.css" in an entrypointCheck each main.tsx imports the global stylesheet
Extension cannot reach Electron desktop backendFirewall / loopback disabledConfirm ws://127.0.0.1:48123 reachable via a WS client; verify Electron logs for browser-bridge.server.listening

Distribution (three stages)

Do not skip stages. BUA extensions with debugger permission receive extra Chrome Web Store scrutiny; land the first two stages solidly before submitting.

StageProduced byDistributed viaAuto-update
1. Developmentpnpm dev:ext → unpackedchrome://extensions → Load unpackedManual reload
2. Internalpnpm --filter @zapvol/bua zipGitHub Release / internal channelUsers reinstall
3. PublicSame zipChrome Web Store ($5 registration + privacy policy + review 1–7d)Store handles

Privacy policy must make clear: the extension only issues debugger commands under user-explicit per-domain time-scoped sessions, no background telemetry of page content.

File-level rules

For “how to add a new action / entrypoint / capability” checklists, see .claude/rules/bua.md in the repo. That file is the enforceable source of truth for contributors; this page is orientation.

Was this page helpful?