@extension.dev/mcp 4.8.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@
10
10
  "name": "extension-mcp",
11
11
  "source": "./",
12
12
  "description": "MCP tools for browser extension development: scaffold from 60+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox.",
13
- "version": "4.8.0",
13
+ "version": "5.1.0",
14
14
  "category": "development",
15
15
  "author": {
16
16
  "name": "Cezar Augusto"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "extension-mcp",
3
3
  "description": "MCP tools for browser extension development: scaffold from 60+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox. Ships /extension, /extension-add, /extension-debug, and /extension-publish commands.",
4
- "version": "4.8.0",
4
+ "version": "5.1.0",
5
5
  "author": {
6
6
  "name": "Cezar Augusto",
7
7
  "email": "boss@cezaraugusto.net",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,183 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.1.0
4
+
5
+ The engine closed its entire open bug range (Extension.js 61-73) in the
6
+ 4.0.14 canary line. This release re-aligns the MCP with the fixed engine,
7
+ finishes the MCP-side half of those bugs, and continues the
8
+ report-failure-not-false-success program that 5.0.0 started. 5.0.0 was never
9
+ published to npm; installing 5.1.0 picks up both.
10
+
11
+ ### Fixed
12
+
13
+ - **Sessions now genuinely survive the MCP process.** `detached: true` alone
14
+ never did it: the child held pipes to the MCP, so when the MCP exited the
15
+ next compile log line killed the dev server with EPIPE. Launch tools
16
+ (`extension_dev`/`start`/`preview`) now stream the child's output to a
17
+ session log file (returned as `logPath`) instead of pipes. A detached
18
+ session outlives the MCP and a fresh MCP process rediscovers it through
19
+ `ready.json` and can stop it. Pinned by a detach-contract test.
20
+ - **`extension_preview` no longer reports `launched` for a process that died
21
+ in seconds.** It health-checks the child like `dev`/`start` (the MCP half of
22
+ engine bug 72), and all three launch tools read the engine's new
23
+ `browser_exited` stamp, so a browser that dies after launch (for example a
24
+ rejected add-on) returns `status:"browser-exited"` instead of success.
25
+ - **`extension_doctor` names a dead browser.** A `browser_exited` ready
26
+ contract now produces a runtime-errors failure that says the browser died,
27
+ with the matching remedy, instead of the generic "fix the build error"
28
+ wording that pointed at a build that was fine.
29
+ - **`extension_create` verifies the scaffold.** A resolved create over a
30
+ partial tree (an interrupted template download) returned `nextSteps`
31
+ pointing at a project that could not compile. It now checks the manifest
32
+ exists and returns `status:"incomplete"` when it does not.
33
+ - **`extension_manifest_validate` is per-target honest.** `chromium:`/
34
+ `firefox:` prefixed keys resolve per target, `edge` joins the default
35
+ matrix, `manifest_version` must be 2 or 3, a `default_locale` without its
36
+ `_locales` catalog blocks, and a missing 128px store icon warns
37
+ (`extension_inspect` reports `has128Icon`).
38
+ - **Stale state stops being served as live.** `extension_logs` stamps
39
+ `stale:true` when the producing session is dead or from a different run;
40
+ `extension_wait` returns `runtimeErrors` alongside ready instead of a bare
41
+ green over a crashing worker; `extension_build` reports
42
+ `productionDivergence` when the production manifest lost permissions or
43
+ resources relative to source.
44
+ - **`extension_open`'s `asTab` fallback fires on the user-gesture wall**, and
45
+ `extension_storage` set without a `key` answers in MCP vocabulary rather
46
+ than CLI flags.
47
+
48
+ ### Added
49
+
50
+ - **Structured bundler warnings on `extension_build`.** The engine now
51
+ persists its build summary to `dist/extension-js/<browser>/
52
+ build-summary.json` (the transport half of engine bug 73), and the tool
53
+ returns it as `buildWarnings` (with `buildWarningsTruncated` naming the
54
+ true count when the engine capped the list). Older engines simply omit the
55
+ field; nothing is scraped from stdout.
56
+ - **Popup-faithful headless rendering.** A popup rendered as a tab is now
57
+ sized like the real popup: the document's content size is measured over
58
+ CDP, clamped to Chrome's 25x25-800x600 popup bounds, and the window is
59
+ resized to it (reported as `renderedAsTab.popupBounds`). If the browser
60
+ does not verifiably honor the resize, the tool keeps saying "no popup
61
+ sizing" instead of implying fidelity. Note headless-new is one such
62
+ browser: it accepts `Browser.setWindowBounds` and changes nothing, so
63
+ headless sessions get the honest fallback, not a resized window. The
64
+ measurement also leaves `body`'s authored width alone; only the root takes
65
+ the temporary fit-content override, so a popup that sizes itself through
66
+ `body { width }` measures at its real width.
67
+ - **CI typechecks the tests.** `pnpm typecheck` covers `src/` and the test
68
+ tsconfig, wired into the CI matrix, so type drift between tools and their
69
+ tests cannot accumulate silently again.
70
+
71
+ ### Changed
72
+
73
+ - **Tool prose caught up with the fixed engine.** `extension_eval` and
74
+ `extension_dom_inspect` now advertise the surface contexts
75
+ (`popup`/`options`/`sidebar`/`devtools`) and override pages
76
+ (`newtab`/`history`/`bookmarks`) the engine's relay serves, needing no tab
77
+ id. The "content eval is known-broken" guard is version-honest: on
78
+ Extension.js >= 4.0.14 a null is the expression's real result, and the note
79
+ says so instead of condemning a repaired path. Firefox hints name every
80
+ working route.
81
+
82
+ A pass focused on a single question: when something has gone wrong, does the
83
+ tool say so? Five tools were reporting success over a failure. All five now
84
+ verify before they claim anything.
85
+
86
+ ### Breaking
87
+
88
+ - **`extension_build` refuses a broken build.** It runs the
89
+ `extension_manifest_validate` checks as a preflight and returns
90
+ `status:"blocked"` on build-blocking errors instead of shelling out to a build
91
+ it knows is broken. Pass `skipValidation: true` for the old behavior. It also
92
+ returns `success:false` with `status:"incomplete"` when the bundler exits 0 but
93
+ a declared entrypoint never reached `dist/`, because the browser refuses to
94
+ load that artifact. Non-blocking findings ride along as `manifestWarnings`.
95
+ - **Browser resolution defaults to `chrome`, not `chromium`.** A dead session
96
+ used to fall through to a blind default, so every call after a dev server
97
+ exited silently retargeted a browser the caller never ran. A dead session now
98
+ resolves to its own browser with `source:"stale"`.
99
+ - **`extension_open` renames `tab` to `target`.** The value is a CDP target id,
100
+ not a `chrome.tabs` id, and the old name invited callers to pass it straight
101
+ into tools that need a numeric tab id.
102
+
103
+ ### Fixed
104
+
105
+ - **`extension_doctor` no longer reports `healthy:true` over a crashing
106
+ extension.** Its runtime-error check read the wrong field, so every error row
107
+ in `logs.ndjson` collapsed to an empty string and was skipped. It now reads the
108
+ engine's `messageParts` payload, with an `errorName`/`stack` fallback, and
109
+ collapses a throw that repeats on every event.
110
+ - **`extension_dev` and `extension_start` no longer report `status:"started"`
111
+ for a server that already exited.** Both health-check the child process and
112
+ return `status:"exited"` with the exit code, signal, and the child's own output
113
+ as evidence.
114
+ - **`extension_open` no longer reports success for a navigation that failed.**
115
+ Navigating to a `chrome-extension://` origin is cross process and swaps the
116
+ render frame, so the pre-navigation session reported a stale error URL on
117
+ success and success on failure. It now confirms against a fresh target list.
118
+ This affected the `url` navigation path shipped in 4.9.0, not only the new
119
+ surface rendering.
120
+ - **`extension_open` targets the right extension.** A dev session also loads
121
+ Extension.js's own manager extension, and taking the first extension target
122
+ navigated against the wrong origin. The id is now derived from the dist path
123
+ the session actually loaded.
124
+
125
+ ### Added
126
+
127
+ - **Headless surface rendering.** `extension_open` accepts `asTab` for
128
+ `popup`/`options`/`sidebar`, rendering the surface document in a real tab so it
129
+ can be inspected where no window exists to host a popup. It is applied
130
+ automatically when a headless session refuses to open the surface, with a note
131
+ saying what was substituted.
132
+ - **Tab targeting by url.** `extension_eval` and `extension_dom_inspect` take a
133
+ `url` and otherwise default to the active tab, and `extension_dom_inspect`
134
+ gains `listTabs` for discovery. The engine gained this in 4.0.13; the tool
135
+ descriptions had been telling callers a numeric tab id was required.
136
+ - **Friendlier arguments.** `timeoutMs`, `lines`, `tabId`, `href` and
137
+ `browserName` fold onto their canonical names, `withConsole` accepts `true`,
138
+ and the input validator understands union types.
139
+ - **`extension_create` matches your package manager.** Hints and the engine
140
+ warning now use bun, pnpm or yarn when that is what the scaffold used, and the
141
+ warning reads the pin the scaffold actually wrote.
142
+
143
+ ## 4.9.0
144
+
145
+ A second pass from the persona swarm, closing the gaps 4.8.0 left and the top
146
+ new blockers it surfaced.
147
+
148
+ - **Honest `extension_manifest_validate`.** It now scans the project source for
149
+ permission-gated `chrome.*`/`browser.*` calls and flags any the manifest does
150
+ not declare, an API used without its permission is `undefined` at runtime and
151
+ crashes the context, the exact case where validate used to report `valid:true`.
152
+ The headline is now honest (`valid:false` + `buildBlocking:true` on any error),
153
+ and it accepts singular `browser` as an alias for `browsers`.
154
+ - **`extension_open` can navigate a tab.** Pass a `url` (Chromium, via CDP) to
155
+ drive a content-script test page, a `webNavigation` target, or the popup as a
156
+ page (`chrome-extension://<id>/popup.html`), the loop the surface-only open
157
+ could not do. `target` is accepted as an alias for `surface`.
158
+ - **`extension_stop` actually reaps the session.** It now terminates the dev CLI
159
+ and both browser families (gecko profile + chromium `--load-extension`, under
160
+ the project's dist) and refuses to report `stopped:true` while any survive.
161
+ - **`extension_wait` won't lie about a dead session.** A `ready.json` whose pid
162
+ is dead now returns `status:"stale"` instead of `ready`, so you don't walk into
163
+ a reload/eval that fails with a misleading control-channel error.
164
+ - **Dropped-channel errors name the real cause.** A `1006` / "no control channel"
165
+ now detects an exited dev server (stale ready.json + dead pid) and says so,
166
+ instead of asking "is the session started with allowControl?" when it was.
167
+ - **`extension_doctor`** surfaces recent error-level logs as a `runtime-errors`
168
+ check (so a background throwing on every event isn't `healthy:true`), keeps the
169
+ project-local engine version in project mode, and flags when that engine
170
+ differs from a pinned `EXTENSION_MCP_CLI_VERSION`.
171
+ - **`extension_build`** lists declared entrypoints in its success output, so a
172
+ content script no longer reads as "didn't build".
173
+ - **`extension_create`** forces non-interactive git (`GIT_TERMINAL_PROMPT=0`) so a
174
+ credential prompt can't hang the template download, retries once on a transient
175
+ network/timeout failure (cleaning the partial dir first), reports a download
176
+ failure as such instead of "choose a valid template name", and warns when the
177
+ scaffold's `extension@latest` pin will win over your pinned CLI.
178
+ - Eval/inspect error guidance now speaks MCP JSON args (`context`, `tab`, `url`)
179
+ instead of CLI flags.
180
+
3
181
  ## 4.8.0
4
182
 
5
183
  Dev-session ergonomics hardened from a 30-persona agent walk of the toolchain.
@@ -146,12 +324,12 @@ that removed nearly all friction a real MCP client hit.
146
324
  --browser=chromium --allow-control` `` becomes `extension_dev with
147
325
  { browser: "chromium", allowControl: true }`, and stray
148
326
  `--allow-control` / `--allow-eval` / `--browser=<x>` mentions become
149
- their tool-argument names. Result data is never touched only
327
+ their tool-argument names. Result data is never touched, only
150
328
  error/hint prose. Tool descriptions now name `allowControl` /
151
329
  `allowEval` directly, so agents no longer discover the gates by
152
330
  fuzzing the schema.
153
331
  - The no-channel error now names the session that IS running ("Active
154
- session browser(s) for this project: chrome pass that as `browser`"),
332
+ session browser(s) for this project: chrome, pass that as `browser`"),
155
333
  so an agent retargets instead of spawning a second, conflicting
156
334
  session. Same for the `extension_logs` follow miss.
157
335
  - `extension_list_extensions` / `extension_source_inspect` accept
@@ -187,7 +365,7 @@ Session lifecycle + determinism release. Tool count 27 -> 28.
187
365
  - CLI spawns are deterministic: dev/start/preview and the act tools now
188
366
  prefer the project's own `node_modules/.bin/extension`, falling back to
189
367
  `npx extension@<pinned>` where the pin derives from the vendored
190
- `extension-develop` version never a floating `latest`.
368
+ `extension-develop` version, never a floating `latest`.
191
369
  - Session registry keys are path-normalized, so a stop with an absolute
192
370
  path matches a session registered with a relative one.
193
371
  - Tests: registry suite now asserts against the exported `tools` array
@@ -262,9 +440,9 @@ this release graduates that line to stable and becomes `latest`.
262
440
  @extension.dev/skill pairing.
263
441
  - MIT license shipped; repository moved to extensiondev/mcp.
264
442
 
265
- # @extension.dev/mcp Changelog
443
+ # @extension.dev/mcp, Changelog
266
444
 
267
- ## Unreleased agent-bridge tools
445
+ ## Unreleased, agent-bridge tools
268
446
 
269
447
  Adds the MCP client surface for the Extension.js **agent bridge** (dev-time
270
448
  observe + act + inspect). All new tools shell out to the `extension` CLI verbs
@@ -274,32 +452,32 @@ a recent **`extension` CLI that ships the bridge verbs** (`logs`, `eval`,
274
452
 
275
453
  > ⚠️ **Release order:** publish this package ONLY after the `extension` /
276
454
  > `extension-develop` suite that ships those verbs is on npm. The published CLI
277
- > at the time of writing (`3.17.0`) does NOT have them publishing this package
455
+ > at the time of writing (`3.17.0`) does NOT have them, publishing this package
278
456
  > before the suite would ship tools that fail with "unknown command". Bump the
279
457
  > version + `extension-*` deps to that suite release, then publish.
280
458
 
281
459
  New tools (22 total):
282
460
 
283
- - **`extension_logs`** read/stream logs from every extension context
461
+ - **`extension_logs`**, read/stream logs from every extension context
284
462
  (background, content, popup/options/sidebar/devtools); filters
285
463
  `level`/`context`/`url`/`tab`/`since`, bounded `follow` window.
286
- - **`extension_eval`** evaluate an expression in a context (requires the dev
464
+ - **`extension_eval`**, evaluate an expression in a context (requires the dev
287
465
  session started with `--allow-eval`; MV3 service worker is CSP-gated).
288
- - **`extension_storage`** read/write `chrome.storage` (requires `--allow-control`).
289
- - **`extension_reload`** reload the extension or a tab (`--allow-control`).
290
- - **`extension_open`** open popup/options/sidebar (`--allow-control`).
291
- - **`extension_dom_inspect`** CDP-free DOM snapshot of content/page or an open
466
+ - **`extension_storage`**, read/write `chrome.storage` (requires `--allow-control`).
467
+ - **`extension_reload`**, reload the extension or a tab (`--allow-control`).
468
+ - **`extension_open`**, open popup/options/sidebar (`--allow-control`).
469
+ - **`extension_dom_inspect`**, CDP-free DOM snapshot of content/page or an open
292
470
  surface (popup/options/sidebar/devtools); `withConsole` merges recent logs.
293
- - **`extension_publish`** publish to extension.dev and return a shareable URL
471
+ - **`extension_publish`**, publish to extension.dev and return a shareable URL
294
472
  (auth-gated; requires `EXTENSION_DEV_TOKEN`).
295
- - **`extension_source_inspect`** gains **`deepDom`** pierce CLOSED shadow roots
473
+ - **`extension_source_inspect`** gains **`deepDom`**, pierce CLOSED shadow roots
296
474
  via CDP (Chromium only).
297
475
 
298
476
  Internal: `lib/act` (CLI shell-out helper), `lib/exec.runExtensionCli` (capture),
299
477
  `lib/cdp.getClosedShadowRoots`. Test infra aligned to the workspace vitest
300
478
  catalog.
301
479
 
302
- ## Unreleased login (auth tools)
480
+ ## Unreleased, login (auth tools)
303
481
 
304
482
  Adds the missing `login` flow so `extension_publish` no longer requires the user
305
483
  to mint and export `EXTENSION_DEV_TOKEN` by hand. Auth stays auth-AWARE: the
@@ -307,13 +485,13 @@ token lives in a local credentials file, never in the MCP process state or logs.
307
485
 
308
486
  New tools (25 total):
309
487
 
310
- - **`extension_login`** GitHub **device-code** flow (no local server; works
488
+ - **`extension_login`**, GitHub **device-code** flow (no local server; works
311
489
  headless). Two-phase: call with `project` (`<workspace>/<project>`) to get a
312
490
  code + URL, call again with the returned `deviceCode` to finish. On success it
313
491
  writes a project-scoped token to the credentials file. Never returns the token.
314
- - **`extension_whoami`** report the stored workspace/project and token expiry
492
+ - **`extension_whoami`**, report the stored workspace/project and token expiry
315
493
  without revealing the token.
316
- - **`extension_logout`** delete the local credentials file.
494
+ - **`extension_logout`**, delete the local credentials file.
317
495
 
318
496
  Token resolution for publish is now `EXTENSION_DEV_TOKEN` env **>** the
319
497
  credentials file (expired file tokens are ignored).
@@ -323,8 +501,8 @@ Credentials file (versioned, `0600`): `$XDG_CONFIG_HOME/extension-dev/auth.json`
323
501
 
324
502
  Platform endpoints this depends on (in `apps/www.extension.dev`):
325
503
 
326
- - `GET /api/cli/login/config` public GitHub OAuth client id + scope.
327
- - `POST /api/cli/login/exchange` trades a GitHub **user** token for a
504
+ - `GET /api/cli/login/config`, public GitHub OAuth client id + scope.
505
+ - `POST /api/cli/login/exchange`, trades a GitHub **user** token for a
328
506
  project-scoped access token after checking workspace membership. Modeled on
329
507
  `/api/oidc/exchange`; tokens are recorded so they stay revocable.
330
508
 
package/README.md CHANGED
@@ -41,7 +41,7 @@ Built on [Extension.js](https://extension.js.org), the open-source cross-browser
41
41
  claude mcp add extension-dev npx @extension.dev/mcp
42
42
  ```
43
43
 
44
- Or install it as a plugin the MCP server plus the `/extension`, `/extension-add`, `/extension-debug`, and `/extension-publish` commands in one step:
44
+ Or install it as a plugin, the MCP server plus the `/extension`, `/extension-add`, `/extension-debug`, and `/extension-publish` commands in one step:
45
45
 
46
46
  ```
47
47
  /plugin marketplace add extensiondev/mcp
@@ -123,11 +123,11 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
123
123
  | platform | `extension_release_promote` | Promote a build to a release channel, headless |
124
124
  | platform | `extension_deploy` | Submit to the Chrome, Firefox, and Edge stores through extension.dev |
125
125
 
126
- Browser-launching tools (`dev`, `start`, `preview`) shell out to the `extension` CLI the project's own `node_modules/.bin/extension` when present, otherwise `npx extension@<pinned>` at the version this package is verified against; everything else runs in-process.
126
+ Browser-launching tools (`dev`, `start`, `preview`) shell out to the `extension` CLI, the project's own `node_modules/.bin/extension` when present, otherwise `npx extension@<pinned>` at the version this package is verified against; everything else runs in-process.
127
127
 
128
128
  ## From preview to store
129
129
 
130
- The platform tools connect agents to [extension.dev](https://extension.dev): `extension_login` runs a GitHub device-code flow and stores a project-scoped token locally (never returned to the agent), `extension_publish` turns a build into a shareable preview URL, and `extension_release_promote` promotes a tested build to a release channel from CI or an agent session, no browser required. `extension_deploy` submits a built extension to the Chrome Web Store, Edge Add-ons, and Firefox AMO through extension.dev, which holds your store credentials and dispatches the release from your project's mirror CI it defaults to a dry run and store credentials are never tool arguments.
130
+ The platform tools connect agents to [extension.dev](https://extension.dev): `extension_login` runs a GitHub device-code flow and stores a project-scoped token locally (never returned to the agent), `extension_publish` turns a build into a shareable preview URL, and `extension_release_promote` promotes a tested build to a release channel from CI or an agent session, no browser required. `extension_deploy` submits a built extension to the Chrome Web Store, Edge Add-ons, and Firefox AMO through extension.dev, which holds your store credentials and dispatches the release from your project's mirror CI, it defaults to a dry run and store credentials are never tool arguments.
131
131
 
132
132
  ## The extension.dev stack
133
133
 
@@ -1,6 +1,6 @@
1
1
  # How the pieces connect
2
2
 
3
- This document explains how the three Claude integration layers the template, the Claude Code rules, and the MCP tools connect through the [examples](https://github.com/extension-js/examples) repo.
3
+ This document explains how the three Claude integration layers (the template, the Claude Code rules, and the MCP tools) connect through the [examples](https://github.com/extension-js/examples) repo.
4
4
 
5
5
  ## The examples repo is the backbone
6
6
 
@@ -154,7 +154,7 @@ MCP server calls extensionCreate() → same go-git-it flow as CLI
154
154
 
155
155
  1. **Single source of truth.** `templates-meta.json` is generated from the actual examples. No manual sync needed. Add a template to `examples/`, run `pnpm run generate`, and all three layers pick it up.
156
156
 
157
- 2. **The examples repo is the knowledge base.** The MCP server doesn't hard-code extension patterns it reads them from examples. This means new patterns (like `sidebar-claude`) are immediately available to Claude without updating the MCP server.
157
+ 2. **The examples repo is the knowledge base.** The MCP server doesn't hard-code extension patterns, it reads them from examples. This means new patterns (like `sidebar-claude`) are immediately available to Claude without updating the MCP server.
158
158
 
159
159
  3. **Graceful degradation.** Users who don't use MCP still benefit from CLAUDE.md. Users who don't use Claude Code still benefit from the template. Each layer works independently.
160
160
 
package/claude/CLAUDE.md CHANGED
@@ -1,4 +1,4 @@
1
- # extension.dev Claude Code Instructions
1
+ # extension.dev, Claude Code Instructions
2
2
 
3
3
  You are working on a browser extension project built with the [extension.dev](https://extension.dev) platform, a zero-config cross-browser extension framework.
4
4
 
@@ -23,11 +23,11 @@ The extension.dev platform ships 60+ templates in the [examples](https://github.
23
23
 
24
24
  | Surface | Vanilla | React | Vue | Svelte | AI |
25
25
  | -------------- | ------------ | ---------------- | ------------- | ---------------- | ---------------- |
26
- | Content script | `content` | `content-react` | `content-vue` | `content-svelte` | |
27
- | Sidebar | `sidebar` | `sidebar-shadcn` | — | | `sidebar-claude` |
28
- | Action popup | `action` | — | | | `action-chatgpt` |
29
- | New tab | `new` | `new-react` | `new-vue` | `new-svelte` | |
30
- | Full framework | `javascript` | `react` | `vue` | `svelte` | |
26
+ | Content script | `content` | `content-react` | `content-vue` | `content-svelte` | n/a |
27
+ | Sidebar | `sidebar` | `sidebar-shadcn` | n/a |, | `sidebar-claude` |
28
+ | Action popup | `action` | n/a |, | n/a | `action-chatgpt` |
29
+ | New tab | `new` | `new-react` | `new-vue` | `new-svelte` | n/a |
30
+ | Full framework | `javascript` | `react` | `vue` | `svelte` | n/a |
31
31
 
32
32
  **When recommending a template:**
33
33
 
@@ -56,7 +56,7 @@ A typical extension.dev project:
56
56
  ```
57
57
  my-extension/
58
58
  src/
59
- manifest.json # Required the source of truth
59
+ manifest.json # Required: the source of truth
60
60
  background.ts # Service worker (Chromium) / background script (Firefox)
61
61
  content/ # Content scripts
62
62
  scripts.tsx
@@ -151,16 +151,16 @@ export default {
151
151
  3. **Service workers vs background scripts.** Chromium uses `service_worker` (single file). Firefox uses `scripts` (array).
152
152
  4. **Environment variables.** Use `EXTENSION_PUBLIC_*` prefix for variables accessible in extension code. `import.meta.env.EXTENSION_PUBLIC_BROWSER` gives the current browser.
153
153
  5. **Asset imports.** Import images/fonts directly in your code. The build system handles bundling.
154
- 6. **CSS Modules.** Use `*.module.css` / `*.module.scss`. Never use the `?url` suffix for CSS module imports it breaks class name hashing.
154
+ 6. **CSS Modules.** Use `*.module.css` / `*.module.scss`. Never use the `?url` suffix for CSS module imports, it breaks class name hashing.
155
155
 
156
156
  ## When creating new extensions
157
157
 
158
158
  1. Check if an existing template matches the use case (see template catalog above)
159
159
  2. If yes: `npx extension@latest create my-ext --template=<slug>`
160
- 3. If no: start from `manifest.json` define what the extension needs
160
+ 3. If no: start from `manifest.json`, define what the extension needs
161
161
  4. Add entry points referenced by the manifest (background, content scripts, UI pages)
162
- 5. Install framework deps if needed (React, Vue, etc.) the framework auto-detects them
163
- 6. Run `npm run dev` the dev server handles the rest
162
+ 5. Install framework deps if needed (React, Vue, etc.), the framework auto-detects them
163
+ 6. Run `npm run dev`, the dev server handles the rest
164
164
 
165
165
  **Learning from examples:** When building a feature you haven't done before, read the source of a relevant template from the examples repo. The source for any template is at:
166
166
 
@@ -234,11 +234,11 @@ npm run dev -- --logs info --log-url "example.com"
234
234
 
235
235
  ### Triggering events without clicking (requires `--allow-control`)
236
236
 
237
- - `extension open action` fire the toolbar action (opens its popup, or replays `chrome.action.onClicked`).
238
- - `extension open command --name <cmd>` replay a `chrome.commands.onCommand` keyboard shortcut.
239
- - `extension_list_extensions` (MCP tool; no CLI verb) list extensions with a live context in the browser (Chromium, read-only).
237
+ - `extension open action`, fire the toolbar action (opens its popup, or replays `chrome.action.onClicked`).
238
+ - `extension open command --name <cmd>`, replay a `chrome.commands.onCommand` keyboard shortcut.
239
+ - `extension_list_extensions` (MCP tool; no CLI verb), list extensions with a live context in the browser (Chromium, read-only).
240
240
 
241
- These replay your captured listeners, so they work on Chrome and Firefox but carry **no user gesture**, so `activeTab` is not granted (the result reports `gesture: false`, plus a `warning` when the manifest declares `activeTab`). If you need a genuine-gesture click (activeTab granted), use [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp)'s `trigger_extension_action` (Chromium only) alongside this server.
241
+ These replay your captured listeners, so they work on Chrome and Firefox, but carry **no user gesture**, so `activeTab` is not granted (the result reports `gesture: false`, plus a `warning` when the manifest declares `activeTab`). If you need a genuine-gesture click (activeTab granted), use [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp)'s `trigger_extension_action` (Chromium only) alongside this server.
242
242
 
243
243
  ## Contributing templates to the examples repo
244
244
 
package/claude/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # extension.dev Claude Code Integration
1
+ # extension.dev, Claude Code Integration
2
2
 
3
3
  Drop-in instructions, rules, and example prompts for building browser extensions with the [extension.dev](https://extension.dev) platform using Claude Code.
4
4
 
@@ -11,10 +11,10 @@ claude/
11
11
  CLAUDE.md Drop-in Claude Code instructions for any extension project
12
12
  ARCHITECTURE.md How the template, CLAUDE.md, and MCP layers connect
13
13
  commands/
14
- extension.md /extension create, dev, build, add features, debug
15
- extension-add.md /extension-add add sidebar, popup, content script, etc.
16
- extension-debug.md /extension-debug live DOM/console inspection
17
- extension-publish.md /extension-publish store submission prep
14
+ extension.md /extension: create, dev, build, add features, debug
15
+ extension-add.md /extension-add: add sidebar, popup, content script, etc.
16
+ extension-debug.md /extension-debug: live DOM/console inspection
17
+ extension-publish.md /extension-publish: store submission prep
18
18
  rules/
19
19
  extension-dev.md Core rules: project structure, manifest, commands
20
20
  cross-browser.md Cross-browser manifest field mapping
@@ -61,9 +61,9 @@ Claude Code will automatically pick up the instructions and know how to:
61
61
 
62
62
  The [examples repo](https://github.com/extension-js/examples) publishes `templates-meta.json` as a nightly release asset. This file is the single source of truth for:
63
63
 
64
- - **CLAUDE.md** references it so Claude knows all available templates
65
- - **MCP tools** `extension_list_templates` fetches and queries it at runtime
66
- - **`extension create`** resolves template slugs to repo URLs via the same naming convention
64
+ - **CLAUDE.md**, references it so Claude knows all available templates
65
+ - **MCP tools**, `extension_list_templates` fetches and queries it at runtime
66
+ - **`extension create`**, resolves template slugs to repo URLs via the same naming convention
67
67
 
68
68
  When a new template is added to the examples repo, all three layers pick it up automatically.
69
69
 
@@ -7,8 +7,8 @@ Add a new feature surface to the current extension project. The user said: $ARGU
7
7
 
8
8
  ## Parse arguments
9
9
 
10
- - First argument: feature type one of: `sidebar`, `popup`, `content-script`, `background`, `newtab`, `options`, `devtools`
11
- - Second argument (optional): framework one of: `react`, `vue`, `svelte`, `preact`, `vanilla`. Default: detect from existing project, fall back to `react`
10
+ - First argument: feature type, one of: `sidebar`, `popup`, `content-script`, `background`, `newtab`, `options`, `devtools`
11
+ - Second argument (optional): framework, one of: `react`, `vue`, `svelte`, `preact`, `vanilla`. Default: detect from existing project, fall back to `react`
12
12
 
13
13
  ## Steps
14
14
 
@@ -18,7 +18,7 @@ Add a new feature surface to the current extension project. The user said: $ARGU
18
18
  - Detect the framework from existing dependencies in `package.json`
19
19
 
20
20
  2. **Get the reference pattern**
21
- If MCP tool `extension_add_feature` is available, use it it returns the exact manifest additions, files to create, and reference template.
21
+ If MCP tool `extension_add_feature` is available, use it. It returns the exact manifest additions, files to create, and reference template.
22
22
 
23
23
  If MCP tool `extension_get_template_source` is available, read the reference template source to get real implementation patterns.
24
24
 
@@ -37,17 +37,17 @@ Add a new feature surface to the current extension project. The user said: $ARGU
37
37
 
38
38
  4. **Create the files**
39
39
  For HTML-based features (sidebar, popup, newtab, options, devtools):
40
- - `src/<feature>/index.html` HTML entry with script tag
41
- - `src/<feature>/scripts.tsx` Framework mount point (or `.ts` for vanilla)
42
- - `src/<feature>/styles.css` Stylesheet
43
- - `src/<feature>/<Feature>App.tsx` Main component (non-vanilla only)
40
+ - `src/<feature>/index.html`, HTML entry with script tag
41
+ - `src/<feature>/scripts.tsx`, Framework mount point (or `.ts` for vanilla)
42
+ - `src/<feature>/styles.css`, Stylesheet
43
+ - `src/<feature>/<Feature>App.tsx`, Main component (non-vanilla only)
44
44
 
45
45
  For content scripts:
46
- - `src/content/scripts.ts` Entry point
47
- - `src/content/styles.css` Injected styles
46
+ - `src/content/scripts.ts`, Entry point
47
+ - `src/content/styles.css`, Injected styles
48
48
 
49
49
  For background:
50
- - `src/background.ts` Service worker / background script
50
+ - `src/background.ts`, Service worker / background script
51
51
 
52
52
  5. **Handle sidebar specifically**
53
53
  If adding a sidebar, also create/update `src/background.ts`:
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Debug a running extension inspect DOM, console, content script injection
2
+ description: Debug a running extension, inspect DOM, console, content script injection
3
3
  argument-hint: "[url] [selectors...]"
4
4
  ---
5
5
 
@@ -25,8 +25,8 @@ Debug the currently running extension dev session. The user said: $ARGUMENTS
25
25
 
26
26
  3. **Exercise event handlers (when the bug is in an action / command / shortcut)**
27
27
  If the session was started with `--allow-control`, fire the events a user would, without clicking:
28
- - `extension_open` with `surface: "action"` triggers the toolbar action (opens its popup, or replays `chrome.action.onClicked`).
29
- - `extension_open` with `surface: "command"` and `name: "<cmd>"` replays a `chrome.commands.onCommand` keyboard shortcut.
28
+ - `extension_open` with `surface: "action"`, triggers the toolbar action (opens its popup, or replays `chrome.action.onClicked`).
29
+ - `extension_open` with `surface: "command"` and `name: "<cmd>"`, replays a `chrome.commands.onCommand` keyboard shortcut.
30
30
  - Then re-inspect or read `extension_logs` to see what the handler did.
31
31
 
32
32
  **Caveat:** replay carries no user gesture, so `activeTab` is NOT granted. If the handler depends on `activeTab` (e.g. `chrome.scripting.executeScript` on the active tab, `captureVisibleTab`), the result includes `gesture: false` and a `warning`, and behavior differs from a real click. For a genuine-gesture click (activeTab granted), use chrome-devtools-mcp's `trigger_extension_action` (Chromium only) alongside this server.
@@ -37,16 +37,16 @@ Debug the currently running extension dev session. The user said: $ARGUMENTS
37
37
  Based on what you find, check for:
38
38
  - **"It didn't load"**: Check extension root count. If 0, content scripts may not be injecting. Check manifest `content_scripts` matches patterns and the target URL.
39
39
  - **Console errors**: Report top errors. Common ones:
40
- - `Uncaught TypeError` likely a missing import or wrong module format
41
- - `Content Security Policy` extension CSP blocking inline scripts
42
- - `chrome.runtime.lastError` API permission missing
40
+ - `Uncaught TypeError`, likely a missing import or wrong module format
41
+ - `Content Security Policy`, extension CSP blocking inline scripts
42
+ - `chrome.runtime.lastError`, API permission missing
43
43
  - **Wrong page**: Check if the content script `matches` pattern in manifest covers the target URL
44
- - **Shadow DOM empty**: Extension root exists but shadow content is empty likely a CSS or framework mounting issue
44
+ - **Shadow DOM empty**: Extension root exists but shadow content is empty, likely a CSS or framework mounting issue
45
45
 
46
46
  5. **Suggest fixes** based on the diagnosis
47
47
 
48
48
  ## Examples
49
49
 
50
- - `/extension-debug` inspect the default page target
51
- - `/extension-debug https://example.com` inspect a specific URL
52
- - `/extension-debug https://example.com #my-root .sidebar` inspect URL and probe selectors
50
+ - `/extension-debug`, inspect the default page target
51
+ - `/extension-debug https://example.com`, inspect a specific URL
52
+ - `/extension-debug https://example.com #my-root .sidebar`, inspect URL and probe selectors
@@ -9,27 +9,27 @@ You are helping build a browser extension with the extension.dev platform. The u
9
9
 
10
10
  Parse the user's intent from `$ARGUMENTS` and execute the matching action:
11
11
 
12
- ### "create <name>" or "new <name>" Scaffold a new extension
12
+ ### "create <name>" or "new <name>", Scaffold a new extension
13
13
 
14
14
  1. If MCP tool `extension_list_templates` is available, use it to find the best template matching the user's description (check for surface type, framework, and keywords)
15
15
  2. If not, check the template catalog: `curl -sL https://github.com/extension-js/examples/releases/download/nightly/templates-meta.json | jq '.templates[] | {slug, description, uiFramework, surfaces}'`
16
16
  3. Run `npx extension@latest create <name> --template=<best-match>`
17
17
  4. Report what was created and suggest `npm run dev`
18
18
 
19
- ### "dev" or "run" Start development
19
+ ### "dev" or "run", Start development
20
20
 
21
21
  1. Run `npm run dev` (or `npx extension dev`) in the project root
22
22
  2. Tell the user the browser will open with their extension loaded
23
- 3. Mention HMR is active changes will hot-reload
23
+ 3. Mention HMR is active, changes will hot-reload
24
24
 
25
- ### "build" Build for production
25
+ ### "build", Build for production
26
26
 
27
27
  1. Run `npm run build` (or `npx extension build`)
28
28
  2. After success, report the output in `dist/chrome/`
29
29
  3. If the user mentions "firefox" or "both", also build with `--browser=firefox`
30
30
  4. If they mention "zip" or "store", add `--zip`
31
31
 
32
- ### "add <feature>" Add a feature surface
32
+ ### "add <feature>", Add a feature surface
33
33
 
34
34
  1. If MCP tool `extension_add_feature` is available, use it to get the manifest additions and file list
35
35
  2. Otherwise, determine what's needed from the feature type:
@@ -40,14 +40,14 @@ Parse the user's intent from `$ARGUMENTS` and execute the matching action:
40
40
  - **background**: `background.service_worker` (Chromium) + `background.scripts` (Firefox)
41
41
  3. Create the files and update `src/manifest.json`
42
42
 
43
- ### "debug" or "inspect" Debug a running extension
43
+ ### "debug" or "inspect", Debug a running extension
44
44
 
45
45
  1. If MCP tool `extension_source_inspect` is available, use it with `include: ["html", "console", "extension_roots"]`
46
46
  2. If there's a URL mentioned, pass it as the target
47
47
  3. If there are CSS selectors mentioned, pass them as `probe`
48
48
  4. Report: injected HTML, console errors, extension root state
49
49
 
50
- ### "validate" Check manifest for issues
50
+ ### "validate", Check manifest for issues
51
51
 
52
52
  1. If MCP tool `extension_manifest_validate` is available, use it
53
53
  2. Otherwise, read `src/manifest.json` and check:
@@ -56,7 +56,7 @@ Parse the user's intent from `$ARGUMENTS` and execute the matching action:
56
56
  - Permissions: `sidePanel` present if `side_panel` is declared
57
57
  - Background: `service_worker` (Chromium) and `scripts` (Firefox) both present
58
58
 
59
- ### "template <query>" Search for a template
59
+ ### "template <query>", Search for a template
60
60
 
61
61
  1. If MCP tool `extension_list_templates` is available, use it with the query
62
62
  2. Otherwise, search the catalog JSON
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## How Claude should approach this
8
8
 
9
- 1. **Update manifest.json** add side panel config for both browsers:
9
+ 1. **Update manifest.json**, add side panel config for both browsers:
10
10
 
11
11
  ```json
12
12
  {
@@ -47,7 +47,7 @@
47
47
  }
48
48
  ```
49
49
 
50
- 4. **Create the sidebar UI** `src/sidebar/index.html`, `src/sidebar/scripts.tsx`, `src/sidebar/styles.css`
50
+ 4. **Create the sidebar UI**, `src/sidebar/index.html`, `src/sidebar/scripts.tsx`, `src/sidebar/styles.css`
51
51
 
52
52
  5. **Test both browsers:**
53
53
  ```bash