@extension.dev/mcp 10.10.9 → 10.10.11

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.
Files changed (77) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +85 -1
  4. package/README.md +10 -10
  5. package/claude/ARCHITECTURE.md +13 -13
  6. package/claude/CLAUDE.md +11 -10
  7. package/claude/README.md +4 -4
  8. package/claude/commands/extension-debug.md +1 -1
  9. package/claude/commands/extension-publish.md +1 -1
  10. package/claude/commands/extension.md +1 -1
  11. package/claude/rules/cross-browser.md +4 -3
  12. package/claude/rules/mcp-tools.md +446 -1009
  13. package/dist/module.js +4621 -1501
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/lib/allowance.d.ts +1 -1
  16. package/dist/src/lib/artifacts-api.d.ts +1 -0
  17. package/dist/src/lib/boot-verdict.d.ts +5 -0
  18. package/dist/src/lib/bridge-tabs.d.ts +3 -1
  19. package/dist/src/lib/browser-family.d.ts +1 -0
  20. package/dist/src/lib/carrier-registry.d.ts +4 -0
  21. package/dist/src/lib/carrier.d.ts +10 -1
  22. package/dist/src/lib/cdp-connection.d.ts +2 -1
  23. package/dist/src/lib/cdp-devtools.d.ts +5 -0
  24. package/dist/src/lib/cdp-extension-page.d.ts +26 -2
  25. package/dist/src/lib/cdp-page-scripts.d.ts +2 -2
  26. package/dist/src/lib/cdp-port.d.ts +1 -1
  27. package/dist/src/lib/cdp.d.ts +13 -1
  28. package/dist/src/lib/common-schema.d.ts +1 -1
  29. package/dist/src/lib/create-answer.d.ts +20 -0
  30. package/dist/src/lib/credential-source.d.ts +25 -0
  31. package/dist/src/lib/credentials.d.ts +23 -0
  32. package/dist/src/lib/docs-tools.d.ts +9 -0
  33. package/dist/src/lib/engine-manifest-view.d.ts +1 -0
  34. package/dist/src/lib/envelope.d.ts +1 -1
  35. package/dist/src/lib/exec.d.ts +3 -0
  36. package/dist/src/lib/extension-identity.d.ts +7 -0
  37. package/dist/src/lib/first-build.d.ts +15 -0
  38. package/dist/src/lib/guest-load-oracle.d.ts +2 -1
  39. package/dist/src/lib/launch-flags.d.ts +2 -2
  40. package/dist/src/lib/match-patterns.d.ts +1 -1
  41. package/dist/src/lib/node-engine.d.ts +11 -0
  42. package/dist/src/lib/platform-hold.d.ts +1 -0
  43. package/dist/src/lib/process-identity.d.ts +5 -0
  44. package/dist/src/lib/process-manager.d.ts +5 -1
  45. package/dist/src/lib/project-manifest.d.ts +1 -0
  46. package/dist/src/lib/promote-outcome.d.ts +29 -0
  47. package/dist/src/lib/publish.d.ts +2 -0
  48. package/dist/src/lib/registry-access.d.ts +1 -0
  49. package/dist/src/lib/registry.d.ts +6 -1
  50. package/dist/src/lib/safari-automation.d.ts +2 -0
  51. package/dist/src/lib/session-browser.d.ts +5 -0
  52. package/dist/src/lib/session-paths.d.ts +1 -0
  53. package/dist/src/lib/store-review.d.ts +14 -2
  54. package/dist/src/lib/submit-outcome.d.ts +14 -0
  55. package/dist/src/lib/templates-cache.d.ts +13 -0
  56. package/dist/src/lib/types.d.ts +2 -1
  57. package/dist/src/lib/vendor/chrome-theme/chrome-theme-resolve.d.ts +1 -0
  58. package/dist/src/tools/assert.d.ts +4 -1
  59. package/dist/src/tools/create.d.ts +1 -0
  60. package/dist/src/tools/dev.d.ts +2 -2
  61. package/dist/src/tools/dom-snapshot.d.ts +1 -1
  62. package/dist/src/tools/eval.d.ts +1 -1
  63. package/dist/src/tools/inspect-gecko.d.ts +2 -1
  64. package/dist/src/tools/logs-filter.d.ts +6 -2
  65. package/dist/src/tools/open.d.ts +4 -1
  66. package/dist/src/tools/project-create.d.ts +1 -0
  67. package/dist/src/tools/reload.d.ts +1 -1
  68. package/dist/src/tools/start.d.ts +2 -2
  69. package/dist/src/tools/stop.d.ts +10 -0
  70. package/dist/src/tools/storage.d.ts +1 -6
  71. package/dist/src/tools/store-status.d.ts +4 -0
  72. package/extensions/live-preview/chromium/action/index.css +1 -1
  73. package/extensions/live-preview/chromium/action/index.js +1 -1
  74. package/extensions/live-preview/chromium/background/service_worker.js +98 -4
  75. package/extensions/live-preview/chromium/manifest.json +1 -1
  76. package/package.json +3 -2
  77. package/server.json +3 -3
