- When working inside a workspace package, also follow that package's nested
AGENTS.md. - Use Node 22+ from
.nvmrcandpnpm@10.33.4frompackageManager; CI builds extension packages on Node 24 and docs on Node 22. - Install with
pnpm install. The workspace is onlypackages/*andapps/*.
pnpm buildruns onlypackages/*(shared,chrome-extension,firefox-extension) in dependency order; it does not build docs.pnpm packruns each extension'sbuild:zipand writes ignored zips underpackages/*-extension/release/.- PR-like verification is
pnpm build && pnpm pack; addpnpm build:docswhen docs changed. pnpm devwatches only extension packages; usepnpm dev:chrome,pnpm dev:firefox,pnpm dev:shared, orpnpm dev:docsfor focused watches.pnpm build:chromeandpnpm build:firefoxdo not buildshared; from a clean tree or after shared changes, runpnpm build:sharedfirst.- There is no root lint/test/typecheck script and no repo-local tests. Lint package TS with
pnpm -r --aggregate-output --filter='./packages/*' lint. - For focused lint in interactive
zsh, quote filters:pnpm --filter='./packages/chrome-extension' lint.
packages/sharedexports runtime helpers imported by both extensions as@vue-devtools-unlocker/shared; its packagemainisbuild/main.js.- Webpack aliases
@to each package's ownsrc, so@/...is not a repo-root alias. - Chrome and Firefox source trees are mostly duplicated; update both unless the browser difference is intentional.
- Known intentional browser differences: copied manifest, manifest background shape (
service_workervsscripts), zip suffix, andbackground.tsallowed-site checks (Chrome waits forchangeInfo.status === 'complete'; Firefox checks any tab update). - Root
public/holds shared HTML/assets pluschrome-manifest.jsonandfirefox-manifest.json; extension webpack copies the selected browser manifest tobuild/manifest.json. - The runtime flow is background allowed-site check -> content script injects
injectedScript.js-> shared helpers unlock Vue DevTools -> popup displays the stored tab status; options editschrome.storage.sync.allowedSites. - Docs live in
apps/docs; VitePress uses/vue-devtools-unlocker/unlessVERCELis set, and the docs nav version comes frompackages/chrome-extension/package.json. - Release versions are duplicated in
packages/*-extension/package.jsonandpublic/*-manifest.json; zips readnameandversionfrom builtmanifest.json.
- Extension package configs are ESM because their package.json has
"type": "module";packages/shared/config/*is CommonJS. - Package
lintscripts run ESLint only onsrc/; packageformatscripts run Prettier overconfig,public, andsrc. - Husky pre-commit calls
npx lint-staged, andlint-staged.config.jsrunsbiome check --writefor stagedpackages/**/*.{ts,js}. lint-stagedis not inpackage.jsonorpnpm-lock.yaml;pnpm exec lint-stagedfails unless that dependency is added.- Generated
build/,release/, andapps/docs/.vitepress/{cache,dist}/are ignored outputs.