@@ -10,7 +10,7 @@
10
10
  "name": "extension-mcp",
11
11
  "source": "./",
12
12
  "description": "MCP tools for browser extension development: scaffold from 50+ 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": "10.10.9",
13
+ "version": "10.10.11",
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 50+ 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": "10.10.9",
4
+ "version": "10.10.11",
5
5
  "author": {
6
6
  "name": "Cezar Augusto",
7
7
  "email": "hello@extension.dev",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,89 @@
1
1
  # Changelog
2
2
 
3
+ ## 10.10.11
4
+
5
+ The rest of the 2026-10-05 audit ledger, apart from the Safari WebDriver
6
+ fields that wait on the engine (entry 110h, Extension.js BUGS_TO_FIX 905).
7
+
8
+ - `extension_eval` says where it ran and what came back: the tab's url and
9
+ title on Firefox, a note when the value was not serializable, only real
10
+ background targets as the background, and `eval-lost` or
11
+ `eval-unsupported` when the answer never arrived. A woken worker is no
12
+ longer said to have idled when it may never have started.
13
+ - `extension_logs` and `extension_assert` report a cut stream: a follow
14
+ that closed early is a partial read, dropped-line markers are not
15
+ counted as events, and console-errors-empty is inconclusive when lines
16
+ were dropped. An unknown console `context` is refused as a bad request
17
+ instead of failing the whole call.
18
+ - `extension_wait` and `extension_start` report only what they observed:
19
+ a start session is `build-ready`, a build contract or a stopped session
20
+ is `no-session`, and start refuses Safari and preview-path hosts it
21
+ cannot serve.
22
+ - `extension_open` names the DevTools panel frame that appeared, and says
23
+ when the panel registry could not be read or the target was inferred.
24
+ - Platform answers of the wrong shape (channels, build index, shares,
25
+ login config) are unreadable, never empty, and an unpinned publish
26
+ matches the build the platform named.
27
+ - `extension_stop` counts a process as reaped only once it is gone, and
28
+ ends a Windows session through `taskkill /T /F`. A session marker that
29
+ could not be written is a warning on the started answer, and the
30
+ `release promote` command exits non-zero on an answer it cannot read.
31
+ - `extension_list_extensions` on Firefox marks a lone temporary add-on as
32
+ an inferred match.
33
+ - The scheduled test tier builds through the real pinned engine with
34
+ `--output json` and checks the fixtures against what it writes.
35
+
36
+ ## 10.10.10
37
+
38
+ Every sentence the server says is now backed by something it read
39
+ (BUGS_TO_FIX_MCP.md entries 45 to 112, two audits of 2026-10-05: a claims
40
+ census of about 2,030 sentences and a fixture sweep against the pinned
41
+ engine and the platform).
42
+
43
+ - Success is read, never assumed. Promote, submit, publish, project and
44
+ workspace create, logout and uninstall read the platform's or the
45
+ library's own answer and say `promoted-partially`, `submit-unconfirmed`,
46
+ `publish-unconfirmed`, `create-unconfirmed`, `not-installed` and the like
47
+ when it falls short. A failed read is reported as unreadable, never as an
48
+ empty list, across eval, open, the tab polls, session markers and
49
+ carriers.
50
+ - One resolver returns the token and the project it belongs to. An
51
+ unnamed call sends `EXTENSION_DEV_TOKEN` and takes its project from the
52
+ token's own claims, never from whichever stored login is active; a named
53
+ project sends its stored login first, the private registry grant
54
+ included.
55
+ - `extension_manifest_validate` judges each browser through the engine's
56
+ own prefix filter, checks every requested browser's references, refuses
57
+ an unknown target, and blocks only where the engine or the browser
58
+ refuses (a `service_worker` the engine rewrites for Firefox is a
59
+ warning).
60
+ - `extension_build` reads `zip_artifacts`, refuses a stale dist, reports a
61
+ timeout as `build-timeout`, uses the engine's own bundle-id rule, and
62
+ writes `firefox-based` builds where the engine does (`dist/gecko-based`).
63
+ - `extension_inspect` names the document it read after navigating, counts
64
+ uncaught exceptions as console errors, reports a section that threw as
65
+ `failedSections` instead of an empty value, and marks every cap.
66
+ - `extension_open` checks popup, options and sidebar against the manifest
67
+ before asking the engine, says when an open could not be confirmed, and
68
+ never counts a tab it rendered itself as the window.
69
+ - `extension_storage` reads a set back; `context` is gone, since the engine
70
+ runs every storage call in the background.
71
+ - `extension_assert` counts only the extension's own log lines, reads the
72
+ guest's id from the contract, compares storage values structurally, and
73
+ does not credit a background the dev build injected.
74
+ - `extension_stop` with `all` leaves sessions owned by another running
75
+ server alone unless `includeOtherServers` is true; stop and auth are
76
+ marked destructive.
77
+ - `extension_dev` reports the control channel from `ready.json`, and a boot
78
+ error that is not a compile error answers `boot-failed`.
79
+ - The tool reference `claude/rules/mcp-tools.md` is generated from the
80
+ schemas, and a test validates every example call in the docs against
81
+ them.
82
+ - Requires Node 22.12 or later, the floor of the engine this package runs
83
+ in-process.
84
+ - The release workflow publishes to npm before it pushes the version
85
+ commit and tag, so a failed publish no longer strands a tag.
86
+
3
87
  ## 10.10.9
4
88
 
5
89
  - One approval now covers several projects in one workspace
@@ -114,7 +198,7 @@
114
198
  of an extension whose policy forbids eval. Use `context: "page"` or
115
199
  `extension_dom_snapshot` there.
116
200
 
117
- - `extension_submit` and `extension_store_status` link to the console's
201
+ - `extension_submit` and `extension_release_status` (include: ["stores"]) link to the console's
118
202
  Submissions tab at `/<workspace>/<project>/submissions`, where the page
119
203
  moved; the old `/stores` address still redirects. `@extension.dev/urls`
120
204
  moves to `^0.8.2`, which carries the new paths.
package/README.md CHANGED
@@ -29,7 +29,7 @@ These tools give agents eyes on the live browser, so they debug from evidence in
29
29
  - **Run** the dev server with HMR in Chrome, Edge, Firefox, Brave, Opera, Vivaldi, Yandex, Waterfox, LibreWolf, Zen, Floorp, or any Chromium- or Gecko-based binary, plus Safari on macOS (no HMR yet), no build config
30
30
  - **See** the live DOM, unified logs from every extension context, `chrome.storage` contents, and the loaded-extension list
31
31
  - **Act**: evaluate code in any context, trigger the action button and commands, reload the extension, replay events
32
- - **Ship**: validate the manifest cross-browser, build for production, publish a shareable preview, and promote builds to release channels headlessly
32
+ - **Ship**: validate the manifest cross-browser, build for production, publish a shareable preview, and promote builds to release channels (a stable promotion asks for a human approval first)
33
33
 
34
34
  Built on [Extension.js](https://extension.js.org), the open-source cross-browser extension framework.
35
35
 
@@ -146,12 +146,12 @@ npx @extension.dev/mcp login --project <workspace>/<project>
146
146
 
147
147
  Two flags (or environment variables) narrow the server before an agent sees it:
148
148
 
149
- - `--features=local` exposes only the tools that work on this machine (create, run, inspect, build), which also cuts the tool list by about 40%. `--features=platform` exposes only the extension.dev account, share, release and store tools. Both are on by default. Env: `EXTENSION_DEV_FEATURES`.
150
- - `--no-ship` keeps everything that stays on this machine and refuses every call that reaches other people: `extension_publish`, `extension_release_promote`, `extension_submit` with `dryRun: false`, `extension_preview_web` with `share: true`, and a share revoke. Dry runs and share listing still work. Env: `EXTENSION_DEV_NO_SHIP=1`.
149
+ - `--features=local` exposes the tools that work on this machine (create, run, inspect, build, plus docs search), which leaves 23 of the 32 tools (the 9 platform tools are off). `--features=platform` exposes only the extension.dev account, share, release and store tools. Both are on by default. Env: `EXTENSION_DEV_FEATURES`.
150
+ - `--no-ship` refuses the calls that put something in front of other people: `extension_publish`, `extension_release_promote`, `extension_submit` with `dryRun: false`, `extension_preview_web` with `share: true`, and a share revoke. Dry runs, share listing, login and project or workspace creation still work. Env: `EXTENSION_DEV_NO_SHIP=1`.
151
151
 
152
152
  A refused call answers `E_TOOL_DISABLED` with the flag to change.
153
153
 
154
- A real store submission, a promotion to stable and a share revoke also wait for a person by default: the first call answers `approval-required` with a link on extension.dev, a workspace member approves exactly that action, and the same call with the returned `approvalId` runs it once. `EXTENSION_DEV_APPROVAL_GATE=1` extends this to every promotion; `EXTENSION_DEV_APPROVAL_GATE=0` turns it off.
154
+ A real store submission, a promotion to stable and a share revoke also wait for a person by default: the first call answers `approval-required` with a link on extension.dev, a workspace member approves exactly that action (a store submission needs a workspace owner), and the same call with the returned `approvalId` runs it once. `EXTENSION_DEV_APPROVAL_GATE=1` extends this to every promotion; `EXTENSION_DEV_APPROVAL_GATE=0` turns it off.
155
155
 
156
156
  Every tool also carries MCP annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`), so clients can auto-approve reads and ask before the rest.
157
157
 
@@ -222,12 +222,12 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
222
222
  | platform | `extension_project_create` | Create the extension.dev project for a built extension, or several under one approval, headless, via device approval |
223
223
  | platform | `extension_preview_web` | Render a build in the web emulator, and share it as a link |
224
224
  | platform | `extension_shares` | List every link you have shared, and revoke one permanently |
225
- | platform | `extension_publish` | Publish a shareable preview to extension.dev |
225
+ | platform | `extension_publish` | Mint a shareable link for a build extension.dev already holds (nothing is uploaded) |
226
226
  | platform | `extension_release_promote` | Promote a build to a release channel, headless |
227
- | platform | `extension_submit` | Submit for store review: Chrome, Firefox and Edge, through extension.dev |
227
+ | platform | `extension_submit` | Submit for store review: Chrome, Firefox, Edge and Safari, through extension.dev |
228
228
  | platform | `extension_release_status` | Read release channels, recent builds, and store submission and review state |
229
229
 
230
- Browser-launching tools (`dev`, `start`) 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.
230
+ Browser-launching tools (`dev`, `start`) 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; build, doctor, eval, storage, reload, open, dom_snapshot and assert spawn that CLI too, and the rest runs in-process.
231
231
 
232
232
  ## Asserting instead of guessing
233
233
 
@@ -286,8 +286,8 @@ and `extension_open` with `url` cannot open one on Safari: the bridge
286
286
  navigates through a background eval, and Safari's MV3 background CSP blocks
287
287
  eval, which also blocks `extension_eval` in `background`. Open the page in
288
288
  Safari by hand, then read it. Safari has no CDP or RDP, so
289
- `extension_inspect` has no Safari path and `surface-rendered` answers
290
- inconclusive, pointing at `extension_dom_snapshot` with a `context`.
289
+ `extension_inspect` has no Safari path; `surface-rendered` reads the
290
+ surface through the relay there and can pass or fail.
291
291
 
292
292
  Safari 27 and Safari Technology Preview 247 also ship Apple's own MCP server
293
293
  inside `safaridriver` (enable Safari > Settings > Developer > "Allow remote
@@ -304,7 +304,7 @@ Extension.js release records one, and that leg reads `skip`.
304
304
 
305
305
  ## Sharing a build in progress
306
306
 
307
- An unpacked extension is unusually hard to hand to someone: the only way to look at a colleague's work-in-progress has been to take their zip and run untrusted code with real browser permissions on your own machine. `extension_preview_web` with `share: true` uploads the `dist/` it just built and returns a link that renders those exact bytes in the emulator. Whoever opens it installs nothing and signs in to nothing, which is what lets a designer, a PM, or a reviewer into the loop at all. Those bytes run in an isolated sandbox origin or they do not run at all: preview refuses a shared build rather than serving it in its own renderer. Sharing needs auth (`extension_auth` or `EXTENSION_DEV_TOKEN`), the link lives 30 days, and `DELETE`ing the returned `revokeUrl` with the same token kills it early. Re-sharing an unchanged build returns that same link rather than a second one, and only a revoked link is replaced by a different one, because revocation is permanent: the address is burned and never resolves again. That makes `revokeUrl` the handle to the link you just made, so every share is also appended to `.extension.dev/shared-previews.json` in the project (gitignored) so it survives losing the tool output. The upload holds up to 2,000 files and about 64MB of text, or roughly 48MB when the build is mostly images, fonts or wasm, which travel base64-encoded. Without `share`, the tool returns a local-only deep link and uploads nothing.
307
+ An unpacked extension is unusually hard to hand to someone: the only way to look at a colleague's work-in-progress has been to take their zip and run untrusted code with real browser permissions on your own machine. `extension_preview_web` with `share: true` uploads the `dist/` it just built and returns a link that renders those exact bytes in the emulator. Whoever opens it installs nothing and signs in to nothing, which is what lets a designer, a PM, or a reviewer into the loop at all. Those bytes run in an isolated sandbox origin or they do not run at all: preview refuses a shared build rather than serving it in its own renderer. Sharing needs auth (`extension_auth` or `EXTENSION_DEV_TOKEN`), the link lives for the workspace plan's share window (30 days on Free, longer on Pro) and the answer carries its exact `expiresAt`, and `DELETE`ing the returned `revokeUrl` with the same token kills it early. Re-sharing an unchanged build returns that same link rather than a second one, and only a revoked link is replaced by a different one, because revocation is permanent: the address is burned and never resolves again. That makes `revokeUrl` the handle to the link you just made, so every share is also appended to `.extension.dev/shared-previews.json` in the project (gitignored) so it survives losing the tool output. The upload holds up to 2,000 files and about 64MB of text, or roughly 48MB when the build is mostly images, fonts or wasm, which travel base64-encoded. Without `share`, the tool returns a local-only deep link and uploads nothing.
308
308
 
309
309
  `extension_shares` is the other half of that: it lists every link the token has shared, live and dead, with the `previewUrl` and `revokeUrl` of each, and revokes one by `artifactId` or by pasting any of its URLs. Pass `projectPath` and it reconciles the platform's answer with the project's own record, so a link shared from another machine shows up as `remoteOnly` and a record with nothing behind it any more shows up under `localOnly`. It never rewrites the local file.
310
310
 
@@ -14,7 +14,7 @@ examples repo (GitHub)
14
14
  │
15
15
  ├── templates-meta.json Auto-generated registry (all templates, structured)
16
16
  │ Generated by: scripts/generate-templates-meta.mjs
17
- │ Published as: GitHub release asset (nightly tag)
17
+ │ Published at media.extension.land/templates/latest.json, with a pinned examples commit as fallback
18
18
  │ Contains: slug, surfaces, framework, permissions, files, downloads, integrity
19
19
  │ File paths are repo-relative: examples/<slug>/...
20
20
  │
@@ -24,19 +24,19 @@ examples repo (GitHub)
24
24
 
25
25
  ## Three integration layers
26
26
 
27
- ### Layer 1: sidebar-claude template
27
+ ### Layer 1: ai-claude template
28
28
 
29
- **Location:** `examples/sidebar-claude/`
29
+ **Location:** `examples/ai-claude/`
30
30
  **Role in ecosystem:** An example in the examples repo, discoverable like any other template.
31
31
 
32
32
  ```
33
33
  User: "Build me a Claude chatbot extension"
34
34
  │
35
35
  ▼
36
- npx extension create my-bot --template=sidebar-claude
36
+ npx extension create my-bot --template=ai-claude
37
37
  │
38
38
  ▼
39
- Resolves → https://github.com/extension-js/examples/tree/main/examples/sidebar-claude
39
+ Resolves → https://github.com/extension-js/examples/tree/main/examples/ai-claude
40
40
  │
41
41
  ▼
42
42
  go-git-it clones → copies to ./my-bot/ → installs deps → done
@@ -44,10 +44,10 @@ go-git-it clones → copies to ./my-bot/ → installs deps → done
44
44
 
45
45
  **How it integrates with the examples pipeline:**
46
46
 
47
- - `generate-templates-meta.mjs` auto-discovers it by scanning `examples/sidebar-claude/src/manifest.json`
47
+ - `generate-templates-meta.mjs` auto-discovers it by scanning `examples/ai-claude/src/manifest.json`
48
48
  - Auto-detects: `uiContext: ["sidebar", "background"]`, `uiFramework: "react"`, `surfaces: ["sidebar", "background"]`
49
49
  - Curated `template.meta.json` adds: featured flag, tags (ai, claude), difficulty, useCases, firstSteps
50
- - CI builds it for Chrome/Edge/Firefox, packages as `.zip`, publishes in nightly release
50
+ - CI builds it for Chrome/Edge/Firefox, packages as `.zip`, publishes it to media.extension.land
51
51
  - `templates-meta.json` includes download URLs with SHA256 integrity
52
52
 
53
53
  ### Layer 2: Claude Code rules (CLAUDE.md)
@@ -76,7 +76,7 @@ Claude now knows:
76
76
  - References `templates-meta.json` as the source of truth for template discovery
77
77
  - Documents the GitHub URL resolution pattern that `extension create` uses
78
78
  - Provides the `curl` command to fetch and query the catalog
79
- - Documents the nightly release download URL pattern for pre-built distributions
79
+ - Documents the download URL pattern for pre-built distributions
80
80
  - Teaches how to contribute new templates (template.meta.json format, generator script)
81
81
 
82
82
  ### Layer 3: MCP tools
@@ -91,19 +91,19 @@ Claude (via MCP) calls extension_templates({ surface: "sidebar", tags: ["ai"] })
91
91
  MCP server fetches templates-meta.json (cached, 1hr TTL)
92
92
  │
93
93
  ▼
94
- Returns: [{ slug: "sidebar-claude", ... }, { slug: "sidebar-transformers-js", ... }]
94
+ Returns: [{ slug: "ai-claude", ... }, { slug: "transformers-js", ... }]
95
95
  │
96
96
  ▼
97
- Claude calls extension_templates({ action: "source", slug: "sidebar-claude", files: ["src/manifest.json", "src/lib/claude.ts"] })
97
+ Claude calls extension_templates({ action: "source", slug: "ai-claude", files: ["src/manifest.json", "src/lib/client.ts"] })
98
98
  │
99
99
  ▼
100
- MCP server fetches from https://raw.githubusercontent.com/extension-js/examples/main/examples/sidebar-claude/<file>
100
+ MCP server fetches the file at the pinned examples commit
101
101
  │
102
102
  ▼
103
103
  Claude reads the source, understands the pattern, adapts it for the user
104
104
  │
105
105
  ▼
106
- Claude calls extension_create({ projectName: "my-bot", template: "sidebar-claude" })
106
+ Claude calls extension_create({ projectName: "my-bot", template: "ai-claude" })
107
107
  │
108
108
  ▼
109
109
  MCP server calls extensionCreate() → same go-git-it flow as CLI
@@ -151,7 +151,7 @@ MCP server calls extensionCreate() → same go-git-it flow as CLI
151
151
 
152
152
  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.
153
153
 
154
- 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.
154
+ 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 `ai-claude`) are immediately available to Claude without updating the MCP server.
155
155
 
156
156
  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.
157
157
 
package/claude/CLAUDE.md CHANGED
@@ -41,7 +41,7 @@ The extension.dev platform ships 50+ templates in the [examples](https://github.
41
41
 
42
42
  ```bash
43
43
  # The full catalog with metadata (framework, surfaces, permissions, etc.)
44
- curl -sL https://github.com/extension-js/examples/releases/download/nightly/templates-meta.json | jq '.templates[] | {slug, description, uiFramework, surfaces}'
44
+ curl -sL https://media.extension.land/templates/latest.json | jq '.templates[] | {slug, description, uiFramework, surfaces}'
45
45
  ```
46
46
 
47
47
  **Pre-built distributions** are available for every template:
@@ -121,7 +121,8 @@ npm run preview
121
121
 
122
122
  # Target a specific browser
123
123
  npm run dev -- --browser=firefox
124
- npm run build -- --browser=chrome,firefox
124
+ npm run build -- --browser=chrome
125
+ npm run build -- --browser=firefox
125
126
 
126
127
  # Zip for distribution
127
128
  npm run build -- --zip
@@ -200,13 +201,13 @@ The `extension_dom_snapshot` MCP tool wraps this verb one-to-one.
200
201
 
201
202
  **Debugging protocol (Chromium CDP): `extension_inspect` MCP tool.** Connects directly to the running session's debug port. Use it when the bridge is not enough: closed shadow roots (`deepDom`), selector probes, DOM snapshots, console summaries, or navigating the tab to a URL before inspecting. Returns structured events:
202
203
 
203
- - `page_html` - full injected HTML (after content scripts run)
204
- - `page_html_summary` - root/script/style/link counts
205
- - `page_meta` - readyState, viewport, frame count
206
- - `dom_snapshot` - structured tree (tag, id, classes, role, max 500 nodes)
207
- - `console_summary` - error/warn counts + top 5 unique messages
208
- - `selector_probe` - per-selector element counts and samples
209
- - `extension_root_tree` - extension root elements with reinject generations
204
+ - `html` - full injected HTML (after content scripts run), with `htmlTruncated` when cut
205
+ - `summary` - root/script/style/link counts
206
+ - `meta` - readyState, viewport, frame count
207
+ - `domSnapshot` - structured tree (tag, id, classes, role; `domSnapshotTruncated` names the cap)
208
+ - `console` - error/warn counts + top unique messages
209
+ - `probes` - per-selector element counts and samples
210
+ - `extensionRoots` - extension root elements with reinject generations
210
211
 
211
212
  ### Unified logging (`--logs`)
212
213
 
@@ -229,7 +230,7 @@ npm run dev -- --logs info --log-url "example.com"
229
230
  ### Other debugging tools
230
231
 
231
232
  - Use `--browser=firefox` to test cross-browser compatibility
232
- - **Safari (macOS).** On Extension.js 4.1.28 or newer, `--browser=safari` builds the app, opens it, and after you enable the extension in Safari > Settings > Extensions it reloads on every save through the extension's bridge and streams background and content lines into the session log. Start it with `allowEval: true` and the bridge tools work: `extension_storage`, `extension_reload`, `extension_open` for surfaces, `extension_dom_snapshot` by tab id, `extension_logs`, and the assertions except `surface-rendered`. `extension_eval` in `content` or `page` needs a tab already open at the url, which you open in Safari by hand: `extension_open` with `url` and `extension_eval` in `background` are blocked by Safari's MV3 background CSP, and the engine says so. Safari has no CDP or RDP, so `extension_inspect` has no Safari path. Apple's Safari MCP server (`claude mcp add safari-mcp -- "/usr/bin/safaridriver" --mcp`, Safari 27+, after enabling Safari > Settings > Developer > "Allow remote automation and external agents") reads a page in its own isolated window with no extension-aware tool, and runs beside a dev session, since this server opens no automation session of its own.
233
+ - **Safari (macOS).** On Extension.js 4.1.28 or newer, `--browser=safari` builds the app, opens it, and after you enable the extension in Safari > Settings > Extensions it reloads on every save through the extension's bridge and streams background and content lines into the session log. Start it with `allowEval: true` and the bridge tools work: `extension_storage`, `extension_reload`, `extension_open` for surfaces, `extension_dom_snapshot` by tab id, `extension_logs`, and the assertions (`surface-rendered` reads the surface through the relay there). `extension_eval` in `content` or `page` needs a tab already open at the url, which you open in Safari by hand: `extension_open` with `url` and `extension_eval` in `background` are blocked by Safari's MV3 background CSP, and the engine says so. Safari has no CDP or RDP, so `extension_inspect` has no Safari path. Apple's Safari MCP server (`claude mcp add safari-mcp -- "/usr/bin/safaridriver" --mcp`, Safari 27+, after enabling Safari > Settings > Developer > "Allow remote automation and external agents") reads a page in its own isolated window with no extension-aware tool, and runs beside a dev session, since this server opens no automation session of its own.
233
234
  - Check `dist/<browser>/` for build output
234
235
  - Use `--wait` flag to check if dev session is ready (outputs ready.json contract)
235
236
  - Use `npm run start` to test production builds (builds first, then launches)
package/claude/README.md CHANGED
@@ -12,13 +12,13 @@ claude/
12
12
  ARCHITECTURE.md How the template, CLAUDE.md, and MCP layers connect
13
13
  commands/
14
14
  extension.md /extension: create, dev, build, add features, debug
15
- extension-add.md /extension-add: add sidebar, popup, content script, etc.
15
+ extension-add.md /extension-add: plan a sidebar, popup, content script, etc. (the tool writes no files)
16
16
  extension-debug.md /extension-debug: live DOM/console inspection
17
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
21
- mcp-tools.md Full MCP tool specification and design doc
21
+ mcp-tools.md MCP tool reference, generated from the server's schemas (pnpm docs:tools)
22
22
  examples/
23
23
  create-extension.md Example prompt: scaffold and customize an extension
24
24
  add-sidebar.md Example prompt: add a sidebar panel to an existing extension
@@ -59,7 +59,7 @@ Claude Code will automatically pick up the instructions and know how to:
59
59
 
60
60
  ## How it connects to the examples repo
61
61
 
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:
62
+ The template catalog (`templates-meta.json`) is read from `media.extension.land/templates/latest.json` first and from a pinned commit of the [examples repo](https://github.com/extension-js/examples) as the fallback, with a bundled snapshot when neither answers. It is the single source of truth for:
63
63
 
64
64
  - **CLAUDE.md**, references it so Claude knows all available templates
65
65
  - **MCP tools**, `extension_templates` fetches and queries it at runtime
@@ -69,4 +69,4 @@ When a new template is added to the examples repo, all three layers pick it up a
69
69
 
70
70
  ## License
71
71
 
72
- MIT
72
+ Apache-2.0
@@ -33,7 +33,7 @@ Debug the currently running extension dev session. The user said: $ARGUMENTS
33
33
 
34
34
  To see what else is loaded in the browser (Chromium): `extension_list_extensions`.
35
35
 
36
- **Safari sessions** (Extension.js 4.1.28+) have no CDP, but the bridge works once the extension is enabled in Safari: `extension_logs`, `extension_storage`, `extension_reload`, `extension_open` for surfaces, `extension_dom_snapshot` by tab id, and the assertions except `surface-rendered`. `extension_eval` in `content` or `page` needs a tab the user already opened at the url; `extension_open` with `url` and `extension_eval` in `background` are blocked by Safari's MV3 background CSP. `extension_inspect` has no Safari path. Apple's `safari-mcp` can read a page in its own window beside the dev session; neither it nor this server can open the popup or background page, which stay Web Inspector, attended.
36
+ **Safari sessions** (Extension.js 4.1.28+) have no CDP, but the bridge works once the extension is enabled in Safari: `extension_logs`, `extension_storage`, `extension_reload`, `extension_open` for surfaces, `extension_dom_snapshot` by tab id, and the assertions (`surface-rendered` reads the surface through the relay there). `extension_eval` in `content` or `page` needs a tab the user already opened at the url; `extension_open` with `url` and `extension_eval` in `background` are blocked by Safari's MV3 background CSP. `extension_inspect` has no Safari path. Apple's `safari-mcp` can read a page in its own window beside the dev session; neither it nor this server can open the popup or background page, which stay Web Inspector, attended.
37
37
 
38
38
  4. **Diagnose common issues**
39
39
  Based on what you find, check for:
@@ -22,7 +22,7 @@ Default to `chrome` and `firefox`. `all` means chrome, firefox, edge and safari.
22
22
  - Firefox: a missing `browser_specific_settings.gecko.data_collection_permissions` declaration, which AMO now requires for new add-ons and updates
23
23
  - a bundle over 10 MB, source maps in the production build, missing 128px icon
24
24
 
25
- 4. **Pick the build to submit.** Store review runs from a build on extension.dev, not from local files. Call `extension_release_status` with `include: "releases"` to find the sha. If the user has not shipped this version yet, say so and offer `extension_publish` first.
25
+ 4. **Pick the build to submit.** Store review runs from a build on extension.dev, not from local files. Call `extension_release_status` with `include: ["releases"]` to find the sha. If no build of this version is listed, say so: a build comes from a push to the project's repository (the platform builds it), not from `extension_publish`, which only shares a build that already exists.
26
26
 
27
27
  5. **Rehearse.** Call `extension_submit` with the browsers and `buildSha`, leaving `dryRun` at its default (`true`). Show the per-store credential rows. A store whose credentials are not healthy is fixed in the extension.dev console (the response names the page); drop it from `browsers` or stop.
28
28
 
@@ -12,7 +12,7 @@ Parse the user's intent from `$ARGUMENTS` and execute the matching action:
12
12
  ### "create <name>" or "new <name>", Scaffold a new extension
13
13
 
14
14
  1. If MCP tool `extension_templates` is available, use it to find the best template matching the user's description (check for surface type, framework, and keywords)
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}'`
15
+ 2. If not, check the template catalog: `curl -sL https://media.extension.land/templates/latest.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
 
@@ -70,8 +70,8 @@ Older Firefox ignores the `chromium:world` field and runs in the default isolate
70
70
  ## API differences
71
71
 
72
72
  - Chromium: use `chrome.*` namespace for Chrome-specific APIs (sidePanel, etc.)
73
- - Firefox: use `browser.*` namespace (auto-polyfilled by the framework)
74
- - For cross-browser code: use `browser.*` when possible, the polyfill maps it to `chrome.*` on Chromium
73
+ - Firefox: `browser.*` is native; `chrome.*` also works there for most APIs
74
+ - For cross-browser code: the polyfill that maps `browser.*` to `chrome.*` on Chromium is on for `extension_dev` and `extension_start` by default and OFF for `extension_build` (pass `polyfill: true` to the build, or write `chrome.*` and check `typeof browser` yourself)
75
75
 
76
76
  ## Testing across browsers
77
77
 
@@ -82,5 +82,6 @@ npm run dev -- --browser=firefox
82
82
  npm run dev -- --browser=edge
83
83
 
84
84
  # Build for multiple browsers
85
- npm run build -- --browser=chrome,firefox
85
+ npm run build -- --browser=chrome
86
+ npm run build -- --browser=firefox
86
87
  ```